blob: 9913a8bc9ebaf4c76780ee302f52893af4b0918a [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";
439 node_names[(unsigned) SPUISD::VEC2PREFSLOT_CHAINED]
440 = "SPUISD::VEC2PREFSLOT_CHAINED";
Scott Michel8efdca42007-12-04 22:23:35 +0000441 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
442 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
443 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
444 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
445 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
446 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
447 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
448 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michel97872d32008-02-23 18:41:37 +0000449 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
450 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel8efdca42007-12-04 22:23:35 +0000451 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
452 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
453 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
454 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
455 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michel97872d32008-02-23 18:41:37 +0000456 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
457 "SPUISD::ROTQUAD_RZ_BYTES";
458 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
459 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel8efdca42007-12-04 22:23:35 +0000460 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
461 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
462 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel67224b22008-06-02 22:18:03 +0000463 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
464 "SPUISD::ROTBYTES_LEFT_BITS";
465 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000466 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel67224b22008-06-02 22:18:03 +0000467 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
468 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
469 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
470 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel8efdca42007-12-04 22:23:35 +0000471 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
472 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
473 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
474 }
475
476 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
477
478 return ((i != node_names.end()) ? i->second : 0);
479}
480
Dan Gohman8181bd12008-07-27 21:46:04 +0000481MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands92c43912008-06-06 12:08:01 +0000482 MVT VT = Op.getValueType();
Scott Michela313fb02008-10-30 01:51:48 +0000483 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel53ab7792008-03-10 16:58:52 +0000484}
485
Scott Michel8efdca42007-12-04 22:23:35 +0000486//===----------------------------------------------------------------------===//
487// Calling convention code:
488//===----------------------------------------------------------------------===//
489
490#include "SPUGenCallingConv.inc"
491
492//===----------------------------------------------------------------------===//
493// LowerOperation implementation
494//===----------------------------------------------------------------------===//
495
Scott Micheldbac4cf2008-01-11 02:53:15 +0000496/// Aligned load common code for CellSPU
497/*!
498 \param[in] Op The SelectionDAG load or store operand
499 \param[in] DAG The selection DAG
500 \param[in] ST CellSPU subtarget information structure
501 \param[in,out] alignment Caller initializes this to the load or store node's
502 value from getAlignment(), may be updated while generating the aligned load
503 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
504 offset (divisible by 16, modulo 16 == 0)
505 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
506 offset of the preferred slot (modulo 16 != 0)
507 \param[in,out] VT Caller initializes this value type to the the load or store
508 node's loaded or stored value type; may be updated if an i1-extended load or
509 store.
510 \param[out] was16aligned true if the base pointer had 16-byte alignment,
511 otherwise false. Can help to determine if the chunk needs to be rotated.
512
513 Both load and store lowering load a block of data aligned on a 16-byte
514 boundary. This is the common aligned load code shared between both.
515 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000516static SDValue
517AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Micheldbac4cf2008-01-11 02:53:15 +0000518 LSBaseSDNode *LSN,
519 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands92c43912008-06-06 12:08:01 +0000520 MVT &VT, bool &was16aligned)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000521{
Duncan Sands92c43912008-06-06 12:08:01 +0000522 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000523 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman8181bd12008-07-27 21:46:04 +0000524 SDValue basePtr = LSN->getBasePtr();
525 SDValue chain = LSN->getChain();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000526
527 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greif1c80d112008-08-28 21:40:38 +0000528 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000529
Gabor Greife9f7f582008-08-31 15:37:04 +0000530 if (Op1.getOpcode() == ISD::Constant
531 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel394e26d2008-01-17 20:38:41 +0000532 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000533
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000534 alignOffs = (int) CN->getZExtValue();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000535 prefSlotOffs = (int) (alignOffs & 0xf);
536
537 // Adjust the rotation amount to ensure that the final result ends up in
538 // the preferred slot:
539 prefSlotOffs -= vtm->prefslot_byte;
540 basePtr = basePtr.getOperand(0);
541
Scott Michel394e26d2008-01-17 20:38:41 +0000542 // Loading from memory, can we adjust alignment?
543 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000544 SDValue APtr = basePtr.getOperand(0);
Scott Michel394e26d2008-01-17 20:38:41 +0000545 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
546 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
547 alignment = GSDN->getGlobal()->getAlignment();
548 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000549 }
550 } else {
551 alignOffs = 0;
552 prefSlotOffs = -vtm->prefslot_byte;
553 }
Scott Michelbc5fbc12008-04-30 00:30:08 +0000554 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
555 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
556 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
557 prefSlotOffs = (int) (alignOffs & 0xf);
558 prefSlotOffs -= vtm->prefslot_byte;
559 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000560 } else {
561 alignOffs = 0;
562 prefSlotOffs = -vtm->prefslot_byte;
563 }
564
565 if (alignment == 16) {
566 // Realign the base pointer as a D-Form address:
567 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel394e26d2008-01-17 20:38:41 +0000568 basePtr = DAG.getNode(ISD::ADD, PtrVT,
569 basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000570 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000571 }
572
573 // Emit the vector load:
574 was16aligned = true;
575 return DAG.getLoad(MVT::v16i8, chain, basePtr,
576 LSN->getSrcValue(), LSN->getSrcValueOffset(),
577 LSN->isVolatile(), 16);
578 }
579
580 // Unaligned load or we're using the "large memory" model, which means that
581 // we have to be very pessimistic:
Scott Michel394e26d2008-01-17 20:38:41 +0000582 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greife9f7f582008-08-31 15:37:04 +0000583 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
584 DAG.getConstant(0, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000585 }
586
587 // Add the offset
Scott Michelf9f42e62008-01-29 02:16:57 +0000588 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000589 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000590 was16aligned = false;
591 return DAG.getLoad(MVT::v16i8, chain, basePtr,
592 LSN->getSrcValue(), LSN->getSrcValueOffset(),
593 LSN->isVolatile(), 16);
594}
595
Scott Michel8efdca42007-12-04 22:23:35 +0000596/// Custom lower loads for CellSPU
597/*!
598 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
599 within a 16-byte block, we have to rotate to extract the requested element.
600 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000601static SDValue
602LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000603 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000604 SDValue the_chain = LN->getChain();
Duncan Sands92c43912008-06-06 12:08:01 +0000605 MVT VT = LN->getMemoryVT();
Gabor Greif1c80d112008-08-28 21:40:38 +0000606 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000607 ISD::LoadExtType ExtType = LN->getExtensionType();
608 unsigned alignment = LN->getAlignment();
Dan Gohman8181bd12008-07-27 21:46:04 +0000609 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +0000610
Scott Michel8efdca42007-12-04 22:23:35 +0000611 switch (LN->getAddressingMode()) {
612 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000613 int offset, rotamt;
614 bool was16aligned;
Dan Gohman8181bd12008-07-27 21:46:04 +0000615 SDValue result =
Scott Micheldbac4cf2008-01-11 02:53:15 +0000616 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000617
Gabor Greif1c80d112008-08-28 21:40:38 +0000618 if (result.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +0000619 return result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000620
621 the_chain = result.getValue(1);
622 // Rotate the chunk if necessary
623 if (rotamt < 0)
624 rotamt += 16;
Scott Michelabc58242008-01-11 21:01:19 +0000625 if (rotamt != 0 || !was16aligned) {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000626 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
627
Scott Michel394e26d2008-01-17 20:38:41 +0000628 Ops[0] = the_chain;
629 Ops[1] = result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000630 if (was16aligned) {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000631 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
632 } else {
Duncan Sands92c43912008-06-06 12:08:01 +0000633 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000634 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michelabc58242008-01-11 21:01:19 +0000635 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel5a6f17b2008-01-30 02:55:46 +0000636 DAG.getConstant(rotamt, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000637 }
638
639 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
640 the_chain = result.getValue(1);
Scott Michel8efdca42007-12-04 22:23:35 +0000641 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000642
643 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
644 SDVTList scalarvts;
Duncan Sands92c43912008-06-06 12:08:01 +0000645 MVT vecVT = MVT::v16i8;
Scott Michel4ec722e2008-07-16 17:17:29 +0000646
Scott Micheldbac4cf2008-01-11 02:53:15 +0000647 // Convert the loaded v16i8 vector to the appropriate vector type
648 // specified by the operand:
649 if (OpVT == VT) {
650 if (VT != MVT::i1)
Duncan Sands92c43912008-06-06 12:08:01 +0000651 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000652 } else
Duncan Sands92c43912008-06-06 12:08:01 +0000653 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000654
655 Ops[0] = the_chain;
656 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
657 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
Scott Michelc630c412008-11-24 17:11:17 +0000658 result = DAG.getNode(SPUISD::VEC2PREFSLOT_CHAINED, scalarvts, Ops, 2);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000659 the_chain = result.getValue(1);
660 } else {
661 // Handle the sign and zero-extending loads for i1 and i8:
662 unsigned NewOpC;
663
664 if (ExtType == ISD::SEXTLOAD) {
665 NewOpC = (OpVT == MVT::i1
666 ? SPUISD::EXTRACT_I1_SEXT
667 : SPUISD::EXTRACT_I8_SEXT);
668 } else {
669 assert(ExtType == ISD::ZEXTLOAD);
670 NewOpC = (OpVT == MVT::i1
671 ? SPUISD::EXTRACT_I1_ZEXT
672 : SPUISD::EXTRACT_I8_ZEXT);
673 }
674
675 result = DAG.getNode(NewOpC, OpVT, result);
676 }
677
678 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman8181bd12008-07-27 21:46:04 +0000679 SDValue retops[2] = {
Scott Michel394e26d2008-01-17 20:38:41 +0000680 result,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000681 the_chain
Scott Michel394e26d2008-01-17 20:38:41 +0000682 };
Scott Micheldbac4cf2008-01-11 02:53:15 +0000683
Scott Michel394e26d2008-01-17 20:38:41 +0000684 result = DAG.getNode(SPUISD::LDRESULT, retvts,
685 retops, sizeof(retops) / sizeof(retops[0]));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000686 return result;
Scott Michel8efdca42007-12-04 22:23:35 +0000687 }
688 case ISD::PRE_INC:
689 case ISD::PRE_DEC:
690 case ISD::POST_INC:
691 case ISD::POST_DEC:
692 case ISD::LAST_INDEXED_MODE:
693 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
694 "UNINDEXED\n";
695 cerr << (unsigned) LN->getAddressingMode() << "\n";
696 abort();
697 /*NOTREACHED*/
698 }
699
Dan Gohman8181bd12008-07-27 21:46:04 +0000700 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000701}
702
703/// Custom lower stores for CellSPU
704/*!
705 All CellSPU stores are aligned to 16-byte boundaries, so for elements
706 within a 16-byte block, we have to generate a shuffle to insert the
707 requested element into its place, then store the resulting block.
708 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000709static SDValue
710LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000711 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000712 SDValue Value = SN->getValue();
Duncan Sands92c43912008-06-06 12:08:01 +0000713 MVT VT = Value.getValueType();
714 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
715 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000716 unsigned alignment = SN->getAlignment();
Scott Michel8efdca42007-12-04 22:23:35 +0000717
718 switch (SN->getAddressingMode()) {
719 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000720 int chunk_offset, slot_offset;
721 bool was16aligned;
Scott Michel8efdca42007-12-04 22:23:35 +0000722
Scott Michel33d73eb2008-11-21 02:56:16 +0000723 // The vector type we really want to load from the 16-byte chunk.
Scott Michele1006032008-11-19 17:45:08 +0000724 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
725 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +0000726
Dan Gohman8181bd12008-07-27 21:46:04 +0000727 SDValue alignLoadVec =
Scott Micheldbac4cf2008-01-11 02:53:15 +0000728 AlignedLoad(Op, DAG, ST, SN, alignment,
729 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000730
Gabor Greif1c80d112008-08-28 21:40:38 +0000731 if (alignLoadVec.getNode() == 0)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000732 return alignLoadVec;
Scott Michel8efdca42007-12-04 22:23:35 +0000733
Scott Micheldbac4cf2008-01-11 02:53:15 +0000734 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman8181bd12008-07-27 21:46:04 +0000735 SDValue basePtr = LN->getBasePtr();
736 SDValue the_chain = alignLoadVec.getValue(1);
737 SDValue theValue = SN->getValue();
738 SDValue result;
Scott Michel8efdca42007-12-04 22:23:35 +0000739
740 if (StVT != VT
Scott Michel5a6f17b2008-01-30 02:55:46 +0000741 && (theValue.getOpcode() == ISD::AssertZext
742 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel8efdca42007-12-04 22:23:35 +0000743 // Drill down and get the value for zero- and sign-extended
744 // quantities
Scott Michel4ec722e2008-07-16 17:17:29 +0000745 theValue = theValue.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000746 }
747
Scott Micheldbac4cf2008-01-11 02:53:15 +0000748 chunk_offset &= 0xf;
Scott Michel8efdca42007-12-04 22:23:35 +0000749
Dan Gohman8181bd12008-07-27 21:46:04 +0000750 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
751 SDValue insertEltPtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000752
753 // If the base pointer is already a D-form address, then just create
754 // a new D-form address with a slot offset and the orignal base pointer.
755 // Otherwise generate a D-form address with the slot offset relative
756 // to the stack pointer, which is always aligned.
Scott Michelabc58242008-01-11 21:01:19 +0000757 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greif1c80d112008-08-28 21:40:38 +0000758 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michelabc58242008-01-11 21:01:19 +0000759 DEBUG(cerr << "\n");
760
Scott Michelf9f42e62008-01-29 02:16:57 +0000761 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
762 (basePtr.getOpcode() == ISD::ADD
763 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michelabc58242008-01-11 21:01:19 +0000764 insertEltPtr = basePtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000765 } else {
Scott Michelf9f42e62008-01-29 02:16:57 +0000766 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000767 }
768
Scott Michelf65c8f02008-11-19 15:24:16 +0000769 SDValue insertEltOp =
Scott Michel0718cd82008-12-01 17:56:02 +0000770 DAG.getNode(SPUISD::SHUFFLE_MASK, vecVT, insertEltPtr);
Scott Michele1006032008-11-19 17:45:08 +0000771 SDValue vectorizeOp =
772 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michelf65c8f02008-11-19 15:24:16 +0000773
Scott Michel0718cd82008-12-01 17:56:02 +0000774 result = DAG.getNode(SPUISD::SHUFB, vecVT,
775 vectorizeOp, alignLoadVec,
776 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, insertEltOp));
Scott Michel8efdca42007-12-04 22:23:35 +0000777
Scott Micheldbac4cf2008-01-11 02:53:15 +0000778 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel8efdca42007-12-04 22:23:35 +0000779 LN->getSrcValue(), LN->getSrcValueOffset(),
780 LN->isVolatile(), LN->getAlignment());
781
Scott Michele1006032008-11-19 17:45:08 +0000782#if 0 && defined(NDEBUG)
Scott Michelf65c8f02008-11-19 15:24:16 +0000783 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
784 const SDValue &currentRoot = DAG.getRoot();
785
786 DAG.setRoot(result);
787 cerr << "------- CellSPU:LowerStore result:\n";
788 DAG.dump();
789 cerr << "-------\n";
790 DAG.setRoot(currentRoot);
791 }
792#endif
Scott Michelec8c82e2008-12-02 19:53:53 +0000793
Scott Michel8efdca42007-12-04 22:23:35 +0000794 return result;
795 /*UNREACHED*/
796 }
797 case ISD::PRE_INC:
798 case ISD::PRE_DEC:
799 case ISD::POST_INC:
800 case ISD::POST_DEC:
801 case ISD::LAST_INDEXED_MODE:
802 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
803 "UNINDEXED\n";
804 cerr << (unsigned) SN->getAddressingMode() << "\n";
805 abort();
806 /*NOTREACHED*/
807 }
808
Dan Gohman8181bd12008-07-27 21:46:04 +0000809 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000810}
811
812/// Generate the address of a constant pool entry.
Dan Gohman8181bd12008-07-27 21:46:04 +0000813static SDValue
814LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000815 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000816 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
817 Constant *C = CP->getConstVal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000818 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
819 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000820 const TargetMachine &TM = DAG.getTarget();
Scott Michel8efdca42007-12-04 22:23:35 +0000821
822 if (TM.getRelocationModel() == Reloc::Static) {
823 if (!ST->usingLargeMem()) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000824 // Just return the SDValue with the constant pool address in it.
Scott Michel394e26d2008-01-17 20:38:41 +0000825 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +0000826 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000827 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
828 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000829 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel8efdca42007-12-04 22:23:35 +0000830 }
831 }
832
833 assert(0 &&
Gabor Greife9f7f582008-08-31 15:37:04 +0000834 "LowerConstantPool: Relocation model other than static"
835 " not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000836 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000837}
838
Dan Gohman8181bd12008-07-27 21:46:04 +0000839static SDValue
840LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000841 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000842 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000843 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
844 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000845 const TargetMachine &TM = DAG.getTarget();
846
847 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel97872d32008-02-23 18:41:37 +0000848 if (!ST->usingLargeMem()) {
849 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
850 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000851 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
852 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000853 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
854 }
Scott Michel8efdca42007-12-04 22:23:35 +0000855 }
856
857 assert(0 &&
858 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000859 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000860}
861
Dan Gohman8181bd12008-07-27 21:46:04 +0000862static SDValue
863LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000864 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000865 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
866 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000867 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel8efdca42007-12-04 22:23:35 +0000868 const TargetMachine &TM = DAG.getTarget();
Dan Gohman8181bd12008-07-27 21:46:04 +0000869 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel4ec722e2008-07-16 17:17:29 +0000870
Scott Michel8efdca42007-12-04 22:23:35 +0000871 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michelf9f42e62008-01-29 02:16:57 +0000872 if (!ST->usingLargeMem()) {
873 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
874 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000875 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
876 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michelf9f42e62008-01-29 02:16:57 +0000877 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
878 }
Scott Michel8efdca42007-12-04 22:23:35 +0000879 } else {
880 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel5a6f17b2008-01-30 02:55:46 +0000881 << "supported.\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000882 abort();
883 /*NOTREACHED*/
884 }
885
Dan Gohman8181bd12008-07-27 21:46:04 +0000886 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000887}
888
889//! Custom lower i64 integer constants
890/*!
891 This code inserts all of the necessary juggling that needs to occur to load
892 a 64-bit constant into a register.
893 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000894static SDValue
895LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000896 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000897
898 if (VT == MVT::i64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000899 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
900 SDValue T = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michelc630c412008-11-24 17:11:17 +0000901 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000902 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +0000903 } else {
904 cerr << "LowerConstant: unhandled constant type "
Duncan Sands92c43912008-06-06 12:08:01 +0000905 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +0000906 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000907 abort();
908 /*NOTREACHED*/
909 }
910
Dan Gohman8181bd12008-07-27 21:46:04 +0000911 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000912}
913
Nate Begeman78125042008-02-14 18:43:04 +0000914//! Custom lower double precision floating point constants
Dan Gohman8181bd12008-07-27 21:46:04 +0000915static SDValue
916LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000917 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000918
Nate Begeman78125042008-02-14 18:43:04 +0000919 if (VT == MVT::f64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000920 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
921
922 assert((FP != 0) &&
923 "LowerConstantFP: Node is not ConstantFPSDNode");
924
Scott Michel11e88bb2007-12-19 20:15:47 +0000925 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel0718cd82008-12-01 17:56:02 +0000926 SDValue T = DAG.getConstant(dbits, MVT::i64);
927 SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T);
928 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
929 DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64, Tvec));
Scott Michel8efdca42007-12-04 22:23:35 +0000930 }
931
Dan Gohman8181bd12008-07-27 21:46:04 +0000932 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000933}
934
Scott Michel33d73eb2008-11-21 02:56:16 +0000935//! Lower MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman8181bd12008-07-27 21:46:04 +0000936static SDValue
937LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel394e26d2008-01-17 20:38:41 +0000938{
Dan Gohman8181bd12008-07-27 21:46:04 +0000939 SDValue Cond = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +0000940 MVT CondVT = Cond.getValueType();
941 MVT CondNVT;
Scott Michel394e26d2008-01-17 20:38:41 +0000942
Scott Michel33d73eb2008-11-21 02:56:16 +0000943 if (CondVT == MVT::i8) {
944 CondNVT = MVT::i16;
Scott Michel394e26d2008-01-17 20:38:41 +0000945 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
946 Op.getOperand(0),
947 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
948 Op.getOperand(2));
949 } else
Dan Gohman8181bd12008-07-27 21:46:04 +0000950 return SDValue(); // Unchanged
Scott Michel394e26d2008-01-17 20:38:41 +0000951}
952
Dan Gohman8181bd12008-07-27 21:46:04 +0000953static SDValue
954LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel8efdca42007-12-04 22:23:35 +0000955{
956 MachineFunction &MF = DAG.getMachineFunction();
957 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner1b989192007-12-31 04:13:23 +0000958 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michela313fb02008-10-30 01:51:48 +0000959 SmallVector<SDValue, 48> ArgValues;
Dan Gohman8181bd12008-07-27 21:46:04 +0000960 SDValue Root = Op.getOperand(0);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000961 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel8efdca42007-12-04 22:23:35 +0000962
963 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
964 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel4ec722e2008-07-16 17:17:29 +0000965
Scott Michel8efdca42007-12-04 22:23:35 +0000966 unsigned ArgOffset = SPUFrameInfo::minStackSize();
967 unsigned ArgRegIdx = 0;
968 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel4ec722e2008-07-16 17:17:29 +0000969
Duncan Sands92c43912008-06-06 12:08:01 +0000970 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +0000971
Scott Michel8efdca42007-12-04 22:23:35 +0000972 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greife9f7f582008-08-31 15:37:04 +0000973 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
974 ArgNo != e; ++ArgNo) {
Duncan Sands92c43912008-06-06 12:08:01 +0000975 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
976 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michela313fb02008-10-30 01:51:48 +0000977 SDValue ArgVal;
Scott Michel8efdca42007-12-04 22:23:35 +0000978
Scott Michela313fb02008-10-30 01:51:48 +0000979 if (ArgRegIdx < NumArgRegs) {
980 const TargetRegisterClass *ArgRegClass;
Scott Michel4ec722e2008-07-16 17:17:29 +0000981
Scott Michela313fb02008-10-30 01:51:48 +0000982 switch (ObjectVT.getSimpleVT()) {
983 default: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000984 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
985 << ObjectVT.getMVTString()
986 << "\n";
987 abort();
Scott Michela313fb02008-10-30 01:51:48 +0000988 }
989 case MVT::i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000990 ArgRegClass = &SPU::R8CRegClass;
991 break;
Scott Michela313fb02008-10-30 01:51:48 +0000992 case MVT::i16:
Scott Michel33d73eb2008-11-21 02:56:16 +0000993 ArgRegClass = &SPU::R16CRegClass;
994 break;
Scott Michela313fb02008-10-30 01:51:48 +0000995 case MVT::i32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000996 ArgRegClass = &SPU::R32CRegClass;
997 break;
Scott Michela313fb02008-10-30 01:51:48 +0000998 case MVT::i64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000999 ArgRegClass = &SPU::R64CRegClass;
1000 break;
Scott Michela313fb02008-10-30 01:51:48 +00001001 case MVT::f32:
Scott Michel33d73eb2008-11-21 02:56:16 +00001002 ArgRegClass = &SPU::R32FPRegClass;
1003 break;
Scott Michela313fb02008-10-30 01:51:48 +00001004 case MVT::f64:
Scott Michel33d73eb2008-11-21 02:56:16 +00001005 ArgRegClass = &SPU::R64FPRegClass;
1006 break;
Scott Michela313fb02008-10-30 01:51:48 +00001007 case MVT::v2f64:
1008 case MVT::v4f32:
1009 case MVT::v2i64:
1010 case MVT::v4i32:
1011 case MVT::v8i16:
1012 case MVT::v16i8:
Scott Michel33d73eb2008-11-21 02:56:16 +00001013 ArgRegClass = &SPU::VECREGRegClass;
1014 break;
Scott Michela313fb02008-10-30 01:51:48 +00001015 }
1016
1017 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
1018 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
1019 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1020 ++ArgRegIdx;
1021 } else {
1022 // We need to load the argument to a virtual register if we determined
1023 // above that we ran out of physical registers of the appropriate type
1024 // or we're forced to do vararg
Chris Lattner60069452008-02-13 07:35:30 +00001025 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +00001026 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner60069452008-02-13 07:35:30 +00001027 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +00001028 ArgOffset += StackSlotSize;
1029 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001030
Scott Michel8efdca42007-12-04 22:23:35 +00001031 ArgValues.push_back(ArgVal);
Scott Michela313fb02008-10-30 01:51:48 +00001032 // Update the chain
1033 Root = ArgVal.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001034 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001035
Scott Michela313fb02008-10-30 01:51:48 +00001036 // vararg handling:
Scott Michel8efdca42007-12-04 22:23:35 +00001037 if (isVarArg) {
Scott Michela313fb02008-10-30 01:51:48 +00001038 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1039 // We will spill (79-3)+1 registers to the stack
1040 SmallVector<SDValue, 79-3+1> MemOps;
1041
1042 // Create the frame slot
1043
Scott Michel8efdca42007-12-04 22:23:35 +00001044 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Michela313fb02008-10-30 01:51:48 +00001045 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1046 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1047 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1048 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1049 Root = Store.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001050 MemOps.push_back(Store);
Scott Michela313fb02008-10-30 01:51:48 +00001051
1052 // Increment address by stack slot size for the next stored argument
1053 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001054 }
1055 if (!MemOps.empty())
Scott Michela313fb02008-10-30 01:51:48 +00001056 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001057 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001058
Scott Michel8efdca42007-12-04 22:23:35 +00001059 ArgValues.push_back(Root);
Scott Michel4ec722e2008-07-16 17:17:29 +00001060
Scott Michel8efdca42007-12-04 22:23:35 +00001061 // Return the new list of results.
Duncan Sands42d7bb82008-12-01 11:41:29 +00001062 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
1063 &ArgValues[0], ArgValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001064}
1065
1066/// isLSAAddress - Return the immediate to use if the specified
1067/// value is representable as a LSA address.
Dan Gohman8181bd12008-07-27 21:46:04 +00001068static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel5974f432008-11-11 03:06:06 +00001069 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel8efdca42007-12-04 22:23:35 +00001070 if (!C) return 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001071
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001072 int Addr = C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001073 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1074 (Addr << 14 >> 14) != Addr)
1075 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel4ec722e2008-07-16 17:17:29 +00001076
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001077 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel8efdca42007-12-04 22:23:35 +00001078}
1079
1080static
Dan Gohman8181bd12008-07-27 21:46:04 +00001081SDValue
1082LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001083 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1084 SDValue Chain = TheCall->getChain();
Dan Gohman705e3f72008-09-13 01:54:27 +00001085 SDValue Callee = TheCall->getCallee();
1086 unsigned NumOps = TheCall->getNumArgs();
Scott Michel8efdca42007-12-04 22:23:35 +00001087 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1088 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1089 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1090
1091 // Handy pointer type
Duncan Sands92c43912008-06-06 12:08:01 +00001092 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +00001093
Scott Michel8efdca42007-12-04 22:23:35 +00001094 // Accumulate how many bytes are to be pushed on the stack, including the
1095 // linkage area, and parameter passing area. According to the SPU ABI,
1096 // we minimally need space for [LR] and [SP]
1097 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel4ec722e2008-07-16 17:17:29 +00001098
Scott Michel8efdca42007-12-04 22:23:35 +00001099 // Set up a copy of the stack pointer for use loading and storing any
1100 // arguments that may not fit in the registers available for argument
1101 // passing.
Dan Gohman8181bd12008-07-27 21:46:04 +00001102 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel4ec722e2008-07-16 17:17:29 +00001103
Scott Michel8efdca42007-12-04 22:23:35 +00001104 // Figure out which arguments are going to go in registers, and which in
1105 // memory.
1106 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1107 unsigned ArgRegIdx = 0;
1108
1109 // Keep track of registers passing arguments
Dan Gohman8181bd12008-07-27 21:46:04 +00001110 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel8efdca42007-12-04 22:23:35 +00001111 // And the arguments passed on the stack
Dan Gohman8181bd12008-07-27 21:46:04 +00001112 SmallVector<SDValue, 8> MemOpChains;
Scott Michel8efdca42007-12-04 22:23:35 +00001113
1114 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001115 SDValue Arg = TheCall->getArg(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001116
Scott Michel8efdca42007-12-04 22:23:35 +00001117 // PtrOff will be used to store the current argument to the stack if a
1118 // register cannot be found for it.
Dan Gohman8181bd12008-07-27 21:46:04 +00001119 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel8efdca42007-12-04 22:23:35 +00001120 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1121
Duncan Sands92c43912008-06-06 12:08:01 +00001122 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001123 default: assert(0 && "Unexpected ValueType for argument!");
1124 case MVT::i32:
1125 case MVT::i64:
1126 case MVT::i128:
1127 if (ArgRegIdx != NumArgRegs) {
1128 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1129 } else {
1130 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001131 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001132 }
1133 break;
1134 case MVT::f32:
1135 case MVT::f64:
1136 if (ArgRegIdx != NumArgRegs) {
1137 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1138 } else {
1139 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001140 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001141 }
1142 break;
1143 case MVT::v4f32:
1144 case MVT::v4i32:
1145 case MVT::v8i16:
1146 case MVT::v16i8:
1147 if (ArgRegIdx != NumArgRegs) {
1148 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1149 } else {
1150 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001151 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001152 }
1153 break;
1154 }
1155 }
1156
1157 // Update number of stack bytes actually used, insert a call sequence start
1158 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001159 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1160 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001161
1162 if (!MemOpChains.empty()) {
1163 // Adjust the stack pointer for the stack arguments.
1164 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1165 &MemOpChains[0], MemOpChains.size());
1166 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001167
Scott Michel8efdca42007-12-04 22:23:35 +00001168 // Build a sequence of copy-to-reg nodes chained together with token chain
1169 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001170 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001171 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1172 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1173 InFlag);
1174 InFlag = Chain.getValue(1);
1175 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001176
Dan Gohman8181bd12008-07-27 21:46:04 +00001177 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001178 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001179
Bill Wendlingfef06052008-09-16 21:48:12 +00001180 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1181 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1182 // node so that legalize doesn't hack it.
Scott Michel5974f432008-11-11 03:06:06 +00001183 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001184 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001185 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001186 SDValue Zero = DAG.getConstant(0, PtrVT);
1187 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001188
Scott Micheldbac4cf2008-01-11 02:53:15 +00001189 if (!ST->usingLargeMem()) {
1190 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1191 // style calls, otherwise, external symbols are BRASL calls. This assumes
1192 // that declared/defined symbols are in the same compilation unit and can
1193 // be reached through PC-relative jumps.
1194 //
1195 // NOTE:
1196 // This may be an unsafe assumption for JIT and really large compilation
1197 // units.
1198 if (GV->isDeclaration()) {
1199 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1200 } else {
1201 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1202 }
Scott Michel8efdca42007-12-04 22:23:35 +00001203 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001204 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1205 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001206 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001207 }
Scott Michel5974f432008-11-11 03:06:06 +00001208 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendlingfef06052008-09-16 21:48:12 +00001209 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Micheldbac4cf2008-01-11 02:53:15 +00001210 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001211 // If this is an absolute destination address that appears to be a legal
1212 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001213 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001214 }
Scott Michel8efdca42007-12-04 22:23:35 +00001215
1216 Ops.push_back(Chain);
1217 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001218
Scott Michel8efdca42007-12-04 22:23:35 +00001219 // Add argument registers to the end of the list so that they are known live
1220 // into the call.
1221 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001222 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001223 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001224
Gabor Greif1c80d112008-08-28 21:40:38 +00001225 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001226 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001227 // Returns a chain and a flag for retval copy to use.
1228 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1229 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001230 InFlag = Chain.getValue(1);
1231
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001232 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1233 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001234 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001235 InFlag = Chain.getValue(1);
1236
Dan Gohman8181bd12008-07-27 21:46:04 +00001237 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001238 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001239
Scott Michel8efdca42007-12-04 22:23:35 +00001240 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001241 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001242 default: assert(0 && "Unexpected ret value!");
1243 case MVT::Other: break;
1244 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001245 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001246 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1247 ResultVals[0] = Chain.getValue(0);
1248 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1249 Chain.getValue(2)).getValue(1);
1250 ResultVals[1] = Chain.getValue(0);
1251 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001252 } else {
1253 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1254 ResultVals[0] = Chain.getValue(0);
1255 NumResults = 1;
1256 }
Scott Michel8efdca42007-12-04 22:23:35 +00001257 break;
1258 case MVT::i64:
1259 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1260 ResultVals[0] = Chain.getValue(0);
1261 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001262 break;
1263 case MVT::f32:
1264 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001265 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001266 InFlag).getValue(1);
1267 ResultVals[0] = Chain.getValue(0);
1268 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001269 break;
1270 case MVT::v2f64:
1271 case MVT::v4f32:
1272 case MVT::v4i32:
1273 case MVT::v8i16:
1274 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001275 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001276 InFlag).getValue(1);
1277 ResultVals[0] = Chain.getValue(0);
1278 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001279 break;
1280 }
Duncan Sands698842f2008-07-02 17:40:58 +00001281
Scott Michel8efdca42007-12-04 22:23:35 +00001282 // If the function returns void, just return the chain.
1283 if (NumResults == 0)
1284 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001285
Scott Michel8efdca42007-12-04 22:23:35 +00001286 // Otherwise, merge everything together with a MERGE_VALUES node.
1287 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001288 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001289 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001290}
1291
Dan Gohman8181bd12008-07-27 21:46:04 +00001292static SDValue
1293LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001294 SmallVector<CCValAssign, 16> RVLocs;
1295 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1296 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1297 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001298 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001299
Scott Michel8efdca42007-12-04 22:23:35 +00001300 // If this is the first return lowered for this function, add the regs to the
1301 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001302 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001303 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001304 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001305 }
1306
Dan Gohman8181bd12008-07-27 21:46:04 +00001307 SDValue Chain = Op.getOperand(0);
1308 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001309
Scott Michel8efdca42007-12-04 22:23:35 +00001310 // Copy the result values into the output registers.
1311 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1312 CCValAssign &VA = RVLocs[i];
1313 assert(VA.isRegLoc() && "Can only return in registers!");
1314 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1315 Flag = Chain.getValue(1);
1316 }
1317
Gabor Greif1c80d112008-08-28 21:40:38 +00001318 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001319 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1320 else
1321 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1322}
1323
1324
1325//===----------------------------------------------------------------------===//
1326// Vector related lowering:
1327//===----------------------------------------------------------------------===//
1328
1329static ConstantSDNode *
1330getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001331 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001332
Scott Michel8efdca42007-12-04 22:23:35 +00001333 // Check to see if this buildvec has a single non-undef value in its elements.
1334 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1335 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001336 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001337 OpVal = N->getOperand(i);
1338 else if (OpVal != N->getOperand(i))
1339 return 0;
1340 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001341
Gabor Greif1c80d112008-08-28 21:40:38 +00001342 if (OpVal.getNode() != 0) {
Scott Michel5974f432008-11-11 03:06:06 +00001343 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001344 return CN;
1345 }
1346 }
1347
1348 return 0; // All UNDEF: use implicit def.; not Constant node
1349}
1350
1351/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1352/// and the value fits into an unsigned 18-bit constant, and if so, return the
1353/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001354SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001355 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001356 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001357 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001358 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001359 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001360 uint32_t upper = uint32_t(UValue >> 32);
1361 uint32_t lower = uint32_t(UValue);
1362 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001363 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001364 Value = Value >> 32;
1365 }
Scott Michel8efdca42007-12-04 22:23:35 +00001366 if (Value <= 0x3ffff)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001367 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001368 }
1369
Dan Gohman8181bd12008-07-27 21:46:04 +00001370 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001371}
1372
1373/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1374/// and the value fits into a signed 16-bit constant, and if so, return the
1375/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001376SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001377 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001378 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001379 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001380 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001381 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001382 uint32_t upper = uint32_t(UValue >> 32);
1383 uint32_t lower = uint32_t(UValue);
1384 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001385 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001386 Value = Value >> 32;
1387 }
Scott Michel6baba072008-03-05 23:02:02 +00001388 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001389 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001390 }
1391 }
1392
Dan Gohman8181bd12008-07-27 21:46:04 +00001393 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001394}
1395
1396/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1397/// and the value fits into a signed 10-bit constant, and if so, return the
1398/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001399SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001400 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001401 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001402 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001403 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001404 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001405 uint32_t upper = uint32_t(UValue >> 32);
1406 uint32_t lower = uint32_t(UValue);
1407 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001408 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001409 Value = Value >> 32;
1410 }
Scott Michel6baba072008-03-05 23:02:02 +00001411 if (isS10Constant(Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001412 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001413 }
1414
Dan Gohman8181bd12008-07-27 21:46:04 +00001415 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001416}
1417
1418/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1419/// and the value fits into a signed 8-bit constant, and if so, return the
1420/// constant.
1421///
1422/// @note: The incoming vector is v16i8 because that's the only way we can load
1423/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1424/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001425SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001426 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001427 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001428 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001429 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001430 && Value <= 0xffff /* truncated from uint64_t */
1431 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001432 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001433 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001434 && (Value & 0xff) == Value)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001435 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001436 }
1437
Dan Gohman8181bd12008-07-27 21:46:04 +00001438 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001439}
1440
1441/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1442/// and the value fits into a signed 16-bit constant, and if so, return the
1443/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001444SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001445 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001446 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001447 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001448 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001449 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1450 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001451 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001452 }
1453
Dan Gohman8181bd12008-07-27 21:46:04 +00001454 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001455}
1456
1457/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001458SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001459 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001460 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001461 }
1462
Dan Gohman8181bd12008-07-27 21:46:04 +00001463 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001464}
1465
1466/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001467SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001468 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001469 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001470 }
1471
Dan Gohman8181bd12008-07-27 21:46:04 +00001472 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001473}
1474
1475// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001476// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001477// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1478// zero. Return true if this is not an array of constants, false if it is.
1479//
1480static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1481 uint64_t UndefBits[2]) {
1482 // Start with zero'd results.
1483 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001484
Duncan Sands92c43912008-06-06 12:08:01 +00001485 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001486 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001487 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001488
Scott Michel8efdca42007-12-04 22:23:35 +00001489 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1490 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1491
1492 uint64_t EltBits = 0;
1493 if (OpVal.getOpcode() == ISD::UNDEF) {
1494 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1495 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1496 continue;
Scott Michel5974f432008-11-11 03:06:06 +00001497 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001498 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel5974f432008-11-11 03:06:06 +00001499 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001500 const APFloat &apf = CN->getValueAPF();
1501 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001502 ? FloatToBits(apf.convertToFloat())
1503 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001504 } else {
1505 // Nonconstant element.
1506 return true;
1507 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001508
Scott Michel8efdca42007-12-04 22:23:35 +00001509 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1510 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001511
1512 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001513 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1514 return false;
1515}
1516
1517/// If this is a splat (repetition) of a value across the whole vector, return
1518/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001519/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001520/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001521static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001522 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001523 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001524 uint64_t &SplatBits, uint64_t &SplatUndef,
1525 int &SplatSize) {
1526 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1527 // the same as the lower 64-bits, ignoring undefs.
1528 uint64_t Bits64 = Bits128[0] | Bits128[1];
1529 uint64_t Undef64 = Undef128[0] & Undef128[1];
1530 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1531 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1532 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1533 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1534
1535 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1536 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001537
Scott Michel8efdca42007-12-04 22:23:35 +00001538 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1539 // undefs.
1540 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001541 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001542
Scott Michel5a6f17b2008-01-30 02:55:46 +00001543 // If the top 16-bits are different than the lower 16-bits, ignoring
1544 // undefs, we have an i32 splat.
1545 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1546 if (MinSplatBits < 16) {
1547 // If the top 8-bits are different than the lower 8-bits, ignoring
1548 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001549 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1550 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001551 // Otherwise, we have an 8-bit splat.
1552 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1553 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1554 SplatSize = 1;
1555 return true;
1556 }
1557 } else {
1558 SplatBits = Bits16;
1559 SplatUndef = Undef16;
1560 SplatSize = 2;
1561 return true;
1562 }
1563 }
1564 } else {
1565 SplatBits = Bits32;
1566 SplatUndef = Undef32;
1567 SplatSize = 4;
1568 return true;
1569 }
Scott Michel8efdca42007-12-04 22:23:35 +00001570 }
1571 } else {
1572 SplatBits = Bits128[0];
1573 SplatUndef = Undef128[0];
1574 SplatSize = 8;
1575 return true;
1576 }
1577 }
1578
1579 return false; // Can't be a splat if two pieces don't match.
1580}
1581
1582// If this is a case we can't handle, return null and let the default
1583// expansion code take care of it. If we CAN select this case, and if it
1584// selects to a single instruction, return Op. Otherwise, if we can codegen
1585// this case more efficiently than a constant pool load, lower it to the
1586// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001587static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001588 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001589 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001590 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001591 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001592 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001593 uint64_t VectorBits[2];
1594 uint64_t UndefBits[2];
1595 uint64_t SplatBits, SplatUndef;
1596 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001597 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001598 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001599 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001600 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001601 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001602
Duncan Sands92c43912008-06-06 12:08:01 +00001603 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001604 default:
1605 case MVT::v4f32: {
1606 uint32_t Value32 = SplatBits;
1607 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001608 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001609 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001610 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001611 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001612 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001613 break;
1614 }
1615 case MVT::v2f64: {
1616 uint64_t f64val = SplatBits;
1617 assert(SplatSize == 8
Scott Michelc630c412008-11-24 17:11:17 +00001618 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel8efdca42007-12-04 22:23:35 +00001619 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001620 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001621 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001622 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001623 break;
1624 }
1625 case MVT::v16i8: {
1626 // 8-bit constants have to be expanded to 16-bits
1627 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001628 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001629 for (int i = 0; i < 8; ++i)
1630 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1631 return DAG.getNode(ISD::BIT_CONVERT, VT,
1632 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1633 }
1634 case MVT::v8i16: {
1635 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001636 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001637 Value16 = (unsigned short) (SplatBits & 0xffff);
1638 else
1639 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001640 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1641 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001642 for (int i = 0; i < 8; ++i) Ops[i] = T;
1643 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1644 }
1645 case MVT::v4i32: {
1646 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001647 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001648 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1649 }
1650 case MVT::v2i64: {
1651 uint64_t val = SplatBits;
1652 uint32_t upper = uint32_t(val >> 32);
1653 uint32_t lower = uint32_t(val);
1654
Scott Michelbcc7b672008-03-06 04:02:54 +00001655 if (upper == lower) {
1656 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001657 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001658 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001659 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001660 SDValue LO32;
1661 SDValue HI32;
1662 SmallVector<SDValue, 16> ShufBytes;
1663 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001664 bool upper_special, lower_special;
1665
1666 // NOTE: This code creates common-case shuffle masks that can be easily
1667 // detected as common expressions. It is not attempting to create highly
1668 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1669
1670 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michelc630c412008-11-24 17:11:17 +00001671 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1672 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel8efdca42007-12-04 22:23:35 +00001673
1674 // Create lower vector if not a special pattern
1675 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001676 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001677 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1678 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1679 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001680 }
1681
1682 // Create upper vector if not a special pattern
1683 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001684 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001685 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1686 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1687 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001688 }
1689
1690 // If either upper or lower are special, then the two input operands are
1691 // the same (basically, one of them is a "don't care")
1692 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001693 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001694 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001695 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001696 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001697 // Unhappy situation... both upper and lower are special, so punt with
1698 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001699 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001700 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001701 Zero, Zero);
1702 }
1703
1704 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001705 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001706 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001707 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001708 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001709 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001710 process_upper = (upper_special && (i & 1) == 0);
1711 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001712
Scott Michel5a6f17b2008-01-30 02:55:46 +00001713 if (process_upper || process_lower) {
1714 if ((process_upper && upper == 0)
1715 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001716 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001717 else if ((process_upper && upper == 0xffffffff)
1718 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001719 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001720 else if ((process_upper && upper == 0x80000000)
1721 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001722 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001723 } else
Scott Michel67224b22008-06-02 22:18:03 +00001724 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001725 }
Scott Michel67224b22008-06-02 22:18:03 +00001726
1727 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001728 }
1729
1730 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001731 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001732 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001733 }
1734 }
1735 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001736
Dan Gohman8181bd12008-07-27 21:46:04 +00001737 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001738}
1739
1740/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1741/// which the Cell can operate. The code inspects V3 to ascertain whether the
1742/// permutation vector, V3, is monotonically increasing with one "exception"
1743/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel56a125e2008-11-22 23:50:42 +00001744/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel8efdca42007-12-04 22:23:35 +00001745/// In either case, the net result is going to eventually invoke SHUFB to
1746/// permute/shuffle the bytes from V1 and V2.
1747/// \note
Scott Michel56a125e2008-11-22 23:50:42 +00001748/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel8efdca42007-12-04 22:23:35 +00001749/// control word for byte/halfword/word insertion. This takes care of a single
1750/// element move from V2 into V1.
1751/// \note
1752/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001753static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1754 SDValue V1 = Op.getOperand(0);
1755 SDValue V2 = Op.getOperand(1);
1756 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001757
Scott Michel8efdca42007-12-04 22:23:35 +00001758 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001759
Scott Michel8efdca42007-12-04 22:23:35 +00001760 // If we have a single element being moved from V1 to V2, this can be handled
1761 // using the C*[DX] compute mask instructions, but the vector elements have
1762 // to be monotonically increasing with one exception element.
Duncan Sands92c43912008-06-06 12:08:01 +00001763 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001764 unsigned EltsFromV2 = 0;
1765 unsigned V2Elt = 0;
1766 unsigned V2EltIdx0 = 0;
1767 unsigned CurrElt = 0;
1768 bool monotonic = true;
1769 if (EltVT == MVT::i8)
1770 V2EltIdx0 = 16;
1771 else if (EltVT == MVT::i16)
1772 V2EltIdx0 = 8;
1773 else if (EltVT == MVT::i32)
1774 V2EltIdx0 = 4;
1775 else
1776 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1777
1778 for (unsigned i = 0, e = PermMask.getNumOperands();
1779 EltsFromV2 <= 1 && monotonic && i != e;
1780 ++i) {
1781 unsigned SrcElt;
1782 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1783 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001784 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001785 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001786
1787 if (SrcElt >= V2EltIdx0) {
1788 ++EltsFromV2;
1789 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1790 } else if (CurrElt != SrcElt) {
1791 monotonic = false;
1792 }
1793
1794 ++CurrElt;
1795 }
1796
1797 if (EltsFromV2 == 1 && monotonic) {
1798 // Compute mask and shuffle
1799 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001800 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1801 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001802 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001803 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001804 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001805 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel56a125e2008-11-22 23:50:42 +00001806 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001807 SDValue ShufMaskOp =
Scott Michel0718cd82008-12-01 17:56:02 +00001808 DAG.getNode(SPUISD::SHUFFLE_MASK, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001809 DAG.getTargetConstant(V2Elt, MVT::i32),
1810 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001811 // Use shuffle mask in SHUFB synthetic instruction:
1812 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1813 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001814 // Convert the SHUFFLE_VECTOR mask's input element units to the
1815 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001816 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001817
Dan Gohman8181bd12008-07-27 21:46:04 +00001818 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001819 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1820 unsigned SrcElt;
1821 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001822 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001823 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001824 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001825
Scott Michel97872d32008-02-23 18:41:37 +00001826 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001827 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1828 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001829 }
1830 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001831
Dan Gohman8181bd12008-07-27 21:46:04 +00001832 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel0718cd82008-12-01 17:56:02 +00001833 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001834 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1835 }
1836}
1837
Dan Gohman8181bd12008-07-27 21:46:04 +00001838static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1839 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001840
Gabor Greif1c80d112008-08-28 21:40:38 +00001841 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001842 // For a constant, build the appropriate constant vector, which will
1843 // eventually simplify to a vector register load.
1844
Gabor Greif1c80d112008-08-28 21:40:38 +00001845 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001846 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001847 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001848 size_t n_copies;
1849
1850 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001851 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001852 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001853 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001854 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1855 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1856 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1857 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1858 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1859 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1860 }
1861
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001862 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001863 for (size_t j = 0; j < n_copies; ++j)
1864 ConstVecValues.push_back(CValue);
1865
1866 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001867 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001868 } else {
1869 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001870 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001871 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1872 case MVT::i8:
1873 case MVT::i16:
1874 case MVT::i32:
1875 case MVT::i64:
1876 case MVT::f32:
1877 case MVT::f64:
1878 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1879 }
1880 }
1881
Dan Gohman8181bd12008-07-27 21:46:04 +00001882 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001883}
1884
Dan Gohman8181bd12008-07-27 21:46:04 +00001885static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001886 switch (Op.getValueType().getSimpleVT()) {
1887 default:
1888 cerr << "CellSPU: Unknown vector multiplication, got "
1889 << Op.getValueType().getMVTString()
1890 << "\n";
1891 abort();
1892 /*NOTREACHED*/
1893
Scott Michel8efdca42007-12-04 22:23:35 +00001894 case MVT::v4i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001895 SDValue rA = Op.getOperand(0);
1896 SDValue rB = Op.getOperand(1);
1897 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1898 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1899 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1900 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel8efdca42007-12-04 22:23:35 +00001901
1902 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1903 break;
1904 }
1905
1906 // Multiply two v8i16 vectors (pipeline friendly version):
1907 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1908 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1909 // c) Use SELB to select upper and lower halves from the intermediate results
1910 //
Scott Michel67224b22008-06-02 22:18:03 +00001911 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel8efdca42007-12-04 22:23:35 +00001912 // dual-issue. This code does manage to do this, even if it's a little on
1913 // the wacky side
1914 case MVT::v8i16: {
1915 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001916 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman8181bd12008-07-27 21:46:04 +00001917 SDValue Chain = Op.getOperand(0);
1918 SDValue rA = Op.getOperand(0);
1919 SDValue rB = Op.getOperand(1);
Chris Lattner1b989192007-12-31 04:13:23 +00001920 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1921 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00001922
Dan Gohman8181bd12008-07-27 21:46:04 +00001923 SDValue FSMBOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001924 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel67224b22008-06-02 22:18:03 +00001925 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001926 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel8efdca42007-12-04 22:23:35 +00001927
Dan Gohman8181bd12008-07-27 21:46:04 +00001928 SDValue HHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001929 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001930 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001931
Dan Gohman8181bd12008-07-27 21:46:04 +00001932 SDValue HHProd_v4i32 =
Scott Michel8efdca42007-12-04 22:23:35 +00001933 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001934 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001935
1936 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001937 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1938 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1939 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1940 HHProd_v4i32,
1941 DAG.getConstant(16, MVT::i16))),
1942 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001943 }
1944
1945 // This M00sE is N@stI! (apologies to Monty Python)
1946 //
1947 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1948 // is to break it all apart, sign extend, and reassemble the various
1949 // intermediate products.
1950 case MVT::v16i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001951 SDValue rA = Op.getOperand(0);
1952 SDValue rB = Op.getOperand(1);
1953 SDValue c8 = DAG.getConstant(8, MVT::i32);
1954 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001955
Dan Gohman8181bd12008-07-27 21:46:04 +00001956 SDValue LLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001957 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001958 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1959 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001960
Dan Gohman8181bd12008-07-27 21:46:04 +00001961 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001962
Dan Gohman8181bd12008-07-27 21:46:04 +00001963 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001964
Dan Gohman8181bd12008-07-27 21:46:04 +00001965 SDValue LHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001966 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001967 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001968
Dan Gohman8181bd12008-07-27 21:46:04 +00001969 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001970 DAG.getConstant(0x2222, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001971
Dan Gohman8181bd12008-07-27 21:46:04 +00001972 SDValue LoProdParts =
Scott Michel97872d32008-02-23 18:41:37 +00001973 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1974 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1975 LLProd, LHProd, FSMBmask));
Scott Michel8efdca42007-12-04 22:23:35 +00001976
Dan Gohman8181bd12008-07-27 21:46:04 +00001977 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001978
Dan Gohman8181bd12008-07-27 21:46:04 +00001979 SDValue LoProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001980 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michel97872d32008-02-23 18:41:37 +00001981 LoProdParts,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001982 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1983 LoProdMask, LoProdMask,
1984 LoProdMask, LoProdMask));
Scott Michel8efdca42007-12-04 22:23:35 +00001985
Dan Gohman8181bd12008-07-27 21:46:04 +00001986 SDValue rAH =
Scott Michel8efdca42007-12-04 22:23:35 +00001987 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001988 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001989
Dan Gohman8181bd12008-07-27 21:46:04 +00001990 SDValue rBH =
Scott Michel8efdca42007-12-04 22:23:35 +00001991 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001992 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001993
Dan Gohman8181bd12008-07-27 21:46:04 +00001994 SDValue HLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001995 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001996 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1997 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel8efdca42007-12-04 22:23:35 +00001998
Dan Gohman8181bd12008-07-27 21:46:04 +00001999 SDValue HHProd_1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002000 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002001 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00002002 DAG.getNode(SPUISD::VEC_SRA,
2003 MVT::v4i32, rAH, c8)),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002004 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00002005 DAG.getNode(SPUISD::VEC_SRA,
2006 MVT::v4i32, rBH, c8)));
Scott Michel8efdca42007-12-04 22:23:35 +00002007
Dan Gohman8181bd12008-07-27 21:46:04 +00002008 SDValue HHProd =
Scott Michel97872d32008-02-23 18:41:37 +00002009 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2010 HLProd,
2011 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2012 FSMBmask);
Scott Michel8efdca42007-12-04 22:23:35 +00002013
Dan Gohman8181bd12008-07-27 21:46:04 +00002014 SDValue HiProd =
Scott Michel97872d32008-02-23 18:41:37 +00002015 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002016
2017 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002018 DAG.getNode(ISD::OR, MVT::v4i32,
2019 LoProd, HiProd));
Scott Michel8efdca42007-12-04 22:23:35 +00002020 }
Scott Michel8efdca42007-12-04 22:23:35 +00002021 }
2022
Dan Gohman8181bd12008-07-27 21:46:04 +00002023 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002024}
2025
Dan Gohman8181bd12008-07-27 21:46:04 +00002026static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00002027 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002028 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002029
Dan Gohman8181bd12008-07-27 21:46:04 +00002030 SDValue A = Op.getOperand(0);
2031 SDValue B = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002032 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002033
2034 unsigned VRegBR, VRegC;
2035
2036 if (VT == MVT::f32) {
Chris Lattner1b989192007-12-31 04:13:23 +00002037 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2038 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002039 } else {
Chris Lattner1b989192007-12-31 04:13:23 +00002040 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2041 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002042 }
2043 // TODO: make sure we're feeding FPInterp the right arguments
2044 // Right now: fi B, frest(B)
2045
2046 // Computes BRcpl =
2047 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman8181bd12008-07-27 21:46:04 +00002048 SDValue BRcpl =
Scott Michel4ec722e2008-07-16 17:17:29 +00002049 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2050 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002051 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002052
Scott Michel8efdca42007-12-04 22:23:35 +00002053 // Computes A * BRcpl and stores in a temporary register
Dan Gohman8181bd12008-07-27 21:46:04 +00002054 SDValue AxBRcpl =
Scott Michel8efdca42007-12-04 22:23:35 +00002055 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel4ec722e2008-07-16 17:17:29 +00002056 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002057 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel8efdca42007-12-04 22:23:35 +00002058 // What's the Chain variable do? It's magic!
2059 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel4ec722e2008-07-16 17:17:29 +00002060
2061 return DAG.getNode(ISD::FADD, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002062 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel4ec722e2008-07-16 17:17:29 +00002063 DAG.getNode(ISD::FMUL, VT,
2064 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002065 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel4ec722e2008-07-16 17:17:29 +00002066 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002067 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel8efdca42007-12-04 22:23:35 +00002068}
2069
Dan Gohman8181bd12008-07-27 21:46:04 +00002070static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002071 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002072 SDValue N = Op.getOperand(0);
2073 SDValue Elt = Op.getOperand(1);
Scott Michel56a125e2008-11-22 23:50:42 +00002074 SDValue retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002075
Scott Michel56a125e2008-11-22 23:50:42 +00002076 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2077 // Constant argument:
2078 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002079
Scott Michel56a125e2008-11-22 23:50:42 +00002080 // sanity checks:
2081 if (VT == MVT::i8 && EltNo >= 16)
2082 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2083 else if (VT == MVT::i16 && EltNo >= 8)
2084 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2085 else if (VT == MVT::i32 && EltNo >= 4)
2086 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2087 else if (VT == MVT::i64 && EltNo >= 2)
2088 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel8efdca42007-12-04 22:23:35 +00002089
Scott Michel56a125e2008-11-22 23:50:42 +00002090 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2091 // i32 and i64: Element 0 is the preferred slot
Scott Michelc630c412008-11-24 17:11:17 +00002092 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel56a125e2008-11-22 23:50:42 +00002093 }
Scott Michel8efdca42007-12-04 22:23:35 +00002094
Scott Michel56a125e2008-11-22 23:50:42 +00002095 // Need to generate shuffle mask and extract:
2096 int prefslot_begin = -1, prefslot_end = -1;
2097 int elt_byte = EltNo * VT.getSizeInBits() / 8;
2098
2099 switch (VT.getSimpleVT()) {
2100 default:
2101 assert(false && "Invalid value type!");
2102 case MVT::i8: {
2103 prefslot_begin = prefslot_end = 3;
2104 break;
2105 }
2106 case MVT::i16: {
2107 prefslot_begin = 2; prefslot_end = 3;
2108 break;
2109 }
2110 case MVT::i32:
2111 case MVT::f32: {
2112 prefslot_begin = 0; prefslot_end = 3;
2113 break;
2114 }
2115 case MVT::i64:
2116 case MVT::f64: {
2117 prefslot_begin = 0; prefslot_end = 7;
2118 break;
2119 }
2120 }
2121
2122 assert(prefslot_begin != -1 && prefslot_end != -1 &&
2123 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2124
2125 unsigned int ShufBytes[16];
2126 for (int i = 0; i < 16; ++i) {
2127 // zero fill uppper part of preferred slot, don't care about the
2128 // other slots:
2129 unsigned int mask_val;
2130 if (i <= prefslot_end) {
2131 mask_val =
2132 ((i < prefslot_begin)
2133 ? 0x80
2134 : elt_byte + (i - prefslot_begin));
2135
2136 ShufBytes[i] = mask_val;
2137 } else
2138 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2139 }
2140
2141 SDValue ShufMask[4];
2142 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
2143 unsigned bidx = i / 4;
2144 unsigned int bits = ((ShufBytes[bidx] << 24) |
2145 (ShufBytes[bidx+1] << 16) |
2146 (ShufBytes[bidx+2] << 8) |
2147 ShufBytes[bidx+3]);
2148 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
2149 }
2150
2151 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2152 &ShufMask[0],
2153 sizeof(ShufMask) / sizeof(ShufMask[0]));
2154
Scott Michelc630c412008-11-24 17:11:17 +00002155 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel56a125e2008-11-22 23:50:42 +00002156 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2157 N, N, ShufMaskVec));
2158 } else {
2159 // Variable index: Rotate the requested element into slot 0, then replicate
2160 // slot 0 across the vector
2161 MVT VecVT = N.getValueType();
2162 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2163 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2164 abort();
2165 }
2166
2167 // Make life easier by making sure the index is zero-extended to i32
2168 if (Elt.getValueType() != MVT::i32)
2169 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2170
2171 // Scale the index to a bit/byte shift quantity
2172 APInt scaleFactor =
Scott Michelc630c412008-11-24 17:11:17 +00002173 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2174 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel56a125e2008-11-22 23:50:42 +00002175 SDValue vecShift;
Scott Michel56a125e2008-11-22 23:50:42 +00002176
Scott Michelc630c412008-11-24 17:11:17 +00002177 if (scaleShift > 0) {
2178 // Scale the shift factor:
Scott Michel56a125e2008-11-22 23:50:42 +00002179 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel0718cd82008-12-01 17:56:02 +00002180 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel56a125e2008-11-22 23:50:42 +00002181 }
2182
Scott Michelc630c412008-11-24 17:11:17 +00002183 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2184
2185 // Replicate the bytes starting at byte 0 across the entire vector (for
2186 // consistency with the notion of a unified register set)
Scott Michel56a125e2008-11-22 23:50:42 +00002187 SDValue replicate;
2188
2189 switch (VT.getSimpleVT()) {
2190 default:
2191 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2192 abort();
2193 /*NOTREACHED*/
2194 case MVT::i8: {
Scott Michelc630c412008-11-24 17:11:17 +00002195 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002196 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2197 factor, factor);
2198 break;
2199 }
2200 case MVT::i16: {
Scott Michelc630c412008-11-24 17:11:17 +00002201 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002202 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2203 factor, factor);
2204 break;
2205 }
2206 case MVT::i32:
2207 case MVT::f32: {
2208 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2209 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2210 factor, factor);
2211 break;
2212 }
2213 case MVT::i64:
2214 case MVT::f64: {
2215 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2216 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2217 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2218 loFactor, hiFactor);
2219 break;
2220 }
2221 }
2222
Scott Michelc630c412008-11-24 17:11:17 +00002223 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel0718cd82008-12-01 17:56:02 +00002224 DAG.getNode(SPUISD::SHUFB, VecVT,
2225 vecShift, vecShift, replicate));
Scott Michel8efdca42007-12-04 22:23:35 +00002226 }
2227
Scott Michel56a125e2008-11-22 23:50:42 +00002228 return retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002229}
2230
Dan Gohman8181bd12008-07-27 21:46:04 +00002231static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2232 SDValue VecOp = Op.getOperand(0);
2233 SDValue ValOp = Op.getOperand(1);
2234 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002235 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002236
2237 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2238 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2239
Duncan Sands92c43912008-06-06 12:08:01 +00002240 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel0718cd82008-12-01 17:56:02 +00002241 // Use $sp ($1) because it's always 16-byte aligned and it's available:
2242 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
2243 DAG.getRegister(SPU::R1, PtrVT),
2244 DAG.getConstant(CN->getSExtValue(), PtrVT));
2245 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, VT, Pointer);
Scott Michel8efdca42007-12-04 22:23:35 +00002246
Dan Gohman8181bd12008-07-27 21:46:04 +00002247 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002248 DAG.getNode(SPUISD::SHUFB, VT,
2249 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
Scott Michel0718cd82008-12-01 17:56:02 +00002250 VecOp,
2251 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, ShufMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002252
2253 return result;
2254}
2255
Dan Gohman8181bd12008-07-27 21:46:04 +00002256static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002257{
Dan Gohman8181bd12008-07-27 21:46:04 +00002258 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel8efdca42007-12-04 22:23:35 +00002259
2260 assert(Op.getValueType() == MVT::i8);
2261 switch (Opc) {
2262 default:
2263 assert(0 && "Unhandled i8 math operator");
2264 /*NOTREACHED*/
2265 break;
2266 case ISD::SUB: {
2267 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2268 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002269 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002270 N0 = (N0.getOpcode() != ISD::Constant
2271 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002272 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2273 MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00002274 N1 = (N1.getOpcode() != ISD::Constant
2275 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002276 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2277 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002278 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002279 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002280 }
Scott Michel8efdca42007-12-04 22:23:35 +00002281 case ISD::ROTR:
2282 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002283 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002284 unsigned N1Opc;
2285 N0 = (N0.getOpcode() != ISD::Constant
2286 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002287 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2288 MVT::i16));
Duncan Sands7aef60d2008-10-30 19:24:28 +00002289 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greife9f7f582008-08-31 15:37:04 +00002290 ? ISD::ZERO_EXTEND
2291 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002292 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sands7aef60d2008-10-30 19:24:28 +00002293 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002294 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sands7aef60d2008-10-30 19:24:28 +00002295 MVT::i32));
Dan Gohman8181bd12008-07-27 21:46:04 +00002296 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002297 DAG.getNode(ISD::OR, MVT::i16, N0,
2298 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sands7aef60d2008-10-30 19:24:28 +00002299 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002300 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002301 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2302 }
2303 case ISD::SRL:
2304 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002305 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002306 unsigned N1Opc;
2307 N0 = (N0.getOpcode() != ISD::Constant
2308 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002309 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2310 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002311 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2312 ? ISD::ZERO_EXTEND
2313 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002314 N1 = (N1.getOpcode() != ISD::Constant
2315 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002316 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2317 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002318 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002319 DAG.getNode(Opc, MVT::i16, N0, N1));
2320 }
2321 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002322 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002323 unsigned N1Opc;
2324 N0 = (N0.getOpcode() != ISD::Constant
2325 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002326 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2327 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002328 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2329 ? ISD::SIGN_EXTEND
2330 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002331 N1 = (N1.getOpcode() != ISD::Constant
2332 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002333 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2334 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002335 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002336 DAG.getNode(Opc, MVT::i16, N0, N1));
2337 }
2338 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002339 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002340 unsigned N1Opc;
2341 N0 = (N0.getOpcode() != ISD::Constant
2342 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002343 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2344 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002345 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002346 N1 = (N1.getOpcode() != ISD::Constant
2347 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002348 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2349 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002350 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002351 DAG.getNode(Opc, MVT::i16, N0, N1));
2352 break;
2353 }
2354 }
2355
Dan Gohman8181bd12008-07-27 21:46:04 +00002356 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002357}
2358
Dan Gohman8181bd12008-07-27 21:46:04 +00002359static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002360{
Duncan Sands92c43912008-06-06 12:08:01 +00002361 MVT VT = Op.getValueType();
2362 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002363
Dan Gohman8181bd12008-07-27 21:46:04 +00002364 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002365
2366 switch (Opc) {
2367 case ISD::ZERO_EXTEND:
2368 case ISD::SIGN_EXTEND:
2369 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002370 MVT Op0VT = Op0.getValueType();
2371 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002372
2373 assert(Op0VT == MVT::i32
2374 && "CellSPU: Zero/sign extending something other than i32");
2375
Scott Michelc630c412008-11-24 17:11:17 +00002376 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2377
Dan Gohman8181bd12008-07-27 21:46:04 +00002378 SDValue PromoteScalar =
Scott Michelc630c412008-11-24 17:11:17 +00002379 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
Scott Michel97872d32008-02-23 18:41:37 +00002380
Scott Michelc630c412008-11-24 17:11:17 +00002381 if (Opc != ISD::SIGN_EXTEND) {
Scott Michelf2df6cb2008-11-24 18:20:46 +00002382 // Use a shuffle to zero extend the i32 to i64 directly:
2383 SDValue shufMask =
2384 DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2385 DAG.getConstant(0x80808080, MVT::i32),
2386 DAG.getConstant(0x00010203, MVT::i32),
2387 DAG.getConstant(0x80808080, MVT::i32),
2388 DAG.getConstant(0x08090a0b, MVT::i32));
2389 SDValue zextShuffle =
2390 DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2391 PromoteScalar, PromoteScalar, shufMask);
2392
Scott Michelc630c412008-11-24 17:11:17 +00002393 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michelf2df6cb2008-11-24 18:20:46 +00002394 DAG.getNode(ISD::BIT_CONVERT, VecVT, zextShuffle));
Scott Michelc630c412008-11-24 17:11:17 +00002395 } else {
2396 // SPU has no "rotate quadword and replicate bit 0" (i.e. rotate/shift
2397 // right and propagate the sign bit) instruction.
Scott Michelf2df6cb2008-11-24 18:20:46 +00002398 SDValue RotQuad =
2399 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, Op0VecVT,
2400 PromoteScalar, DAG.getConstant(4, MVT::i32));
Scott Michelc630c412008-11-24 17:11:17 +00002401 SDValue SignQuad =
2402 DAG.getNode(SPUISD::VEC_SRA, Op0VecVT,
2403 PromoteScalar, DAG.getConstant(32, MVT::i32));
2404 SDValue SelMask =
2405 DAG.getNode(SPUISD::SELECT_MASK, Op0VecVT,
2406 DAG.getConstant(0xf0f0, MVT::i16));
2407 SDValue CombineQuad =
2408 DAG.getNode(SPUISD::SELB, Op0VecVT,
2409 SignQuad, RotQuad, SelMask);
2410
2411 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2412 DAG.getNode(ISD::BIT_CONVERT, VecVT, CombineQuad));
2413 }
Scott Michel97872d32008-02-23 18:41:37 +00002414 }
2415
Scott Michel67224b22008-06-02 22:18:03 +00002416 case ISD::ADD: {
2417 // Turn operands into vectors to satisfy type checking (shufb works on
2418 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002419 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002420 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002421 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002422 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002423 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002424
2425 // Create the shuffle mask for "rotating" the borrow up one register slot
2426 // once the borrow is generated.
2427 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2428 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2429 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2430 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2431
Dan Gohman8181bd12008-07-27 21:46:04 +00002432 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002433 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002434 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002435 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2436 CarryGen, CarryGen,
2437 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2438 &ShufBytes[0], ShufBytes.size()));
2439
Scott Michelc630c412008-11-24 17:11:17 +00002440 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002441 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2442 Op0, Op1, ShiftedCarry));
2443 }
2444
2445 case ISD::SUB: {
2446 // Turn operands into vectors to satisfy type checking (shufb works on
2447 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002448 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002449 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002450 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002451 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002452 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002453
2454 // Create the shuffle mask for "rotating" the borrow up one register slot
2455 // once the borrow is generated.
2456 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2457 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2458 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2459 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2460
Dan Gohman8181bd12008-07-27 21:46:04 +00002461 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002462 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002463 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002464 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2465 BorrowGen, BorrowGen,
2466 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2467 &ShufBytes[0], ShufBytes.size()));
2468
Scott Michelc630c412008-11-24 17:11:17 +00002469 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002470 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2471 Op0, Op1, ShiftedBorrow));
2472 }
2473
Scott Michel97872d32008-02-23 18:41:37 +00002474 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002475 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002476 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002477 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2478 SDValue MaskLower =
Scott Michel97872d32008-02-23 18:41:37 +00002479 DAG.getNode(SPUISD::SELB, VecVT,
2480 Op0Vec,
2481 DAG.getConstant(0, VecVT),
Scott Michel67224b22008-06-02 22:18:03 +00002482 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michel97872d32008-02-23 18:41:37 +00002483 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman8181bd12008-07-27 21:46:04 +00002484 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002485 DAG.getNode(ISD::SRL, ShiftAmtVT,
2486 ShiftAmt,
2487 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002488 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002489 DAG.getNode(ISD::AND, ShiftAmtVT,
2490 ShiftAmt,
2491 DAG.getConstant(7, ShiftAmtVT));
2492
Scott Michelc630c412008-11-24 17:11:17 +00002493 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel97872d32008-02-23 18:41:37 +00002494 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2495 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2496 MaskLower, ShiftAmtBytes),
2497 ShiftAmtBits));
2498 }
2499
2500 case ISD::SRL: {
Duncan Sands92c43912008-06-06 12:08:01 +00002501 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002502 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002503 MVT ShiftAmtVT = ShiftAmt.getValueType();
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
2513 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2514 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2515 Op0, ShiftAmtBytes),
2516 ShiftAmtBits);
2517 }
Scott Michel67224b22008-06-02 22:18:03 +00002518
2519 case ISD::SRA: {
2520 // Promote Op0 to vector
Dan Gohman8181bd12008-07-27 21:46:04 +00002521 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002522 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002523 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002524 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel67224b22008-06-02 22:18:03 +00002525
2526 // Negate variable shift amounts
2527 if (!isa<ConstantSDNode>(ShiftAmt)) {
2528 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2529 DAG.getConstant(0, ShiftVT), ShiftAmt);
2530 }
2531
Dan Gohman8181bd12008-07-27 21:46:04 +00002532 SDValue UpperHalfSign =
Scott Michelc630c412008-11-24 17:11:17 +00002533 DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i32,
Scott Michel67224b22008-06-02 22:18:03 +00002534 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2535 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2536 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman8181bd12008-07-27 21:46:04 +00002537 SDValue UpperHalfSignMask =
Scott Michel67224b22008-06-02 22:18:03 +00002538 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman8181bd12008-07-27 21:46:04 +00002539 SDValue UpperLowerMask =
Scott Michel67224b22008-06-02 22:18:03 +00002540 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2541 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman8181bd12008-07-27 21:46:04 +00002542 SDValue UpperLowerSelect =
Scott Michel67224b22008-06-02 22:18:03 +00002543 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2544 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman8181bd12008-07-27 21:46:04 +00002545 SDValue RotateLeftBytes =
Scott Michel67224b22008-06-02 22:18:03 +00002546 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2547 UpperLowerSelect, ShiftAmt);
Dan Gohman8181bd12008-07-27 21:46:04 +00002548 SDValue RotateLeftBits =
Scott Michel67224b22008-06-02 22:18:03 +00002549 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2550 RotateLeftBytes, ShiftAmt);
2551
Scott Michelc630c412008-11-24 17:11:17 +00002552 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002553 RotateLeftBits);
2554 }
Scott Michel97872d32008-02-23 18:41:37 +00002555 }
2556
Dan Gohman8181bd12008-07-27 21:46:04 +00002557 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002558}
2559
Scott Michel8efdca42007-12-04 22:23:35 +00002560//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002561static SDValue
2562LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2563 SDValue ConstVec;
2564 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002565 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002566
2567 ConstVec = Op.getOperand(0);
2568 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002569 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2570 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002571 ConstVec = ConstVec.getOperand(0);
2572 } else {
2573 ConstVec = Op.getOperand(1);
2574 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002575 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002576 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002577 }
2578 }
2579 }
2580
Gabor Greif1c80d112008-08-28 21:40:38 +00002581 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002582 uint64_t VectorBits[2];
2583 uint64_t UndefBits[2];
2584 uint64_t SplatBits, SplatUndef;
2585 int SplatSize;
2586
Gabor Greif1c80d112008-08-28 21:40:38 +00002587 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002588 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002589 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002590 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002591 SDValue tcVec[16];
2592 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002593 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2594
2595 // Turn the BUILD_VECTOR into a set of target constants:
2596 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002597 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002598
Gabor Greif1c80d112008-08-28 21:40:38 +00002599 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002600 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002601 }
2602 }
Nate Begeman7569e762008-07-29 19:07:27 +00002603 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2604 // lowered. Return the operation, rather than a null SDValue.
2605 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002606}
2607
2608//! Lower i32 multiplication
Dan Gohman8181bd12008-07-27 21:46:04 +00002609static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel8efdca42007-12-04 22:23:35 +00002610 unsigned Opc) {
Duncan Sands92c43912008-06-06 12:08:01 +00002611 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00002612 default:
2613 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands92c43912008-06-06 12:08:01 +00002614 << Op.getValueType().getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +00002615 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +00002616 abort();
2617 /*NOTREACHED*/
2618
2619 case MVT::i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002620 SDValue rA = Op.getOperand(0);
2621 SDValue rB = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002622
2623 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002624 DAG.getNode(ISD::ADD, MVT::i32,
2625 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2626 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2627 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00002628 }
2629 }
2630
Dan Gohman8181bd12008-07-27 21:46:04 +00002631 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002632}
2633
2634//! Custom lowering for CTPOP (count population)
2635/*!
2636 Custom lowering code that counts the number ones in the input
2637 operand. SPU has such an instruction, but it counts the number of
2638 ones per byte, which then have to be accumulated.
2639*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002640static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002641 MVT VT = Op.getValueType();
2642 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002643
Duncan Sands92c43912008-06-06 12:08:01 +00002644 switch (VT.getSimpleVT()) {
2645 default:
2646 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002647 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002648 SDValue N = Op.getOperand(0);
2649 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002650
Dan Gohman8181bd12008-07-27 21:46:04 +00002651 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2652 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002653
2654 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2655 }
2656
2657 case MVT::i16: {
2658 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002659 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002660
Chris Lattner1b989192007-12-31 04:13:23 +00002661 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002662
Dan Gohman8181bd12008-07-27 21:46:04 +00002663 SDValue N = Op.getOperand(0);
2664 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2665 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sands7aef60d2008-10-30 19:24:28 +00002666 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002667
Dan Gohman8181bd12008-07-27 21:46:04 +00002668 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2669 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002670
2671 // CNTB_result becomes the chain to which all of the virtual registers
2672 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002673 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002674 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002675
Dan Gohman8181bd12008-07-27 21:46:04 +00002676 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002677 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2678
Dan Gohman8181bd12008-07-27 21:46:04 +00002679 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002680
2681 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002682 DAG.getNode(ISD::ADD, MVT::i16,
2683 DAG.getNode(ISD::SRL, MVT::i16,
2684 Tmp1, Shift1),
2685 Tmp1),
2686 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002687 }
2688
2689 case MVT::i32: {
2690 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002691 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002692
Chris Lattner1b989192007-12-31 04:13:23 +00002693 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2694 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002695
Dan Gohman8181bd12008-07-27 21:46:04 +00002696 SDValue N = Op.getOperand(0);
2697 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2698 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2699 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2700 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002701
Dan Gohman8181bd12008-07-27 21:46:04 +00002702 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2703 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002704
2705 // CNTB_result becomes the chain to which all of the virtual registers
2706 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002707 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002708 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002709
Dan Gohman8181bd12008-07-27 21:46:04 +00002710 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002711 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2712
Dan Gohman8181bd12008-07-27 21:46:04 +00002713 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002714 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002715 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002716
Dan Gohman8181bd12008-07-27 21:46:04 +00002717 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002718 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002719 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002720
Dan Gohman8181bd12008-07-27 21:46:04 +00002721 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002722 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2723
Dan Gohman8181bd12008-07-27 21:46:04 +00002724 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002725 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002726 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2727 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002728 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002729 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002730 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002731
2732 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2733 }
2734
2735 case MVT::i64:
2736 break;
2737 }
2738
Dan Gohman8181bd12008-07-27 21:46:04 +00002739 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002740}
2741
Scott Michel56a125e2008-11-22 23:50:42 +00002742//! Lower ISD::SELECT_CC
2743/*!
2744 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2745 SELB instruction.
2746
2747 \note Need to revisit this in the future: if the code path through the true
2748 and false value computations is longer than the latency of a branch (6
2749 cycles), then it would be more advantageous to branch and insert a new basic
2750 block and branch on the condition. However, this code does not make that
2751 assumption, given the simplisitc uses so far.
2752 */
2753
2754static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
2755 MVT VT = Op.getValueType();
2756 SDValue lhs = Op.getOperand(0);
2757 SDValue rhs = Op.getOperand(1);
2758 SDValue trueval = Op.getOperand(2);
2759 SDValue falseval = Op.getOperand(3);
2760 SDValue condition = Op.getOperand(4);
2761
2762 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2763 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2764 // with another "cannot select select_cc" assert:
2765
2766 SDValue compare = DAG.getNode(ISD::SETCC, VT, lhs, rhs, condition);
2767 return DAG.getNode(SPUISD::SELB, VT, trueval, falseval, compare);
2768}
2769
Scott Michelec8c82e2008-12-02 19:53:53 +00002770//! Custom lower ISD::TRUNCATE
2771static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
2772{
2773 MVT VT = Op.getValueType();
2774 MVT::SimpleValueType simpleVT = VT.getSimpleVT();
2775 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
2776
2777 SDValue Op0 = Op.getOperand(0);
2778 MVT Op0VT = Op0.getValueType();
2779 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
2780
2781 SDValue PromoteScalar = DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2782
2783 unsigned maskLow;
2784 unsigned maskHigh;
2785
2786 // Create shuffle mask
2787 switch (Op0VT.getSimpleVT()) {
2788 case MVT::i128:
2789 switch (simpleVT) {
2790 case MVT::i64:
2791 // least significant doubleword of quadword
2792 maskHigh = 0x08090a0b;
2793 maskLow = 0x0c0d0e0f;
2794 break;
2795 case MVT::i32:
2796 // least significant word of quadword
2797 maskHigh = maskLow = 0x0c0d0e0f;
2798 break;
2799 case MVT::i16:
2800 // least significant halfword of quadword
2801 maskHigh = maskLow = 0x0e0f0e0f;
2802 break;
2803 case MVT::i8:
2804 // least significant byte of quadword
2805 maskHigh = maskLow = 0x0f0f0f0f;
2806 break;
2807 default:
2808 cerr << "Truncation to illegal type!";
2809 abort();
2810 }
2811 break;
2812 case MVT::i64:
2813 switch (simpleVT) {
2814 case MVT::i32:
2815 // least significant word of doubleword
2816 maskHigh = maskLow = 0x04050607;
2817 break;
2818 case MVT::i16:
2819 // least significant halfword of doubleword
2820 maskHigh = maskLow = 0x06070607;
2821 break;
2822 case MVT::i8:
2823 // least significant byte of doubleword
2824 maskHigh = maskLow = 0x07070707;
2825 break;
2826 default:
2827 cerr << "Truncation to illegal type!";
2828 abort();
2829 }
2830 break;
2831 case MVT::i32:
2832 case MVT::i16:
2833 switch (simpleVT) {
2834 case MVT::i16:
2835 // least significant halfword of word
2836 maskHigh = maskLow = 0x02030203;
2837 break;
2838 case MVT::i8:
2839 // least significant byte of word/halfword
2840 maskHigh = maskLow = 0x03030303;
2841 break;
2842 default:
2843 cerr << "Truncation to illegal type!";
2844 abort();
2845 }
2846 break;
2847 default:
2848 cerr << "Trying to lower truncation from illegal type!";
2849 abort();
2850 }
2851
2852 // Use a shuffle to perform the truncation
2853 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2854 DAG.getConstant(maskHigh, MVT::i32),
2855 DAG.getConstant(maskLow, MVT::i32),
2856 DAG.getConstant(maskHigh, MVT::i32),
2857 DAG.getConstant(maskLow, MVT::i32));
2858
2859 SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2860 PromoteScalar, PromoteScalar, shufMask);
2861
2862 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2863 DAG.getNode(ISD::BIT_CONVERT, VecVT, truncShuffle));
2864}
2865
Scott Michel56a125e2008-11-22 23:50:42 +00002866//! Custom (target-specific) lowering entry point
2867/*!
2868 This is where LLVM's DAG selection process calls to do target-specific
2869 lowering of nodes.
2870 */
Dan Gohman8181bd12008-07-27 21:46:04 +00002871SDValue
2872SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel8efdca42007-12-04 22:23:35 +00002873{
Scott Michel97872d32008-02-23 18:41:37 +00002874 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands92c43912008-06-06 12:08:01 +00002875 MVT VT = Op.getValueType();
Scott Michel97872d32008-02-23 18:41:37 +00002876
2877 switch (Opc) {
Scott Michel8efdca42007-12-04 22:23:35 +00002878 default: {
2879 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michel97872d32008-02-23 18:41:37 +00002880 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greif1c80d112008-08-28 21:40:38 +00002881 cerr << "*Op.getNode():\n";
2882 Op.getNode()->dump();
Scott Michel8efdca42007-12-04 22:23:35 +00002883 abort();
2884 }
2885 case ISD::LOAD:
Scott Michelec8c82e2008-12-02 19:53:53 +00002886 case ISD::EXTLOAD:
Scott Michel8efdca42007-12-04 22:23:35 +00002887 case ISD::SEXTLOAD:
2888 case ISD::ZEXTLOAD:
2889 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2890 case ISD::STORE:
2891 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2892 case ISD::ConstantPool:
2893 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2894 case ISD::GlobalAddress:
2895 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2896 case ISD::JumpTable:
2897 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2898 case ISD::Constant:
2899 return LowerConstant(Op, DAG);
2900 case ISD::ConstantFP:
2901 return LowerConstantFP(Op, DAG);
Scott Michel394e26d2008-01-17 20:38:41 +00002902 case ISD::BRCOND:
2903 return LowerBRCOND(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002904 case ISD::FORMAL_ARGUMENTS:
Scott Michel394e26d2008-01-17 20:38:41 +00002905 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel8efdca42007-12-04 22:23:35 +00002906 case ISD::CALL:
Scott Micheldbac4cf2008-01-11 02:53:15 +00002907 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel8efdca42007-12-04 22:23:35 +00002908 case ISD::RET:
2909 return LowerRET(Op, DAG, getTargetMachine());
2910
Scott Michel97872d32008-02-23 18:41:37 +00002911
2912 // i8, i64 math ops:
2913 case ISD::ZERO_EXTEND:
2914 case ISD::SIGN_EXTEND:
2915 case ISD::ANY_EXTEND:
Scott Michel67224b22008-06-02 22:18:03 +00002916 case ISD::ADD:
Scott Michel8efdca42007-12-04 22:23:35 +00002917 case ISD::SUB:
2918 case ISD::ROTR:
2919 case ISD::ROTL:
2920 case ISD::SRL:
2921 case ISD::SHL:
Scott Michel67224b22008-06-02 22:18:03 +00002922 case ISD::SRA: {
Scott Michel97872d32008-02-23 18:41:37 +00002923 if (VT == MVT::i8)
2924 return LowerI8Math(Op, DAG, Opc);
2925 else if (VT == MVT::i64)
2926 return LowerI64Math(Op, DAG, Opc);
2927 break;
Scott Michel67224b22008-06-02 22:18:03 +00002928 }
Scott Michel8efdca42007-12-04 22:23:35 +00002929
2930 // Vector-related lowering.
2931 case ISD::BUILD_VECTOR:
2932 return LowerBUILD_VECTOR(Op, DAG);
2933 case ISD::SCALAR_TO_VECTOR:
2934 return LowerSCALAR_TO_VECTOR(Op, DAG);
2935 case ISD::VECTOR_SHUFFLE:
2936 return LowerVECTOR_SHUFFLE(Op, DAG);
2937 case ISD::EXTRACT_VECTOR_ELT:
2938 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2939 case ISD::INSERT_VECTOR_ELT:
2940 return LowerINSERT_VECTOR_ELT(Op, DAG);
2941
2942 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2943 case ISD::AND:
2944 case ISD::OR:
2945 case ISD::XOR:
2946 return LowerByteImmed(Op, DAG);
2947
2948 // Vector and i8 multiply:
2949 case ISD::MUL:
Duncan Sands92c43912008-06-06 12:08:01 +00002950 if (VT.isVector())
Scott Michel8efdca42007-12-04 22:23:35 +00002951 return LowerVectorMUL(Op, DAG);
Scott Michel97872d32008-02-23 18:41:37 +00002952 else if (VT == MVT::i8)
2953 return LowerI8Math(Op, DAG, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002954 else
Scott Michel97872d32008-02-23 18:41:37 +00002955 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002956
2957 case ISD::FDIV:
Scott Michel97872d32008-02-23 18:41:37 +00002958 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel8efdca42007-12-04 22:23:35 +00002959 return LowerFDIVf32(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002960#if 0
2961 // This is probably a libcall
2962 else if (Op.getValueType() == MVT::f64)
2963 return LowerFDIVf64(Op, DAG);
2964#endif
Scott Michel8efdca42007-12-04 22:23:35 +00002965 else
2966 assert(0 && "Calling FDIV on unsupported MVT");
2967
2968 case ISD::CTPOP:
2969 return LowerCTPOP(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002970
2971 case ISD::SELECT_CC:
2972 return LowerSELECT_CC(Op, DAG);
Scott Michelec8c82e2008-12-02 19:53:53 +00002973
2974 case ISD::TRUNCATE:
2975 return LowerTRUNCATE(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002976 }
2977
Dan Gohman8181bd12008-07-27 21:46:04 +00002978 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002979}
2980
Duncan Sands7d9834b2008-12-01 11:39:25 +00002981void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
2982 SmallVectorImpl<SDValue>&Results,
2983 SelectionDAG &DAG)
Scott Michel6e2d68b2008-11-10 23:43:06 +00002984{
2985#if 0
2986 unsigned Opc = (unsigned) N->getOpcode();
2987 MVT OpVT = N->getValueType(0);
2988
2989 switch (Opc) {
2990 default: {
2991 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2992 cerr << "Op.getOpcode() = " << Opc << "\n";
2993 cerr << "*Op.getNode():\n";
2994 N->dump();
2995 abort();
2996 /*NOTREACHED*/
2997 }
2998 }
2999#endif
3000
3001 /* Otherwise, return unchanged */
Scott Michel6e2d68b2008-11-10 23:43:06 +00003002}
3003
Scott Michel8efdca42007-12-04 22:23:35 +00003004//===----------------------------------------------------------------------===//
Scott Michel8efdca42007-12-04 22:23:35 +00003005// Target Optimization Hooks
3006//===----------------------------------------------------------------------===//
3007
Dan Gohman8181bd12008-07-27 21:46:04 +00003008SDValue
Scott Michel8efdca42007-12-04 22:23:35 +00003009SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
3010{
3011#if 0
3012 TargetMachine &TM = getTargetMachine();
Scott Michelf9f42e62008-01-29 02:16:57 +00003013#endif
3014 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel8efdca42007-12-04 22:23:35 +00003015 SelectionDAG &DAG = DCI.DAG;
Scott Michel0718cd82008-12-01 17:56:02 +00003016 SDValue Op0 = N->getOperand(0); // everything has at least one operand
3017 MVT NodeVT = N->getValueType(0); // The node's value type
3018 MVT Op0VT = Op0.getValueType(); // The first operand's result
3019 SDValue Result; // Initially, empty result
Scott Michel8efdca42007-12-04 22:23:35 +00003020
3021 switch (N->getOpcode()) {
3022 default: break;
Scott Michelf9f42e62008-01-29 02:16:57 +00003023 case ISD::ADD: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003024 SDValue Op1 = N->getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003025
Scott Michel67224b22008-06-02 22:18:03 +00003026 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003027 SDValue Op01 = Op0.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003028 if (Op01.getOpcode() == ISD::Constant
3029 || Op01.getOpcode() == ISD::TargetConstant) {
3030 // (add <const>, (SPUindirect <arg>, <const>)) ->
3031 // (SPUindirect <arg>, <const + const>)
3032 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
3033 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman8181bd12008-07-27 21:46:04 +00003034 SDValue combinedConst =
Scott Michel0718cd82008-12-01 17:56:02 +00003035 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(), Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00003036
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003037 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
3038 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00003039 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003040 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel0718cd82008-12-01 17:56:02 +00003041 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
Scott Michelf9f42e62008-01-29 02:16:57 +00003042 Op0.getOperand(0), combinedConst);
3043 }
Scott Michel67224b22008-06-02 22:18:03 +00003044 } else if (isa<ConstantSDNode>(Op0)
Scott Michelf9f42e62008-01-29 02:16:57 +00003045 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003046 SDValue Op11 = Op1.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003047 if (Op11.getOpcode() == ISD::Constant
3048 || Op11.getOpcode() == ISD::TargetConstant) {
3049 // (add (SPUindirect <arg>, <const>), <const>) ->
3050 // (SPUindirect <arg>, <const + const>)
3051 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
3052 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman8181bd12008-07-27 21:46:04 +00003053 SDValue combinedConst =
Scott Michel0718cd82008-12-01 17:56:02 +00003054 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(), Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00003055
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003056 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
3057 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00003058 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003059 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00003060
3061 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
3062 Op1.getOperand(0), combinedConst);
3063 }
3064 }
Scott Michel97872d32008-02-23 18:41:37 +00003065 break;
3066 }
3067 case ISD::SIGN_EXTEND:
3068 case ISD::ZERO_EXTEND:
3069 case ISD::ANY_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00003070 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
Scott Michel97872d32008-02-23 18:41:37 +00003071 // (any_extend (SPUextract_elt0 <arg>)) ->
3072 // (SPUextract_elt0 <arg>)
3073 // Types must match, however...
3074 DEBUG(cerr << "Replace: ");
3075 DEBUG(N->dump(&DAG));
3076 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003077 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003078 DEBUG(cerr << "\n");
3079
3080 return Op0;
3081 }
3082 break;
3083 }
3084 case SPUISD::IndirectAddr: {
3085 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
3086 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003087 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00003088 // (SPUindirect (SPUaform <addr>, 0), 0) ->
3089 // (SPUaform <addr>, 0)
3090
3091 DEBUG(cerr << "Replace: ");
3092 DEBUG(N->dump(&DAG));
3093 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003094 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003095 DEBUG(cerr << "\n");
3096
3097 return Op0;
3098 }
3099 }
3100 break;
3101 }
3102 case SPUISD::SHLQUAD_L_BITS:
3103 case SPUISD::SHLQUAD_L_BYTES:
3104 case SPUISD::VEC_SHL:
3105 case SPUISD::VEC_SRL:
3106 case SPUISD::VEC_SRA:
3107 case SPUISD::ROTQUAD_RZ_BYTES:
3108 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003109 SDValue Op1 = N->getOperand(1);
Scott Michel97872d32008-02-23 18:41:37 +00003110
3111 if (isa<ConstantSDNode>(Op1)) {
3112 // Kill degenerate vector shifts:
3113 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003114 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00003115 Result = Op0;
3116 }
3117 }
3118 break;
3119 }
3120 case SPUISD::PROMOTE_SCALAR: {
3121 switch (Op0.getOpcode()) {
3122 default:
3123 break;
3124 case ISD::ANY_EXTEND:
3125 case ISD::ZERO_EXTEND:
3126 case ISD::SIGN_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00003127 // (SPUpromote_scalar (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
Scott Michel97872d32008-02-23 18:41:37 +00003128 // <arg>
3129 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman8181bd12008-07-27 21:46:04 +00003130 SDValue Op00 = Op0.getOperand(0);
Scott Michelc630c412008-11-24 17:11:17 +00003131 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003132 SDValue Op000 = Op00.getOperand(0);
Scott Michel0718cd82008-12-01 17:56:02 +00003133 if (Op000.getValueType() == NodeVT) {
Scott Michel97872d32008-02-23 18:41:37 +00003134 Result = Op000;
3135 }
3136 }
3137 break;
3138 }
Scott Michelc630c412008-11-24 17:11:17 +00003139 case SPUISD::VEC2PREFSLOT: {
Scott Michel0718cd82008-12-01 17:56:02 +00003140 // (SPUpromote_scalar (SPUvec2prefslot <arg>)) ->
Scott Michel97872d32008-02-23 18:41:37 +00003141 // <arg>
3142 Result = Op0.getOperand(0);
3143 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003144 }
Scott Michel97872d32008-02-23 18:41:37 +00003145 }
3146 break;
Scott Michelf9f42e62008-01-29 02:16:57 +00003147 }
3148 }
Scott Michel394e26d2008-01-17 20:38:41 +00003149 // Otherwise, return unchanged.
Scott Michel0718cd82008-12-01 17:56:02 +00003150#ifndef NDEBUG
Gabor Greif1c80d112008-08-28 21:40:38 +00003151 if (Result.getNode()) {
Scott Michel97872d32008-02-23 18:41:37 +00003152 DEBUG(cerr << "\nReplace.SPU: ");
3153 DEBUG(N->dump(&DAG));
3154 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003155 DEBUG(Result.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003156 DEBUG(cerr << "\n");
3157 }
3158#endif
3159
3160 return Result;
Scott Michel8efdca42007-12-04 22:23:35 +00003161}
3162
3163//===----------------------------------------------------------------------===//
3164// Inline Assembly Support
3165//===----------------------------------------------------------------------===//
3166
3167/// getConstraintType - Given a constraint letter, return the type of
3168/// constraint it is for this target.
Scott Michel4ec722e2008-07-16 17:17:29 +00003169SPUTargetLowering::ConstraintType
Scott Michel8efdca42007-12-04 22:23:35 +00003170SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3171 if (ConstraintLetter.size() == 1) {
3172 switch (ConstraintLetter[0]) {
3173 default: break;
3174 case 'b':
3175 case 'r':
3176 case 'f':
3177 case 'v':
3178 case 'y':
3179 return C_RegisterClass;
Scott Michel4ec722e2008-07-16 17:17:29 +00003180 }
Scott Michel8efdca42007-12-04 22:23:35 +00003181 }
3182 return TargetLowering::getConstraintType(ConstraintLetter);
3183}
3184
Scott Michel4ec722e2008-07-16 17:17:29 +00003185std::pair<unsigned, const TargetRegisterClass*>
Scott Michel8efdca42007-12-04 22:23:35 +00003186SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands92c43912008-06-06 12:08:01 +00003187 MVT VT) const
Scott Michel8efdca42007-12-04 22:23:35 +00003188{
3189 if (Constraint.size() == 1) {
3190 // GCC RS6000 Constraint Letters
3191 switch (Constraint[0]) {
3192 case 'b': // R1-R31
3193 case 'r': // R0-R31
3194 if (VT == MVT::i64)
3195 return std::make_pair(0U, SPU::R64CRegisterClass);
3196 return std::make_pair(0U, SPU::R32CRegisterClass);
3197 case 'f':
3198 if (VT == MVT::f32)
3199 return std::make_pair(0U, SPU::R32FPRegisterClass);
3200 else if (VT == MVT::f64)
3201 return std::make_pair(0U, SPU::R64FPRegisterClass);
3202 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003203 case 'v':
Scott Michel8efdca42007-12-04 22:23:35 +00003204 return std::make_pair(0U, SPU::GPRCRegisterClass);
3205 }
3206 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003207
Scott Michel8efdca42007-12-04 22:23:35 +00003208 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3209}
3210
Scott Michel97872d32008-02-23 18:41:37 +00003211//! Compute used/known bits for a SPU operand
Scott Michel8efdca42007-12-04 22:23:35 +00003212void
Dan Gohman8181bd12008-07-27 21:46:04 +00003213SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohmand0dfc772008-02-13 22:28:48 +00003214 const APInt &Mask,
Scott Michel4ec722e2008-07-16 17:17:29 +00003215 APInt &KnownZero,
Dan Gohman229fa052008-02-13 00:35:47 +00003216 APInt &KnownOne,
Scott Michel5a6f17b2008-01-30 02:55:46 +00003217 const SelectionDAG &DAG,
3218 unsigned Depth ) const {
Scott Michelbc5fbc12008-04-30 00:30:08 +00003219#if 0
Scott Michel97872d32008-02-23 18:41:37 +00003220 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michelbc5fbc12008-04-30 00:30:08 +00003221#endif
Scott Michel97872d32008-02-23 18:41:37 +00003222
3223 switch (Op.getOpcode()) {
3224 default:
3225 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3226 break;
3227
3228#if 0
3229 case CALL:
3230 case SHUFB:
Scott Michel56a125e2008-11-22 23:50:42 +00003231 case SHUFFLE_MASK:
Scott Michel97872d32008-02-23 18:41:37 +00003232 case CNTB:
3233#endif
3234
3235 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003236 SDValue Op0 = Op.getOperand(0);
Duncan Sands92c43912008-06-06 12:08:01 +00003237 MVT Op0VT = Op0.getValueType();
3238 unsigned Op0VTBits = Op0VT.getSizeInBits();
3239 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003240 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3241 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003242 break;
3243 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003244
Scott Michel97872d32008-02-23 18:41:37 +00003245 case SPUISD::LDRESULT:
Scott Michelc630c412008-11-24 17:11:17 +00003246 case SPUISD::VEC2PREFSLOT:
3247 case SPUISD::VEC2PREFSLOT_CHAINED: {
Duncan Sands92c43912008-06-06 12:08:01 +00003248 MVT OpVT = Op.getValueType();
3249 unsigned OpVTBits = OpVT.getSizeInBits();
3250 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003251 KnownZero |= APInt(OpVTBits, ~InMask, false);
3252 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003253 break;
3254 }
3255
3256#if 0
3257 case EXTRACT_I1_ZEXT:
3258 case EXTRACT_I1_SEXT:
3259 case EXTRACT_I8_ZEXT:
3260 case EXTRACT_I8_SEXT:
3261 case MPY:
3262 case MPYU:
3263 case MPYH:
3264 case MPYHH:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003265 case SPUISD::SHLQUAD_L_BITS:
3266 case SPUISD::SHLQUAD_L_BYTES:
3267 case SPUISD::VEC_SHL:
3268 case SPUISD::VEC_SRL:
3269 case SPUISD::VEC_SRA:
3270 case SPUISD::VEC_ROTL:
3271 case SPUISD::VEC_ROTR:
3272 case SPUISD::ROTQUAD_RZ_BYTES:
3273 case SPUISD::ROTQUAD_RZ_BITS:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003274 case SPUISD::ROTBYTES_LEFT:
3275 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel67224b22008-06-02 22:18:03 +00003276 case SPUISD::SELECT_MASK:
3277 case SPUISD::SELB:
3278 case SPUISD::FPInterp:
3279 case SPUISD::FPRecipEst:
3280 case SPUISD::SEXT32TO64:
Scott Michel97872d32008-02-23 18:41:37 +00003281#endif
3282 }
Scott Michel8efdca42007-12-04 22:23:35 +00003283}
3284
Scott Michelbc5fbc12008-04-30 00:30:08 +00003285// LowerAsmOperandForConstraint
3286void
Dan Gohman8181bd12008-07-27 21:46:04 +00003287SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003288 char ConstraintLetter,
Evan Cheng7f250d62008-09-24 00:05:32 +00003289 bool hasMemory,
Dan Gohman8181bd12008-07-27 21:46:04 +00003290 std::vector<SDValue> &Ops,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003291 SelectionDAG &DAG) const {
3292 // Default, for the time being, to the base class handler
Evan Cheng7f250d62008-09-24 00:05:32 +00003293 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3294 Ops, DAG);
Scott Michelbc5fbc12008-04-30 00:30:08 +00003295}
3296
Scott Michel8efdca42007-12-04 22:23:35 +00003297/// isLegalAddressImmediate - Return true if the integer value can be used
3298/// as the offset of the target addressing mode.
Gabor Greife9f7f582008-08-31 15:37:04 +00003299bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3300 const Type *Ty) const {
Scott Michel8efdca42007-12-04 22:23:35 +00003301 // SPU's addresses are 256K:
3302 return (V > -(1 << 18) && V < (1 << 18) - 1);
3303}
3304
3305bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel4ec722e2008-07-16 17:17:29 +00003306 return false;
Scott Michel8efdca42007-12-04 22:23:35 +00003307}
Dan Gohman36322c72008-10-18 02:06:02 +00003308
3309bool
3310SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3311 // The SPU target isn't yet aware of offsets.
3312 return false;
3313}