blob: 17d88a937adeaab31e3317297ccba96e0ae5bfb3 [file] [log] [blame]
Scott Michel8efdca42007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner081ce942007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel8efdca42007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SPUTargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPURegisterNames.h"
15#include "SPUISelLowering.h"
16#include "SPUTargetMachine.h"
Scott Michelbc5fbc12008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michel8efdca42007-12-04 22:23:35 +000018#include "llvm/ADT/VectorExtras.h"
Scott Michel8efdca42007-12-04 22:23:35 +000019#include "llvm/CodeGen/CallingConvLower.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner1b989192007-12-31 04:13:23 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel8efdca42007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel8efdca42007-12-04 22:23:35 +000025#include "llvm/Constants.h"
26#include "llvm/Function.h"
27#include "llvm/Intrinsics.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/MathExtras.h"
30#include "llvm/Target/TargetOptions.h"
31
32#include <map>
33
34using namespace llvm;
35
36// Used in getTargetNodeName() below
37namespace {
38 std::map<unsigned, const char *> node_names;
39
Duncan Sands92c43912008-06-06 12:08:01 +000040 //! MVT mapping to useful data for Cell SPU
Scott Michel8efdca42007-12-04 22:23:35 +000041 struct valtype_map_s {
Scott Michel56a125e2008-11-22 23:50:42 +000042 const MVT valtype;
43 const int prefslot_byte;
Scott Michel8efdca42007-12-04 22:23:35 +000044 };
Scott Michel4ec722e2008-07-16 17:17:29 +000045
Scott Michel8efdca42007-12-04 22:23:35 +000046 const valtype_map_s valtype_map[] = {
47 { MVT::i1, 3 },
48 { MVT::i8, 3 },
49 { MVT::i16, 2 },
50 { MVT::i32, 0 },
51 { MVT::f32, 0 },
52 { MVT::i64, 0 },
53 { MVT::f64, 0 },
54 { MVT::i128, 0 }
55 };
56
57 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
58
Duncan Sands92c43912008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel8efdca42007-12-04 22:23:35 +000060 const valtype_map_s *retval = 0;
61
62 for (size_t i = 0; i < n_valtype_map; ++i) {
63 if (valtype_map[i].valtype == VT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel8efdca42007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands92c43912008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +000074 abort();
75 }
76#endif
77
78 return retval;
79 }
80
81 //! Predicate that returns true if operand is a memory target
82 /*!
83 \arg Op Operand to test
84 \return true if the operand is a memory target (i.e., global
Scott Micheldbac4cf2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel8efdca42007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman8181bd12008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel8efdca42007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel8efdca42007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
Bill Wendlingfef06052008-09-16 21:48:12 +000095 || Opc == ISD::ExternalSymbol
Scott Michel8efdca42007-12-04 22:23:35 +000096 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel8efdca42007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
Bill Wendlingfef06052008-09-16 21:48:12 +0000100 || Opc == ISD::TargetExternalSymbol
Scott Micheldbac4cf2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel8efdca42007-12-04 22:23:35 +0000102 }
Scott Michel394e26d2008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman8181bd12008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel394e26d2008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel5a6f17b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel394e26d2008-01-17 20:38:41 +0000110 }
Scott Michel8efdca42007-12-04 22:23:35 +0000111}
112
113SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
114 : TargetLowering(TM),
115 SPUTM(TM)
116{
117 // Fold away setcc operations if possible.
118 setPow2DivIsCheap();
119
120 // Use _setjmp/_longjmp instead of setjmp/longjmp.
121 setUseUnderscoreSetJmp(true);
122 setUseUnderscoreLongJmp(true);
Scott Michel4ec722e2008-07-16 17:17:29 +0000123
Scott Michel8efdca42007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel438be252007-12-17 22:32:34 +0000125 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
126 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
127 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
128 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
129 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
130 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel8efdca42007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel4ec722e2008-07-16 17:17:29 +0000132
Scott Michelabb8ca12008-11-20 16:36:33 +0000133 // Initialize libcalls:
134 setLibcallName(RTLIB::MUL_I64, "__muldi3");
135
Scott Michel8efdca42007-12-04 22:23:35 +0000136 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng08c171a2008-10-14 21:26:46 +0000137 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
138 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
139 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +0000140
Evan Cheng08c171a2008-10-14 21:26:46 +0000141 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
142 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
143 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Scott Michel55252632008-11-20 04:26:21 +0000144 setTruncStoreAction(MVT::i8, MVT::i8, Custom);
145 setTruncStoreAction(MVT::i16, MVT::i8, Custom);
146 setTruncStoreAction(MVT::i32, MVT::i8, Custom);
147 setTruncStoreAction(MVT::i64, MVT::i8, Custom);
148 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000149
Evan Cheng08c171a2008-10-14 21:26:46 +0000150 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
151 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
152 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000153
Scott Michelec8c82e2008-12-02 19:53:53 +0000154 setLoadExtAction(ISD::EXTLOAD, MVT::f32, Custom);
155
Scott Michel8efdca42007-12-04 22:23:35 +0000156 // SPU constant load actions are custom lowered:
157 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begeman78125042008-02-14 18:43:04 +0000158 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000159 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
160
161 // SPU's loads and stores have to be custom lowered:
Scott Michele1006032008-11-19 17:45:08 +0000162 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel8efdca42007-12-04 22:23:35 +0000163 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000164 MVT VT = (MVT::SimpleValueType)sctype;
165
166 setOperationAction(ISD::LOAD, VT, Custom);
167 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000168 }
169
Scott Michel33d73eb2008-11-21 02:56:16 +0000170 // Custom lower BRCOND for i8 to "promote" the result to i16
Scott Michel394e26d2008-01-17 20:38:41 +0000171 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000172
173 // Expand the jumptable branches
174 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
175 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel56a125e2008-11-22 23:50:42 +0000176
177 // Custom lower SELECT_CC for most cases, but expand by default
Scott Michel4ec722e2008-07-16 17:17:29 +0000178 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel56a125e2008-11-22 23:50:42 +0000179 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
180 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
181 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
Scott Michelfa888632008-11-25 00:23:16 +0000182#if 0
Scott Michel56a125e2008-11-22 23:50:42 +0000183 setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
Scott Michelfa888632008-11-25 00:23:16 +0000184#endif
Scott Michel8efdca42007-12-04 22:23:35 +0000185
186 // SPU has no intrinsics for these particular operations:
Andrew Lenharth0531ec52008-02-16 14:46:26 +0000187 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
188
Scott Michel8efdca42007-12-04 22:23:35 +0000189 // PowerPC has no SREM/UREM instructions
190 setOperationAction(ISD::SREM, MVT::i32, Expand);
191 setOperationAction(ISD::UREM, MVT::i32, Expand);
192 setOperationAction(ISD::SREM, MVT::i64, Expand);
193 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000194
Scott Michel8efdca42007-12-04 22:23:35 +0000195 // We don't support sin/cos/sqrt/fmod
196 setOperationAction(ISD::FSIN , MVT::f64, Expand);
197 setOperationAction(ISD::FCOS , MVT::f64, Expand);
198 setOperationAction(ISD::FREM , MVT::f64, Expand);
199 setOperationAction(ISD::FSIN , MVT::f32, Expand);
200 setOperationAction(ISD::FCOS , MVT::f32, Expand);
201 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000202
Scott Michel8efdca42007-12-04 22:23:35 +0000203 // If we're enabling GP optimizations, use hardware square root
204 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
205 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000206
Scott Michel8efdca42007-12-04 22:23:35 +0000207 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
208 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
209
210 // SPU can do rotate right and left, so legalize it... but customize for i8
211 // because instructions don't exist.
Bill Wendling965299c2008-08-31 02:59:23 +0000212
213 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
214 // .td files.
215 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
216 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
217 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
218
Scott Michel8efdca42007-12-04 22:23:35 +0000219 setOperationAction(ISD::ROTL, MVT::i32, Legal);
220 setOperationAction(ISD::ROTL, MVT::i16, Legal);
221 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Michelabb8ca12008-11-20 16:36:33 +0000222
Scott Michel8efdca42007-12-04 22:23:35 +0000223 // SPU has no native version of shift left/right for i8
224 setOperationAction(ISD::SHL, MVT::i8, Custom);
225 setOperationAction(ISD::SRL, MVT::i8, Custom);
226 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000227
228 // SPU needs custom lowering for shift left/right for i64
Scott Michel97872d32008-02-23 18:41:37 +0000229 setOperationAction(ISD::SHL, MVT::i64, Custom);
230 setOperationAction(ISD::SRL, MVT::i64, Custom);
231 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000232
Scott Michel4ec722e2008-07-16 17:17:29 +0000233 // Custom lower i8, i32 and i64 multiplications
234 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000235 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000236 setOperationAction(ISD::MUL, MVT::i64, Expand); // libcall
237
238 // SMUL_LOHI, UMUL_LOHI
239 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
240 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
241 setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom);
242 setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000243
Scott Michel67224b22008-06-02 22:18:03 +0000244 // Need to custom handle (some) common i8, i64 math ops
245 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000246 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000247 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000248
Scott Michel8efdca42007-12-04 22:23:35 +0000249 // SPU does not have BSWAP. It does have i32 support CTLZ.
250 // CTPOP has to be custom lowered.
251 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
252 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
253
254 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
255 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
256 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
257 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
258
259 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
260 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
261
262 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000263
Scott Michel67224b22008-06-02 22:18:03 +0000264 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel978b96f2008-03-10 23:49:09 +0000265 // select ought to work:
Scott Michel53ab7792008-03-10 16:58:52 +0000266 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000267 setOperationAction(ISD::SELECT, MVT::i16, Legal);
268 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000269 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000270
Scott Michel53ab7792008-03-10 16:58:52 +0000271 setOperationAction(ISD::SETCC, MVT::i8, Legal);
272 setOperationAction(ISD::SETCC, MVT::i16, Legal);
273 setOperationAction(ISD::SETCC, MVT::i32, Legal);
274 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michel6baba072008-03-05 23:02:02 +0000275
Scott Michel97872d32008-02-23 18:41:37 +0000276 // Zero extension and sign extension for i64 have to be
277 // custom legalized
278 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
279 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
280 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000281
Scott Michelec8c82e2008-12-02 19:53:53 +0000282 // Custom lower truncates
283 setOperationAction(ISD::TRUNCATE, MVT::i8, Custom);
284 setOperationAction(ISD::TRUNCATE, MVT::i16, Custom);
285 setOperationAction(ISD::TRUNCATE, MVT::i32, Custom);
286 setOperationAction(ISD::TRUNCATE, MVT::i64, Custom);
287
Scott Michel8efdca42007-12-04 22:23:35 +0000288 // SPU has a legal FP -> signed INT instruction
289 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
290 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
291 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
292 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
293
294 // FDIV on SPU requires custom lowering
295 setOperationAction(ISD::FDIV, MVT::f32, Custom);
296 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
297
298 // SPU has [U|S]INT_TO_FP
299 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
300 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
301 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
302 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
303 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
304 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
305 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
306 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
307
Scott Michel754d8662007-12-20 00:44:13 +0000308 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
309 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
310 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
311 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000312
313 // We cannot sextinreg(i1). Expand to shifts.
314 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000315
Scott Michel8efdca42007-12-04 22:23:35 +0000316 // Support label based line numbers.
Dan Gohman472d12c2008-06-30 20:59:49 +0000317 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000318 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000319
320 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel8efdca42007-12-04 22:23:35 +0000321 // appropriate instructions to materialize the address.
Scott Michel33d73eb2008-11-21 02:56:16 +0000322 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michelf9f42e62008-01-29 02:16:57 +0000323 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000324 MVT VT = (MVT::SimpleValueType)sctype;
325
326 setOperationAction(ISD::GlobalAddress, VT, Custom);
327 setOperationAction(ISD::ConstantPool, VT, Custom);
328 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michelf9f42e62008-01-29 02:16:57 +0000329 }
Scott Michel8efdca42007-12-04 22:23:35 +0000330
331 // RET must be custom lowered, to meet ABI requirements
332 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000333
Scott Michel8efdca42007-12-04 22:23:35 +0000334 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
335 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000336
Scott Michel8efdca42007-12-04 22:23:35 +0000337 // Use the default implementation.
338 setOperationAction(ISD::VAARG , MVT::Other, Expand);
339 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
340 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000341 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000342 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
343 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
344 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
345
346 // Cell SPU has instructions for converting between i64 and fp.
347 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
348 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000349
Scott Michel8efdca42007-12-04 22:23:35 +0000350 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
351 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
352
353 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
354 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
355
356 // First set operation action for all vector types to expand. Then we
357 // will selectively turn on ones that can be effectively codegen'd.
358 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
359 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
360 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
361 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
362 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
363 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
364
Duncan Sands92c43912008-06-06 12:08:01 +0000365 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
366 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
367 MVT VT = (MVT::SimpleValueType)i;
Scott Michel8efdca42007-12-04 22:23:35 +0000368
Duncan Sands92c43912008-06-06 12:08:01 +0000369 // add/sub are legal for all supported vector VT's.
370 setOperationAction(ISD::ADD , VT, Legal);
371 setOperationAction(ISD::SUB , VT, Legal);
372 // mul has to be custom lowered.
373 setOperationAction(ISD::MUL , VT, Custom);
374
375 setOperationAction(ISD::AND , VT, Legal);
376 setOperationAction(ISD::OR , VT, Legal);
377 setOperationAction(ISD::XOR , VT, Legal);
378 setOperationAction(ISD::LOAD , VT, Legal);
379 setOperationAction(ISD::SELECT, VT, Legal);
380 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000381
Scott Michel8efdca42007-12-04 22:23:35 +0000382 // These operations need to be expanded:
Duncan Sands92c43912008-06-06 12:08:01 +0000383 setOperationAction(ISD::SDIV, VT, Expand);
384 setOperationAction(ISD::SREM, VT, Expand);
385 setOperationAction(ISD::UDIV, VT, Expand);
386 setOperationAction(ISD::UREM, VT, Expand);
387 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000388
389 // Custom lower build_vector, constant pool spills, insert and
390 // extract vector elements:
Duncan Sands92c43912008-06-06 12:08:01 +0000391 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
392 setOperationAction(ISD::ConstantPool, VT, Custom);
393 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
394 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
395 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
396 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000397 }
398
399 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
400 setOperationAction(ISD::AND, MVT::v16i8, Custom);
401 setOperationAction(ISD::OR, MVT::v16i8, Custom);
402 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
403 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000404
Scott Michel8efdca42007-12-04 22:23:35 +0000405 setShiftAmountType(MVT::i32);
Duncan Sands8cf4a822008-11-23 15:47:28 +0000406 setBooleanContents(ZeroOrOneBooleanContent);
Scott Michel4ec722e2008-07-16 17:17:29 +0000407
Scott Michel8efdca42007-12-04 22:23:35 +0000408 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel4ec722e2008-07-16 17:17:29 +0000409
Scott Michel8efdca42007-12-04 22:23:35 +0000410 // We have target-specific dag combine patterns for the following nodes:
Scott Michelf9f42e62008-01-29 02:16:57 +0000411 setTargetDAGCombine(ISD::ADD);
Scott Michel97872d32008-02-23 18:41:37 +0000412 setTargetDAGCombine(ISD::ZERO_EXTEND);
413 setTargetDAGCombine(ISD::SIGN_EXTEND);
414 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel4ec722e2008-07-16 17:17:29 +0000415
Scott Michel8efdca42007-12-04 22:23:35 +0000416 computeRegisterProperties();
Scott Michel56a125e2008-11-22 23:50:42 +0000417
418 // Set other properties:
419 setSchedulingPreference(SchedulingForLatency);
Scott Michel8efdca42007-12-04 22:23:35 +0000420}
421
422const char *
423SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
424{
425 if (node_names.empty()) {
426 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
427 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
428 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
429 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Micheldbac4cf2008-01-11 02:53:15 +0000430 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michelf9f42e62008-01-29 02:16:57 +0000431 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel8efdca42007-12-04 22:23:35 +0000432 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
433 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
434 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel56a125e2008-11-22 23:50:42 +0000435 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000436 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
437 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
Scott Michelc630c412008-11-24 17:11:17 +0000438 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
Scott Michel8efdca42007-12-04 22:23:35 +0000439 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
440 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
441 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
442 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michel97872d32008-02-23 18:41:37 +0000443 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
444 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel8efdca42007-12-04 22:23:35 +0000445 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
446 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
447 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
448 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
449 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michel97872d32008-02-23 18:41:37 +0000450 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
451 "SPUISD::ROTQUAD_RZ_BYTES";
452 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
453 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel8efdca42007-12-04 22:23:35 +0000454 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
Scott Michel67224b22008-06-02 22:18:03 +0000455 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
456 "SPUISD::ROTBYTES_LEFT_BITS";
457 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000458 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel67224b22008-06-02 22:18:03 +0000459 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
460 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
461 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
462 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel8efdca42007-12-04 22:23:35 +0000463 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
464 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
465 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
466 }
467
468 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
469
470 return ((i != node_names.end()) ? i->second : 0);
471}
472
Dan Gohman8181bd12008-07-27 21:46:04 +0000473MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands92c43912008-06-06 12:08:01 +0000474 MVT VT = Op.getValueType();
Scott Michela313fb02008-10-30 01:51:48 +0000475 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel53ab7792008-03-10 16:58:52 +0000476}
477
Scott Michel8efdca42007-12-04 22:23:35 +0000478//===----------------------------------------------------------------------===//
479// Calling convention code:
480//===----------------------------------------------------------------------===//
481
482#include "SPUGenCallingConv.inc"
483
484//===----------------------------------------------------------------------===//
485// LowerOperation implementation
486//===----------------------------------------------------------------------===//
487
Scott Micheldbac4cf2008-01-11 02:53:15 +0000488/// Aligned load common code for CellSPU
489/*!
490 \param[in] Op The SelectionDAG load or store operand
491 \param[in] DAG The selection DAG
492 \param[in] ST CellSPU subtarget information structure
493 \param[in,out] alignment Caller initializes this to the load or store node's
494 value from getAlignment(), may be updated while generating the aligned load
495 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
496 offset (divisible by 16, modulo 16 == 0)
497 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
498 offset of the preferred slot (modulo 16 != 0)
499 \param[in,out] VT Caller initializes this value type to the the load or store
500 node's loaded or stored value type; may be updated if an i1-extended load or
501 store.
502 \param[out] was16aligned true if the base pointer had 16-byte alignment,
503 otherwise false. Can help to determine if the chunk needs to be rotated.
504
505 Both load and store lowering load a block of data aligned on a 16-byte
506 boundary. This is the common aligned load code shared between both.
507 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000508static SDValue
509AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Micheldbac4cf2008-01-11 02:53:15 +0000510 LSBaseSDNode *LSN,
511 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands92c43912008-06-06 12:08:01 +0000512 MVT &VT, bool &was16aligned)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000513{
Duncan Sands92c43912008-06-06 12:08:01 +0000514 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000515 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman8181bd12008-07-27 21:46:04 +0000516 SDValue basePtr = LSN->getBasePtr();
517 SDValue chain = LSN->getChain();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000518
519 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greif1c80d112008-08-28 21:40:38 +0000520 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000521
Gabor Greife9f7f582008-08-31 15:37:04 +0000522 if (Op1.getOpcode() == ISD::Constant
523 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel394e26d2008-01-17 20:38:41 +0000524 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000525
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000526 alignOffs = (int) CN->getZExtValue();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000527 prefSlotOffs = (int) (alignOffs & 0xf);
528
529 // Adjust the rotation amount to ensure that the final result ends up in
530 // the preferred slot:
531 prefSlotOffs -= vtm->prefslot_byte;
532 basePtr = basePtr.getOperand(0);
533
Scott Michel394e26d2008-01-17 20:38:41 +0000534 // Loading from memory, can we adjust alignment?
535 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000536 SDValue APtr = basePtr.getOperand(0);
Scott Michel394e26d2008-01-17 20:38:41 +0000537 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
538 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
539 alignment = GSDN->getGlobal()->getAlignment();
540 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000541 }
542 } else {
543 alignOffs = 0;
544 prefSlotOffs = -vtm->prefslot_byte;
545 }
Scott Michelbc5fbc12008-04-30 00:30:08 +0000546 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
547 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
548 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
549 prefSlotOffs = (int) (alignOffs & 0xf);
550 prefSlotOffs -= vtm->prefslot_byte;
551 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000552 } else {
553 alignOffs = 0;
554 prefSlotOffs = -vtm->prefslot_byte;
555 }
556
557 if (alignment == 16) {
558 // Realign the base pointer as a D-Form address:
559 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel394e26d2008-01-17 20:38:41 +0000560 basePtr = DAG.getNode(ISD::ADD, PtrVT,
561 basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000562 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000563 }
564
565 // Emit the vector load:
566 was16aligned = true;
567 return DAG.getLoad(MVT::v16i8, chain, basePtr,
568 LSN->getSrcValue(), LSN->getSrcValueOffset(),
569 LSN->isVolatile(), 16);
570 }
571
572 // Unaligned load or we're using the "large memory" model, which means that
573 // we have to be very pessimistic:
Scott Michel394e26d2008-01-17 20:38:41 +0000574 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greife9f7f582008-08-31 15:37:04 +0000575 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
576 DAG.getConstant(0, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000577 }
578
579 // Add the offset
Scott Michelf9f42e62008-01-29 02:16:57 +0000580 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000581 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000582 was16aligned = false;
583 return DAG.getLoad(MVT::v16i8, chain, basePtr,
584 LSN->getSrcValue(), LSN->getSrcValueOffset(),
585 LSN->isVolatile(), 16);
586}
587
Scott Michel8efdca42007-12-04 22:23:35 +0000588/// Custom lower loads for CellSPU
589/*!
590 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
591 within a 16-byte block, we have to rotate to extract the requested element.
Scott Michel6ccefab2008-12-04 03:02:42 +0000592
593 For extending loads, we also want to ensure that the following sequence is
594 emitted, e.g. for MVT::f32 extending load to MVT::f64:
595
596\verbatim
597%1 v16i8,ch = load
598%2 v16i8,ch = rotate %1
599%3 v4f8, ch = bitconvert %2
600%4 f32 = vec2perfslot %3
601%5 f64 = fp_extend %4
602\endverbatim
603*/
Dan Gohman8181bd12008-07-27 21:46:04 +0000604static SDValue
605LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000606 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000607 SDValue the_chain = LN->getChain();
Scott Michel6ccefab2008-12-04 03:02:42 +0000608 MVT InVT = LN->getMemoryVT();
609 MVT OutVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000610 ISD::LoadExtType ExtType = LN->getExtensionType();
611 unsigned alignment = LN->getAlignment();
Dan Gohman8181bd12008-07-27 21:46:04 +0000612 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +0000613
Scott Michel8efdca42007-12-04 22:23:35 +0000614 switch (LN->getAddressingMode()) {
615 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000616 int offset, rotamt;
617 bool was16aligned;
Dan Gohman8181bd12008-07-27 21:46:04 +0000618 SDValue result =
Scott Michel6ccefab2008-12-04 03:02:42 +0000619 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, InVT,
620 was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000621
Gabor Greif1c80d112008-08-28 21:40:38 +0000622 if (result.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +0000623 return result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000624
625 the_chain = result.getValue(1);
626 // Rotate the chunk if necessary
627 if (rotamt < 0)
628 rotamt += 16;
Scott Michelabc58242008-01-11 21:01:19 +0000629 if (rotamt != 0 || !was16aligned) {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000630 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
631
Scott Michel6ccefab2008-12-04 03:02:42 +0000632 Ops[0] = result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000633 if (was16aligned) {
Scott Michel6ccefab2008-12-04 03:02:42 +0000634 Ops[1] = DAG.getConstant(rotamt, MVT::i16);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000635 } else {
Duncan Sands92c43912008-06-06 12:08:01 +0000636 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000637 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel6ccefab2008-12-04 03:02:42 +0000638 Ops[1] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel5a6f17b2008-01-30 02:55:46 +0000639 DAG.getConstant(rotamt, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000640 }
641
Scott Michel6ccefab2008-12-04 03:02:42 +0000642 result = DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v16i8, Ops, 2);
Scott Michel8efdca42007-12-04 22:23:35 +0000643 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000644
Scott Michel6ccefab2008-12-04 03:02:42 +0000645 // Convert the loaded v16i8 vector to the appropriate vector type
646 // specified by the operand:
647 MVT vecVT = MVT::getVectorVT(InVT, (128 / InVT.getSizeInBits()));
648 result = DAG.getNode(SPUISD::VEC2PREFSLOT, InVT,
649 DAG.getNode(ISD::BIT_CONVERT, vecVT, result));
Scott Michel4ec722e2008-07-16 17:17:29 +0000650
Scott Michel6ccefab2008-12-04 03:02:42 +0000651 // Handle extending loads by extending the scalar result:
652 if (ExtType == ISD::SEXTLOAD) {
653 result = DAG.getNode(ISD::SIGN_EXTEND, OutVT, result);
654 } else if (ExtType == ISD::ZEXTLOAD) {
655 result = DAG.getNode(ISD::ZERO_EXTEND, OutVT, result);
656 } else if (ExtType == ISD::EXTLOAD) {
657 unsigned NewOpc = ISD::ANY_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000658
Scott Michel6ccefab2008-12-04 03:02:42 +0000659 if (OutVT.isFloatingPoint())
660 NewOpc = ISD::FP_EXTEND;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000661
Scott Michel6ccefab2008-12-04 03:02:42 +0000662 result = DAG.getNode(NewOpc, OutVT, result);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000663 }
664
Scott Michel6ccefab2008-12-04 03:02:42 +0000665 SDVTList retvts = DAG.getVTList(OutVT, MVT::Other);
Dan Gohman8181bd12008-07-27 21:46:04 +0000666 SDValue retops[2] = {
Scott Michel394e26d2008-01-17 20:38:41 +0000667 result,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000668 the_chain
Scott Michel394e26d2008-01-17 20:38:41 +0000669 };
Scott Micheldbac4cf2008-01-11 02:53:15 +0000670
Scott Michel394e26d2008-01-17 20:38:41 +0000671 result = DAG.getNode(SPUISD::LDRESULT, retvts,
672 retops, sizeof(retops) / sizeof(retops[0]));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000673 return result;
Scott Michel8efdca42007-12-04 22:23:35 +0000674 }
675 case ISD::PRE_INC:
676 case ISD::PRE_DEC:
677 case ISD::POST_INC:
678 case ISD::POST_DEC:
679 case ISD::LAST_INDEXED_MODE:
680 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
681 "UNINDEXED\n";
682 cerr << (unsigned) LN->getAddressingMode() << "\n";
683 abort();
684 /*NOTREACHED*/
685 }
686
Dan Gohman8181bd12008-07-27 21:46:04 +0000687 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000688}
689
690/// Custom lower stores for CellSPU
691/*!
692 All CellSPU stores are aligned to 16-byte boundaries, so for elements
693 within a 16-byte block, we have to generate a shuffle to insert the
694 requested element into its place, then store the resulting block.
695 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000696static SDValue
697LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000698 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000699 SDValue Value = SN->getValue();
Duncan Sands92c43912008-06-06 12:08:01 +0000700 MVT VT = Value.getValueType();
701 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
702 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000703 unsigned alignment = SN->getAlignment();
Scott Michel8efdca42007-12-04 22:23:35 +0000704
705 switch (SN->getAddressingMode()) {
706 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000707 int chunk_offset, slot_offset;
708 bool was16aligned;
Scott Michel8efdca42007-12-04 22:23:35 +0000709
Scott Michel33d73eb2008-11-21 02:56:16 +0000710 // The vector type we really want to load from the 16-byte chunk.
Scott Michele1006032008-11-19 17:45:08 +0000711 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
712 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +0000713
Dan Gohman8181bd12008-07-27 21:46:04 +0000714 SDValue alignLoadVec =
Scott Micheldbac4cf2008-01-11 02:53:15 +0000715 AlignedLoad(Op, DAG, ST, SN, alignment,
716 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000717
Gabor Greif1c80d112008-08-28 21:40:38 +0000718 if (alignLoadVec.getNode() == 0)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000719 return alignLoadVec;
Scott Michel8efdca42007-12-04 22:23:35 +0000720
Scott Micheldbac4cf2008-01-11 02:53:15 +0000721 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman8181bd12008-07-27 21:46:04 +0000722 SDValue basePtr = LN->getBasePtr();
723 SDValue the_chain = alignLoadVec.getValue(1);
724 SDValue theValue = SN->getValue();
725 SDValue result;
Scott Michel8efdca42007-12-04 22:23:35 +0000726
727 if (StVT != VT
Scott Michel5a6f17b2008-01-30 02:55:46 +0000728 && (theValue.getOpcode() == ISD::AssertZext
729 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel8efdca42007-12-04 22:23:35 +0000730 // Drill down and get the value for zero- and sign-extended
731 // quantities
Scott Michel4ec722e2008-07-16 17:17:29 +0000732 theValue = theValue.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000733 }
734
Scott Micheldbac4cf2008-01-11 02:53:15 +0000735 chunk_offset &= 0xf;
Scott Michel8efdca42007-12-04 22:23:35 +0000736
Dan Gohman8181bd12008-07-27 21:46:04 +0000737 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
738 SDValue insertEltPtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000739
740 // If the base pointer is already a D-form address, then just create
741 // a new D-form address with a slot offset and the orignal base pointer.
742 // Otherwise generate a D-form address with the slot offset relative
743 // to the stack pointer, which is always aligned.
Scott Michelabc58242008-01-11 21:01:19 +0000744 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greif1c80d112008-08-28 21:40:38 +0000745 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michelabc58242008-01-11 21:01:19 +0000746 DEBUG(cerr << "\n");
747
Scott Michelf9f42e62008-01-29 02:16:57 +0000748 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
749 (basePtr.getOpcode() == ISD::ADD
750 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michelabc58242008-01-11 21:01:19 +0000751 insertEltPtr = basePtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000752 } else {
Scott Michelf9f42e62008-01-29 02:16:57 +0000753 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000754 }
755
Scott Michelf65c8f02008-11-19 15:24:16 +0000756 SDValue insertEltOp =
Scott Michel0718cd82008-12-01 17:56:02 +0000757 DAG.getNode(SPUISD::SHUFFLE_MASK, vecVT, insertEltPtr);
Scott Michele1006032008-11-19 17:45:08 +0000758 SDValue vectorizeOp =
759 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michelf65c8f02008-11-19 15:24:16 +0000760
Scott Michel0718cd82008-12-01 17:56:02 +0000761 result = DAG.getNode(SPUISD::SHUFB, vecVT,
762 vectorizeOp, alignLoadVec,
763 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, insertEltOp));
Scott Michel8efdca42007-12-04 22:23:35 +0000764
Scott Micheldbac4cf2008-01-11 02:53:15 +0000765 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel8efdca42007-12-04 22:23:35 +0000766 LN->getSrcValue(), LN->getSrcValueOffset(),
767 LN->isVolatile(), LN->getAlignment());
768
Scott Michel8c2746e2008-12-04 17:16:59 +0000769#if 0 && !defined(NDEBUG)
Scott Michelf65c8f02008-11-19 15:24:16 +0000770 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
771 const SDValue &currentRoot = DAG.getRoot();
772
773 DAG.setRoot(result);
774 cerr << "------- CellSPU:LowerStore result:\n";
775 DAG.dump();
776 cerr << "-------\n";
777 DAG.setRoot(currentRoot);
778 }
779#endif
Scott Michelec8c82e2008-12-02 19:53:53 +0000780
Scott Michel8efdca42007-12-04 22:23:35 +0000781 return result;
782 /*UNREACHED*/
783 }
784 case ISD::PRE_INC:
785 case ISD::PRE_DEC:
786 case ISD::POST_INC:
787 case ISD::POST_DEC:
788 case ISD::LAST_INDEXED_MODE:
789 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
790 "UNINDEXED\n";
791 cerr << (unsigned) SN->getAddressingMode() << "\n";
792 abort();
793 /*NOTREACHED*/
794 }
795
Dan Gohman8181bd12008-07-27 21:46:04 +0000796 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000797}
798
799/// Generate the address of a constant pool entry.
Dan Gohman8181bd12008-07-27 21:46:04 +0000800static SDValue
801LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000802 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000803 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
804 Constant *C = CP->getConstVal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000805 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
806 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000807 const TargetMachine &TM = DAG.getTarget();
Scott Michel8efdca42007-12-04 22:23:35 +0000808
809 if (TM.getRelocationModel() == Reloc::Static) {
810 if (!ST->usingLargeMem()) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000811 // Just return the SDValue with the constant pool address in it.
Scott Michel394e26d2008-01-17 20:38:41 +0000812 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +0000813 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000814 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
815 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000816 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel8efdca42007-12-04 22:23:35 +0000817 }
818 }
819
820 assert(0 &&
Gabor Greife9f7f582008-08-31 15:37:04 +0000821 "LowerConstantPool: Relocation model other than static"
822 " not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000823 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000824}
825
Dan Gohman8181bd12008-07-27 21:46:04 +0000826static SDValue
827LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000828 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000829 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000830 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
831 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000832 const TargetMachine &TM = DAG.getTarget();
833
834 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel97872d32008-02-23 18:41:37 +0000835 if (!ST->usingLargeMem()) {
836 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
837 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000838 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
839 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000840 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
841 }
Scott Michel8efdca42007-12-04 22:23:35 +0000842 }
843
844 assert(0 &&
845 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000846 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000847}
848
Dan Gohman8181bd12008-07-27 21:46:04 +0000849static SDValue
850LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000851 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000852 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
853 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000854 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel8efdca42007-12-04 22:23:35 +0000855 const TargetMachine &TM = DAG.getTarget();
Dan Gohman8181bd12008-07-27 21:46:04 +0000856 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel4ec722e2008-07-16 17:17:29 +0000857
Scott Michel8efdca42007-12-04 22:23:35 +0000858 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michelf9f42e62008-01-29 02:16:57 +0000859 if (!ST->usingLargeMem()) {
860 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
861 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000862 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
863 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michelf9f42e62008-01-29 02:16:57 +0000864 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
865 }
Scott Michel8efdca42007-12-04 22:23:35 +0000866 } else {
867 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel5a6f17b2008-01-30 02:55:46 +0000868 << "supported.\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000869 abort();
870 /*NOTREACHED*/
871 }
872
Dan Gohman8181bd12008-07-27 21:46:04 +0000873 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000874}
875
876//! Custom lower i64 integer constants
877/*!
878 This code inserts all of the necessary juggling that needs to occur to load
879 a 64-bit constant into a register.
880 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000881static SDValue
882LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000883 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000884
885 if (VT == MVT::i64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000886 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
887 SDValue T = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michelc630c412008-11-24 17:11:17 +0000888 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000889 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +0000890 } else {
891 cerr << "LowerConstant: unhandled constant type "
Duncan Sands92c43912008-06-06 12:08:01 +0000892 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +0000893 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000894 abort();
895 /*NOTREACHED*/
896 }
897
Dan Gohman8181bd12008-07-27 21:46:04 +0000898 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000899}
900
Nate Begeman78125042008-02-14 18:43:04 +0000901//! Custom lower double precision floating point constants
Dan Gohman8181bd12008-07-27 21:46:04 +0000902static SDValue
903LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000904 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000905
Nate Begeman78125042008-02-14 18:43:04 +0000906 if (VT == MVT::f64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000907 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
908
909 assert((FP != 0) &&
910 "LowerConstantFP: Node is not ConstantFPSDNode");
911
Scott Michel11e88bb2007-12-19 20:15:47 +0000912 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel0718cd82008-12-01 17:56:02 +0000913 SDValue T = DAG.getConstant(dbits, MVT::i64);
914 SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T);
915 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
916 DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64, Tvec));
Scott Michel8efdca42007-12-04 22:23:35 +0000917 }
918
Dan Gohman8181bd12008-07-27 21:46:04 +0000919 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000920}
921
Scott Michel33d73eb2008-11-21 02:56:16 +0000922//! Lower MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman8181bd12008-07-27 21:46:04 +0000923static SDValue
924LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel394e26d2008-01-17 20:38:41 +0000925{
Dan Gohman8181bd12008-07-27 21:46:04 +0000926 SDValue Cond = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +0000927 MVT CondVT = Cond.getValueType();
928 MVT CondNVT;
Scott Michel394e26d2008-01-17 20:38:41 +0000929
Scott Michel33d73eb2008-11-21 02:56:16 +0000930 if (CondVT == MVT::i8) {
931 CondNVT = MVT::i16;
Scott Michel394e26d2008-01-17 20:38:41 +0000932 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
933 Op.getOperand(0),
934 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
935 Op.getOperand(2));
936 } else
Dan Gohman8181bd12008-07-27 21:46:04 +0000937 return SDValue(); // Unchanged
Scott Michel394e26d2008-01-17 20:38:41 +0000938}
939
Dan Gohman8181bd12008-07-27 21:46:04 +0000940static SDValue
941LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel8efdca42007-12-04 22:23:35 +0000942{
943 MachineFunction &MF = DAG.getMachineFunction();
944 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner1b989192007-12-31 04:13:23 +0000945 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michela313fb02008-10-30 01:51:48 +0000946 SmallVector<SDValue, 48> ArgValues;
Dan Gohman8181bd12008-07-27 21:46:04 +0000947 SDValue Root = Op.getOperand(0);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000948 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel8efdca42007-12-04 22:23:35 +0000949
950 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
951 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel4ec722e2008-07-16 17:17:29 +0000952
Scott Michel8efdca42007-12-04 22:23:35 +0000953 unsigned ArgOffset = SPUFrameInfo::minStackSize();
954 unsigned ArgRegIdx = 0;
955 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel4ec722e2008-07-16 17:17:29 +0000956
Duncan Sands92c43912008-06-06 12:08:01 +0000957 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +0000958
Scott Michel8efdca42007-12-04 22:23:35 +0000959 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greife9f7f582008-08-31 15:37:04 +0000960 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
961 ArgNo != e; ++ArgNo) {
Duncan Sands92c43912008-06-06 12:08:01 +0000962 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
963 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michela313fb02008-10-30 01:51:48 +0000964 SDValue ArgVal;
Scott Michel8efdca42007-12-04 22:23:35 +0000965
Scott Michela313fb02008-10-30 01:51:48 +0000966 if (ArgRegIdx < NumArgRegs) {
967 const TargetRegisterClass *ArgRegClass;
Scott Michel4ec722e2008-07-16 17:17:29 +0000968
Scott Michela313fb02008-10-30 01:51:48 +0000969 switch (ObjectVT.getSimpleVT()) {
970 default: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000971 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
972 << ObjectVT.getMVTString()
973 << "\n";
974 abort();
Scott Michela313fb02008-10-30 01:51:48 +0000975 }
976 case MVT::i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000977 ArgRegClass = &SPU::R8CRegClass;
978 break;
Scott Michela313fb02008-10-30 01:51:48 +0000979 case MVT::i16:
Scott Michel33d73eb2008-11-21 02:56:16 +0000980 ArgRegClass = &SPU::R16CRegClass;
981 break;
Scott Michela313fb02008-10-30 01:51:48 +0000982 case MVT::i32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000983 ArgRegClass = &SPU::R32CRegClass;
984 break;
Scott Michela313fb02008-10-30 01:51:48 +0000985 case MVT::i64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000986 ArgRegClass = &SPU::R64CRegClass;
987 break;
Scott Michela313fb02008-10-30 01:51:48 +0000988 case MVT::f32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000989 ArgRegClass = &SPU::R32FPRegClass;
990 break;
Scott Michela313fb02008-10-30 01:51:48 +0000991 case MVT::f64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000992 ArgRegClass = &SPU::R64FPRegClass;
993 break;
Scott Michela313fb02008-10-30 01:51:48 +0000994 case MVT::v2f64:
995 case MVT::v4f32:
996 case MVT::v2i64:
997 case MVT::v4i32:
998 case MVT::v8i16:
999 case MVT::v16i8:
Scott Michel33d73eb2008-11-21 02:56:16 +00001000 ArgRegClass = &SPU::VECREGRegClass;
1001 break;
Scott Michela313fb02008-10-30 01:51:48 +00001002 }
1003
1004 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
1005 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
1006 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1007 ++ArgRegIdx;
1008 } else {
1009 // We need to load the argument to a virtual register if we determined
1010 // above that we ran out of physical registers of the appropriate type
1011 // or we're forced to do vararg
Chris Lattner60069452008-02-13 07:35:30 +00001012 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +00001013 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner60069452008-02-13 07:35:30 +00001014 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +00001015 ArgOffset += StackSlotSize;
1016 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001017
Scott Michel8efdca42007-12-04 22:23:35 +00001018 ArgValues.push_back(ArgVal);
Scott Michela313fb02008-10-30 01:51:48 +00001019 // Update the chain
1020 Root = ArgVal.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001021 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001022
Scott Michela313fb02008-10-30 01:51:48 +00001023 // vararg handling:
Scott Michel8efdca42007-12-04 22:23:35 +00001024 if (isVarArg) {
Scott Michela313fb02008-10-30 01:51:48 +00001025 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1026 // We will spill (79-3)+1 registers to the stack
1027 SmallVector<SDValue, 79-3+1> MemOps;
1028
1029 // Create the frame slot
1030
Scott Michel8efdca42007-12-04 22:23:35 +00001031 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Michela313fb02008-10-30 01:51:48 +00001032 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1033 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1034 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1035 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1036 Root = Store.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001037 MemOps.push_back(Store);
Scott Michela313fb02008-10-30 01:51:48 +00001038
1039 // Increment address by stack slot size for the next stored argument
1040 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001041 }
1042 if (!MemOps.empty())
Scott Michela313fb02008-10-30 01:51:48 +00001043 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001044 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001045
Scott Michel8efdca42007-12-04 22:23:35 +00001046 ArgValues.push_back(Root);
Scott Michel4ec722e2008-07-16 17:17:29 +00001047
Scott Michel8efdca42007-12-04 22:23:35 +00001048 // Return the new list of results.
Duncan Sands42d7bb82008-12-01 11:41:29 +00001049 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
1050 &ArgValues[0], ArgValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001051}
1052
1053/// isLSAAddress - Return the immediate to use if the specified
1054/// value is representable as a LSA address.
Dan Gohman8181bd12008-07-27 21:46:04 +00001055static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel5974f432008-11-11 03:06:06 +00001056 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel8efdca42007-12-04 22:23:35 +00001057 if (!C) return 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001058
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001059 int Addr = C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001060 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1061 (Addr << 14 >> 14) != Addr)
1062 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel4ec722e2008-07-16 17:17:29 +00001063
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001064 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel8efdca42007-12-04 22:23:35 +00001065}
1066
1067static
Dan Gohman8181bd12008-07-27 21:46:04 +00001068SDValue
1069LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001070 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1071 SDValue Chain = TheCall->getChain();
Dan Gohman705e3f72008-09-13 01:54:27 +00001072 SDValue Callee = TheCall->getCallee();
1073 unsigned NumOps = TheCall->getNumArgs();
Scott Michel8efdca42007-12-04 22:23:35 +00001074 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1075 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1076 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1077
1078 // Handy pointer type
Duncan Sands92c43912008-06-06 12:08:01 +00001079 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +00001080
Scott Michel8efdca42007-12-04 22:23:35 +00001081 // Accumulate how many bytes are to be pushed on the stack, including the
1082 // linkage area, and parameter passing area. According to the SPU ABI,
1083 // we minimally need space for [LR] and [SP]
1084 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel4ec722e2008-07-16 17:17:29 +00001085
Scott Michel8efdca42007-12-04 22:23:35 +00001086 // Set up a copy of the stack pointer for use loading and storing any
1087 // arguments that may not fit in the registers available for argument
1088 // passing.
Dan Gohman8181bd12008-07-27 21:46:04 +00001089 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel4ec722e2008-07-16 17:17:29 +00001090
Scott Michel8efdca42007-12-04 22:23:35 +00001091 // Figure out which arguments are going to go in registers, and which in
1092 // memory.
1093 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1094 unsigned ArgRegIdx = 0;
1095
1096 // Keep track of registers passing arguments
Dan Gohman8181bd12008-07-27 21:46:04 +00001097 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel8efdca42007-12-04 22:23:35 +00001098 // And the arguments passed on the stack
Dan Gohman8181bd12008-07-27 21:46:04 +00001099 SmallVector<SDValue, 8> MemOpChains;
Scott Michel8efdca42007-12-04 22:23:35 +00001100
1101 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001102 SDValue Arg = TheCall->getArg(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001103
Scott Michel8efdca42007-12-04 22:23:35 +00001104 // PtrOff will be used to store the current argument to the stack if a
1105 // register cannot be found for it.
Dan Gohman8181bd12008-07-27 21:46:04 +00001106 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel8efdca42007-12-04 22:23:35 +00001107 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1108
Duncan Sands92c43912008-06-06 12:08:01 +00001109 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001110 default: assert(0 && "Unexpected ValueType for argument!");
1111 case MVT::i32:
1112 case MVT::i64:
1113 case MVT::i128:
1114 if (ArgRegIdx != NumArgRegs) {
1115 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1116 } else {
1117 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001118 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001119 }
1120 break;
1121 case MVT::f32:
1122 case MVT::f64:
1123 if (ArgRegIdx != NumArgRegs) {
1124 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1125 } else {
1126 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001127 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001128 }
1129 break;
1130 case MVT::v4f32:
1131 case MVT::v4i32:
1132 case MVT::v8i16:
1133 case MVT::v16i8:
1134 if (ArgRegIdx != NumArgRegs) {
1135 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1136 } else {
1137 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001138 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001139 }
1140 break;
1141 }
1142 }
1143
1144 // Update number of stack bytes actually used, insert a call sequence start
1145 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001146 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1147 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001148
1149 if (!MemOpChains.empty()) {
1150 // Adjust the stack pointer for the stack arguments.
1151 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1152 &MemOpChains[0], MemOpChains.size());
1153 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001154
Scott Michel8efdca42007-12-04 22:23:35 +00001155 // Build a sequence of copy-to-reg nodes chained together with token chain
1156 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001157 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001158 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1159 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1160 InFlag);
1161 InFlag = Chain.getValue(1);
1162 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001163
Dan Gohman8181bd12008-07-27 21:46:04 +00001164 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001165 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001166
Bill Wendlingfef06052008-09-16 21:48:12 +00001167 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1168 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1169 // node so that legalize doesn't hack it.
Scott Michel5974f432008-11-11 03:06:06 +00001170 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001171 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001172 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001173 SDValue Zero = DAG.getConstant(0, PtrVT);
1174 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001175
Scott Micheldbac4cf2008-01-11 02:53:15 +00001176 if (!ST->usingLargeMem()) {
1177 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1178 // style calls, otherwise, external symbols are BRASL calls. This assumes
1179 // that declared/defined symbols are in the same compilation unit and can
1180 // be reached through PC-relative jumps.
1181 //
1182 // NOTE:
1183 // This may be an unsafe assumption for JIT and really large compilation
1184 // units.
1185 if (GV->isDeclaration()) {
1186 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1187 } else {
1188 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1189 }
Scott Michel8efdca42007-12-04 22:23:35 +00001190 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001191 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1192 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001193 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001194 }
Scott Michel5974f432008-11-11 03:06:06 +00001195 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendlingfef06052008-09-16 21:48:12 +00001196 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Micheldbac4cf2008-01-11 02:53:15 +00001197 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001198 // If this is an absolute destination address that appears to be a legal
1199 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001200 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001201 }
Scott Michel8efdca42007-12-04 22:23:35 +00001202
1203 Ops.push_back(Chain);
1204 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001205
Scott Michel8efdca42007-12-04 22:23:35 +00001206 // Add argument registers to the end of the list so that they are known live
1207 // into the call.
1208 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001209 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001210 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001211
Gabor Greif1c80d112008-08-28 21:40:38 +00001212 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001213 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001214 // Returns a chain and a flag for retval copy to use.
1215 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1216 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001217 InFlag = Chain.getValue(1);
1218
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001219 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1220 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001221 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001222 InFlag = Chain.getValue(1);
1223
Dan Gohman8181bd12008-07-27 21:46:04 +00001224 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001225 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001226
Scott Michel8efdca42007-12-04 22:23:35 +00001227 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001228 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001229 default: assert(0 && "Unexpected ret value!");
1230 case MVT::Other: break;
1231 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001232 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001233 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1234 ResultVals[0] = Chain.getValue(0);
1235 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1236 Chain.getValue(2)).getValue(1);
1237 ResultVals[1] = Chain.getValue(0);
1238 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001239 } else {
1240 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1241 ResultVals[0] = Chain.getValue(0);
1242 NumResults = 1;
1243 }
Scott Michel8efdca42007-12-04 22:23:35 +00001244 break;
1245 case MVT::i64:
1246 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1247 ResultVals[0] = Chain.getValue(0);
1248 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001249 break;
1250 case MVT::f32:
1251 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001252 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001253 InFlag).getValue(1);
1254 ResultVals[0] = Chain.getValue(0);
1255 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001256 break;
1257 case MVT::v2f64:
1258 case MVT::v4f32:
1259 case MVT::v4i32:
1260 case MVT::v8i16:
1261 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001262 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001263 InFlag).getValue(1);
1264 ResultVals[0] = Chain.getValue(0);
1265 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001266 break;
1267 }
Duncan Sands698842f2008-07-02 17:40:58 +00001268
Scott Michel8efdca42007-12-04 22:23:35 +00001269 // If the function returns void, just return the chain.
1270 if (NumResults == 0)
1271 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001272
Scott Michel8efdca42007-12-04 22:23:35 +00001273 // Otherwise, merge everything together with a MERGE_VALUES node.
1274 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001275 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001276 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001277}
1278
Dan Gohman8181bd12008-07-27 21:46:04 +00001279static SDValue
1280LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001281 SmallVector<CCValAssign, 16> RVLocs;
1282 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1283 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1284 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001285 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001286
Scott Michel8efdca42007-12-04 22:23:35 +00001287 // If this is the first return lowered for this function, add the regs to the
1288 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001289 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001290 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001291 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001292 }
1293
Dan Gohman8181bd12008-07-27 21:46:04 +00001294 SDValue Chain = Op.getOperand(0);
1295 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001296
Scott Michel8efdca42007-12-04 22:23:35 +00001297 // Copy the result values into the output registers.
1298 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1299 CCValAssign &VA = RVLocs[i];
1300 assert(VA.isRegLoc() && "Can only return in registers!");
1301 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1302 Flag = Chain.getValue(1);
1303 }
1304
Gabor Greif1c80d112008-08-28 21:40:38 +00001305 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001306 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1307 else
1308 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1309}
1310
1311
1312//===----------------------------------------------------------------------===//
1313// Vector related lowering:
1314//===----------------------------------------------------------------------===//
1315
1316static ConstantSDNode *
1317getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001318 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001319
Scott Michel8efdca42007-12-04 22:23:35 +00001320 // Check to see if this buildvec has a single non-undef value in its elements.
1321 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1322 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001323 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001324 OpVal = N->getOperand(i);
1325 else if (OpVal != N->getOperand(i))
1326 return 0;
1327 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001328
Gabor Greif1c80d112008-08-28 21:40:38 +00001329 if (OpVal.getNode() != 0) {
Scott Michel5974f432008-11-11 03:06:06 +00001330 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001331 return CN;
1332 }
1333 }
1334
1335 return 0; // All UNDEF: use implicit def.; not Constant node
1336}
1337
1338/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1339/// and the value fits into an unsigned 18-bit constant, and if so, return the
1340/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001341SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001342 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001343 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001344 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001345 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001346 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001347 uint32_t upper = uint32_t(UValue >> 32);
1348 uint32_t lower = uint32_t(UValue);
1349 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001350 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001351 Value = Value >> 32;
1352 }
Scott Michel8efdca42007-12-04 22:23:35 +00001353 if (Value <= 0x3ffff)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001354 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001355 }
1356
Dan Gohman8181bd12008-07-27 21:46:04 +00001357 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001358}
1359
1360/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1361/// and the value fits into a signed 16-bit constant, and if so, return the
1362/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001363SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001364 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001365 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001366 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001367 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001368 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001369 uint32_t upper = uint32_t(UValue >> 32);
1370 uint32_t lower = uint32_t(UValue);
1371 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001372 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001373 Value = Value >> 32;
1374 }
Scott Michel6baba072008-03-05 23:02:02 +00001375 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001376 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001377 }
1378 }
1379
Dan Gohman8181bd12008-07-27 21:46:04 +00001380 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001381}
1382
1383/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1384/// and the value fits into a signed 10-bit constant, and if so, return the
1385/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001386SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001387 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001388 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001389 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001390 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001391 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001392 uint32_t upper = uint32_t(UValue >> 32);
1393 uint32_t lower = uint32_t(UValue);
1394 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001395 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001396 Value = Value >> 32;
1397 }
Scott Michel6baba072008-03-05 23:02:02 +00001398 if (isS10Constant(Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001399 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001400 }
1401
Dan Gohman8181bd12008-07-27 21:46:04 +00001402 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001403}
1404
1405/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1406/// and the value fits into a signed 8-bit constant, and if so, return the
1407/// constant.
1408///
1409/// @note: The incoming vector is v16i8 because that's the only way we can load
1410/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1411/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001412SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001413 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001414 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001415 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001416 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001417 && Value <= 0xffff /* truncated from uint64_t */
1418 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001419 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001420 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001421 && (Value & 0xff) == Value)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001422 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001423 }
1424
Dan Gohman8181bd12008-07-27 21:46:04 +00001425 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001426}
1427
1428/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1429/// and the value fits into a signed 16-bit constant, and if so, return the
1430/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001431SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001432 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001433 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001434 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001435 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001436 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1437 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001438 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001439 }
1440
Dan Gohman8181bd12008-07-27 21:46:04 +00001441 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001442}
1443
1444/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001445SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001446 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001447 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001448 }
1449
Dan Gohman8181bd12008-07-27 21:46:04 +00001450 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001451}
1452
1453/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001454SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001455 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001456 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001457 }
1458
Dan Gohman8181bd12008-07-27 21:46:04 +00001459 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001460}
1461
1462// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001463// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001464// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1465// zero. Return true if this is not an array of constants, false if it is.
1466//
1467static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1468 uint64_t UndefBits[2]) {
1469 // Start with zero'd results.
1470 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001471
Duncan Sands92c43912008-06-06 12:08:01 +00001472 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001473 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001474 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001475
Scott Michel8efdca42007-12-04 22:23:35 +00001476 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1477 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1478
1479 uint64_t EltBits = 0;
1480 if (OpVal.getOpcode() == ISD::UNDEF) {
1481 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1482 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1483 continue;
Scott Michel5974f432008-11-11 03:06:06 +00001484 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001485 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel5974f432008-11-11 03:06:06 +00001486 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001487 const APFloat &apf = CN->getValueAPF();
1488 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001489 ? FloatToBits(apf.convertToFloat())
1490 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001491 } else {
1492 // Nonconstant element.
1493 return true;
1494 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001495
Scott Michel8efdca42007-12-04 22:23:35 +00001496 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1497 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001498
1499 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001500 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1501 return false;
1502}
1503
1504/// If this is a splat (repetition) of a value across the whole vector, return
1505/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001506/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001507/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001508static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001509 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001510 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001511 uint64_t &SplatBits, uint64_t &SplatUndef,
1512 int &SplatSize) {
1513 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1514 // the same as the lower 64-bits, ignoring undefs.
1515 uint64_t Bits64 = Bits128[0] | Bits128[1];
1516 uint64_t Undef64 = Undef128[0] & Undef128[1];
1517 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1518 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1519 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1520 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1521
1522 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1523 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001524
Scott Michel8efdca42007-12-04 22:23:35 +00001525 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1526 // undefs.
1527 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001528 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001529
Scott Michel5a6f17b2008-01-30 02:55:46 +00001530 // If the top 16-bits are different than the lower 16-bits, ignoring
1531 // undefs, we have an i32 splat.
1532 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1533 if (MinSplatBits < 16) {
1534 // If the top 8-bits are different than the lower 8-bits, ignoring
1535 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001536 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1537 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001538 // Otherwise, we have an 8-bit splat.
1539 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1540 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1541 SplatSize = 1;
1542 return true;
1543 }
1544 } else {
1545 SplatBits = Bits16;
1546 SplatUndef = Undef16;
1547 SplatSize = 2;
1548 return true;
1549 }
1550 }
1551 } else {
1552 SplatBits = Bits32;
1553 SplatUndef = Undef32;
1554 SplatSize = 4;
1555 return true;
1556 }
Scott Michel8efdca42007-12-04 22:23:35 +00001557 }
1558 } else {
1559 SplatBits = Bits128[0];
1560 SplatUndef = Undef128[0];
1561 SplatSize = 8;
1562 return true;
1563 }
1564 }
1565
1566 return false; // Can't be a splat if two pieces don't match.
1567}
1568
1569// If this is a case we can't handle, return null and let the default
1570// expansion code take care of it. If we CAN select this case, and if it
1571// selects to a single instruction, return Op. Otherwise, if we can codegen
1572// this case more efficiently than a constant pool load, lower it to the
1573// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001574static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001575 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001576 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001577 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001578 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001579 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001580 uint64_t VectorBits[2];
1581 uint64_t UndefBits[2];
1582 uint64_t SplatBits, SplatUndef;
1583 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001584 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001585 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001586 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001587 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001588 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001589
Duncan Sands92c43912008-06-06 12:08:01 +00001590 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001591 default:
1592 case MVT::v4f32: {
1593 uint32_t Value32 = SplatBits;
1594 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001595 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001596 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001597 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001598 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001599 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001600 break;
1601 }
1602 case MVT::v2f64: {
1603 uint64_t f64val = SplatBits;
1604 assert(SplatSize == 8
Scott Michelc630c412008-11-24 17:11:17 +00001605 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel8efdca42007-12-04 22:23:35 +00001606 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001607 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001608 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001609 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001610 break;
1611 }
1612 case MVT::v16i8: {
1613 // 8-bit constants have to be expanded to 16-bits
1614 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001615 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001616 for (int i = 0; i < 8; ++i)
1617 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1618 return DAG.getNode(ISD::BIT_CONVERT, VT,
1619 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1620 }
1621 case MVT::v8i16: {
1622 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001623 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001624 Value16 = (unsigned short) (SplatBits & 0xffff);
1625 else
1626 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001627 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1628 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001629 for (int i = 0; i < 8; ++i) Ops[i] = T;
1630 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1631 }
1632 case MVT::v4i32: {
1633 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001634 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001635 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1636 }
1637 case MVT::v2i64: {
1638 uint64_t val = SplatBits;
1639 uint32_t upper = uint32_t(val >> 32);
1640 uint32_t lower = uint32_t(val);
1641
Scott Michelbcc7b672008-03-06 04:02:54 +00001642 if (upper == lower) {
1643 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001644 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001645 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001646 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001647 SDValue LO32;
1648 SDValue HI32;
1649 SmallVector<SDValue, 16> ShufBytes;
1650 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001651 bool upper_special, lower_special;
1652
1653 // NOTE: This code creates common-case shuffle masks that can be easily
1654 // detected as common expressions. It is not attempting to create highly
1655 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1656
1657 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michelc630c412008-11-24 17:11:17 +00001658 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1659 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel8efdca42007-12-04 22:23:35 +00001660
1661 // Create lower vector if not a special pattern
1662 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001663 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001664 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1665 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1666 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001667 }
1668
1669 // Create upper vector if not a special pattern
1670 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001671 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001672 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1673 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1674 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001675 }
1676
1677 // If either upper or lower are special, then the two input operands are
1678 // the same (basically, one of them is a "don't care")
1679 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001680 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001681 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001682 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001683 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001684 // Unhappy situation... both upper and lower are special, so punt with
1685 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001686 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001687 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001688 Zero, Zero);
1689 }
1690
1691 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001692 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001693 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001694 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001695 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001696 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001697 process_upper = (upper_special && (i & 1) == 0);
1698 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001699
Scott Michel5a6f17b2008-01-30 02:55:46 +00001700 if (process_upper || process_lower) {
1701 if ((process_upper && upper == 0)
1702 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001703 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001704 else if ((process_upper && upper == 0xffffffff)
1705 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001706 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001707 else if ((process_upper && upper == 0x80000000)
1708 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001709 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001710 } else
Scott Michel67224b22008-06-02 22:18:03 +00001711 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001712 }
Scott Michel67224b22008-06-02 22:18:03 +00001713
1714 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001715 }
1716
1717 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001718 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001719 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001720 }
1721 }
1722 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001723
Dan Gohman8181bd12008-07-27 21:46:04 +00001724 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001725}
1726
1727/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1728/// which the Cell can operate. The code inspects V3 to ascertain whether the
1729/// permutation vector, V3, is monotonically increasing with one "exception"
1730/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel56a125e2008-11-22 23:50:42 +00001731/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel8efdca42007-12-04 22:23:35 +00001732/// In either case, the net result is going to eventually invoke SHUFB to
1733/// permute/shuffle the bytes from V1 and V2.
1734/// \note
Scott Michel56a125e2008-11-22 23:50:42 +00001735/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel8efdca42007-12-04 22:23:35 +00001736/// control word for byte/halfword/word insertion. This takes care of a single
1737/// element move from V2 into V1.
1738/// \note
1739/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001740static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1741 SDValue V1 = Op.getOperand(0);
1742 SDValue V2 = Op.getOperand(1);
1743 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001744
Scott Michel8efdca42007-12-04 22:23:35 +00001745 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001746
Scott Michel8efdca42007-12-04 22:23:35 +00001747 // If we have a single element being moved from V1 to V2, this can be handled
1748 // using the C*[DX] compute mask instructions, but the vector elements have
1749 // to be monotonically increasing with one exception element.
Duncan Sands92c43912008-06-06 12:08:01 +00001750 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001751 unsigned EltsFromV2 = 0;
1752 unsigned V2Elt = 0;
1753 unsigned V2EltIdx0 = 0;
1754 unsigned CurrElt = 0;
1755 bool monotonic = true;
1756 if (EltVT == MVT::i8)
1757 V2EltIdx0 = 16;
1758 else if (EltVT == MVT::i16)
1759 V2EltIdx0 = 8;
1760 else if (EltVT == MVT::i32)
1761 V2EltIdx0 = 4;
1762 else
1763 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1764
1765 for (unsigned i = 0, e = PermMask.getNumOperands();
1766 EltsFromV2 <= 1 && monotonic && i != e;
1767 ++i) {
1768 unsigned SrcElt;
1769 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1770 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001771 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001772 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001773
1774 if (SrcElt >= V2EltIdx0) {
1775 ++EltsFromV2;
1776 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1777 } else if (CurrElt != SrcElt) {
1778 monotonic = false;
1779 }
1780
1781 ++CurrElt;
1782 }
1783
1784 if (EltsFromV2 == 1 && monotonic) {
1785 // Compute mask and shuffle
1786 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001787 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1788 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001789 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001790 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001791 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001792 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel56a125e2008-11-22 23:50:42 +00001793 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001794 SDValue ShufMaskOp =
Scott Michel0718cd82008-12-01 17:56:02 +00001795 DAG.getNode(SPUISD::SHUFFLE_MASK, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001796 DAG.getTargetConstant(V2Elt, MVT::i32),
1797 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001798 // Use shuffle mask in SHUFB synthetic instruction:
1799 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1800 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001801 // Convert the SHUFFLE_VECTOR mask's input element units to the
1802 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001803 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001804
Dan Gohman8181bd12008-07-27 21:46:04 +00001805 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001806 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1807 unsigned SrcElt;
1808 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001809 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001810 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001811 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001812
Scott Michel97872d32008-02-23 18:41:37 +00001813 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001814 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1815 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001816 }
1817 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001818
Dan Gohman8181bd12008-07-27 21:46:04 +00001819 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel0718cd82008-12-01 17:56:02 +00001820 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001821 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1822 }
1823}
1824
Dan Gohman8181bd12008-07-27 21:46:04 +00001825static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1826 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001827
Gabor Greif1c80d112008-08-28 21:40:38 +00001828 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001829 // For a constant, build the appropriate constant vector, which will
1830 // eventually simplify to a vector register load.
1831
Gabor Greif1c80d112008-08-28 21:40:38 +00001832 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001833 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001834 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001835 size_t n_copies;
1836
1837 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001838 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001839 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001840 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001841 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1842 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1843 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1844 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1845 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1846 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1847 }
1848
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001849 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001850 for (size_t j = 0; j < n_copies; ++j)
1851 ConstVecValues.push_back(CValue);
1852
1853 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001854 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001855 } else {
1856 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001857 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001858 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1859 case MVT::i8:
1860 case MVT::i16:
1861 case MVT::i32:
1862 case MVT::i64:
1863 case MVT::f32:
1864 case MVT::f64:
1865 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1866 }
1867 }
1868
Dan Gohman8181bd12008-07-27 21:46:04 +00001869 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001870}
1871
Dan Gohman8181bd12008-07-27 21:46:04 +00001872static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001873 switch (Op.getValueType().getSimpleVT()) {
1874 default:
1875 cerr << "CellSPU: Unknown vector multiplication, got "
1876 << Op.getValueType().getMVTString()
1877 << "\n";
1878 abort();
1879 /*NOTREACHED*/
1880
Scott Michel8efdca42007-12-04 22:23:35 +00001881 case MVT::v4i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001882 SDValue rA = Op.getOperand(0);
1883 SDValue rB = Op.getOperand(1);
1884 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1885 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1886 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1887 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel8efdca42007-12-04 22:23:35 +00001888
1889 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1890 break;
1891 }
1892
1893 // Multiply two v8i16 vectors (pipeline friendly version):
1894 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1895 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1896 // c) Use SELB to select upper and lower halves from the intermediate results
1897 //
Scott Michel67224b22008-06-02 22:18:03 +00001898 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel8efdca42007-12-04 22:23:35 +00001899 // dual-issue. This code does manage to do this, even if it's a little on
1900 // the wacky side
1901 case MVT::v8i16: {
1902 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001903 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman8181bd12008-07-27 21:46:04 +00001904 SDValue Chain = Op.getOperand(0);
1905 SDValue rA = Op.getOperand(0);
1906 SDValue rB = Op.getOperand(1);
Chris Lattner1b989192007-12-31 04:13:23 +00001907 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1908 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00001909
Dan Gohman8181bd12008-07-27 21:46:04 +00001910 SDValue FSMBOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001911 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel67224b22008-06-02 22:18:03 +00001912 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001913 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel8efdca42007-12-04 22:23:35 +00001914
Dan Gohman8181bd12008-07-27 21:46:04 +00001915 SDValue HHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001916 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001917 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001918
Dan Gohman8181bd12008-07-27 21:46:04 +00001919 SDValue HHProd_v4i32 =
Scott Michel8efdca42007-12-04 22:23:35 +00001920 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001921 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001922
1923 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001924 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1925 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1926 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1927 HHProd_v4i32,
1928 DAG.getConstant(16, MVT::i16))),
1929 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001930 }
1931
1932 // This M00sE is N@stI! (apologies to Monty Python)
1933 //
1934 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1935 // is to break it all apart, sign extend, and reassemble the various
1936 // intermediate products.
1937 case MVT::v16i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001938 SDValue rA = Op.getOperand(0);
1939 SDValue rB = Op.getOperand(1);
1940 SDValue c8 = DAG.getConstant(8, MVT::i32);
1941 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001942
Dan Gohman8181bd12008-07-27 21:46:04 +00001943 SDValue LLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001944 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001945 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1946 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001947
Dan Gohman8181bd12008-07-27 21:46:04 +00001948 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001949
Dan Gohman8181bd12008-07-27 21:46:04 +00001950 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001951
Dan Gohman8181bd12008-07-27 21:46:04 +00001952 SDValue LHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001953 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001954 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001955
Dan Gohman8181bd12008-07-27 21:46:04 +00001956 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001957 DAG.getConstant(0x2222, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001958
Dan Gohman8181bd12008-07-27 21:46:04 +00001959 SDValue LoProdParts =
Scott Michel97872d32008-02-23 18:41:37 +00001960 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1961 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1962 LLProd, LHProd, FSMBmask));
Scott Michel8efdca42007-12-04 22:23:35 +00001963
Dan Gohman8181bd12008-07-27 21:46:04 +00001964 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001965
Dan Gohman8181bd12008-07-27 21:46:04 +00001966 SDValue LoProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001967 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michel97872d32008-02-23 18:41:37 +00001968 LoProdParts,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001969 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1970 LoProdMask, LoProdMask,
1971 LoProdMask, LoProdMask));
Scott Michel8efdca42007-12-04 22:23:35 +00001972
Dan Gohman8181bd12008-07-27 21:46:04 +00001973 SDValue rAH =
Scott Michel8efdca42007-12-04 22:23:35 +00001974 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001975 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001976
Dan Gohman8181bd12008-07-27 21:46:04 +00001977 SDValue rBH =
Scott Michel8efdca42007-12-04 22:23:35 +00001978 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001979 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001980
Dan Gohman8181bd12008-07-27 21:46:04 +00001981 SDValue HLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001982 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001983 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1984 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel8efdca42007-12-04 22:23:35 +00001985
Dan Gohman8181bd12008-07-27 21:46:04 +00001986 SDValue HHProd_1 =
Scott Michel8efdca42007-12-04 22:23:35 +00001987 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001988 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00001989 DAG.getNode(SPUISD::VEC_SRA,
1990 MVT::v4i32, rAH, c8)),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001991 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00001992 DAG.getNode(SPUISD::VEC_SRA,
1993 MVT::v4i32, rBH, c8)));
Scott Michel8efdca42007-12-04 22:23:35 +00001994
Dan Gohman8181bd12008-07-27 21:46:04 +00001995 SDValue HHProd =
Scott Michel97872d32008-02-23 18:41:37 +00001996 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1997 HLProd,
1998 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
1999 FSMBmask);
Scott Michel8efdca42007-12-04 22:23:35 +00002000
Dan Gohman8181bd12008-07-27 21:46:04 +00002001 SDValue HiProd =
Scott Michel97872d32008-02-23 18:41:37 +00002002 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002003
2004 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002005 DAG.getNode(ISD::OR, MVT::v4i32,
2006 LoProd, HiProd));
Scott Michel8efdca42007-12-04 22:23:35 +00002007 }
Scott Michel8efdca42007-12-04 22:23:35 +00002008 }
2009
Dan Gohman8181bd12008-07-27 21:46:04 +00002010 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002011}
2012
Dan Gohman8181bd12008-07-27 21:46:04 +00002013static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00002014 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002015 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002016
Dan Gohman8181bd12008-07-27 21:46:04 +00002017 SDValue A = Op.getOperand(0);
2018 SDValue B = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002019 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002020
2021 unsigned VRegBR, VRegC;
2022
2023 if (VT == MVT::f32) {
Chris Lattner1b989192007-12-31 04:13:23 +00002024 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2025 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002026 } else {
Chris Lattner1b989192007-12-31 04:13:23 +00002027 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2028 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002029 }
2030 // TODO: make sure we're feeding FPInterp the right arguments
2031 // Right now: fi B, frest(B)
2032
2033 // Computes BRcpl =
2034 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman8181bd12008-07-27 21:46:04 +00002035 SDValue BRcpl =
Scott Michel4ec722e2008-07-16 17:17:29 +00002036 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2037 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002038 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002039
Scott Michel8efdca42007-12-04 22:23:35 +00002040 // Computes A * BRcpl and stores in a temporary register
Dan Gohman8181bd12008-07-27 21:46:04 +00002041 SDValue AxBRcpl =
Scott Michel8efdca42007-12-04 22:23:35 +00002042 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel4ec722e2008-07-16 17:17:29 +00002043 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002044 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel8efdca42007-12-04 22:23:35 +00002045 // What's the Chain variable do? It's magic!
2046 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel4ec722e2008-07-16 17:17:29 +00002047
2048 return DAG.getNode(ISD::FADD, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002049 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel4ec722e2008-07-16 17:17:29 +00002050 DAG.getNode(ISD::FMUL, VT,
2051 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002052 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel4ec722e2008-07-16 17:17:29 +00002053 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002054 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel8efdca42007-12-04 22:23:35 +00002055}
2056
Dan Gohman8181bd12008-07-27 21:46:04 +00002057static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002058 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002059 SDValue N = Op.getOperand(0);
2060 SDValue Elt = Op.getOperand(1);
Scott Michel56a125e2008-11-22 23:50:42 +00002061 SDValue retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002062
Scott Michel56a125e2008-11-22 23:50:42 +00002063 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2064 // Constant argument:
2065 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002066
Scott Michel56a125e2008-11-22 23:50:42 +00002067 // sanity checks:
2068 if (VT == MVT::i8 && EltNo >= 16)
2069 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2070 else if (VT == MVT::i16 && EltNo >= 8)
2071 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2072 else if (VT == MVT::i32 && EltNo >= 4)
2073 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2074 else if (VT == MVT::i64 && EltNo >= 2)
2075 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel8efdca42007-12-04 22:23:35 +00002076
Scott Michel56a125e2008-11-22 23:50:42 +00002077 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2078 // i32 and i64: Element 0 is the preferred slot
Scott Michelc630c412008-11-24 17:11:17 +00002079 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel56a125e2008-11-22 23:50:42 +00002080 }
Scott Michel8efdca42007-12-04 22:23:35 +00002081
Scott Michel56a125e2008-11-22 23:50:42 +00002082 // Need to generate shuffle mask and extract:
2083 int prefslot_begin = -1, prefslot_end = -1;
2084 int elt_byte = EltNo * VT.getSizeInBits() / 8;
2085
2086 switch (VT.getSimpleVT()) {
2087 default:
2088 assert(false && "Invalid value type!");
2089 case MVT::i8: {
2090 prefslot_begin = prefslot_end = 3;
2091 break;
2092 }
2093 case MVT::i16: {
2094 prefslot_begin = 2; prefslot_end = 3;
2095 break;
2096 }
2097 case MVT::i32:
2098 case MVT::f32: {
2099 prefslot_begin = 0; prefslot_end = 3;
2100 break;
2101 }
2102 case MVT::i64:
2103 case MVT::f64: {
2104 prefslot_begin = 0; prefslot_end = 7;
2105 break;
2106 }
2107 }
2108
2109 assert(prefslot_begin != -1 && prefslot_end != -1 &&
2110 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2111
2112 unsigned int ShufBytes[16];
2113 for (int i = 0; i < 16; ++i) {
2114 // zero fill uppper part of preferred slot, don't care about the
2115 // other slots:
2116 unsigned int mask_val;
2117 if (i <= prefslot_end) {
2118 mask_val =
2119 ((i < prefslot_begin)
2120 ? 0x80
2121 : elt_byte + (i - prefslot_begin));
2122
2123 ShufBytes[i] = mask_val;
2124 } else
2125 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2126 }
2127
2128 SDValue ShufMask[4];
2129 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
2130 unsigned bidx = i / 4;
2131 unsigned int bits = ((ShufBytes[bidx] << 24) |
2132 (ShufBytes[bidx+1] << 16) |
2133 (ShufBytes[bidx+2] << 8) |
2134 ShufBytes[bidx+3]);
2135 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
2136 }
2137
2138 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2139 &ShufMask[0],
2140 sizeof(ShufMask) / sizeof(ShufMask[0]));
2141
Scott Michelc630c412008-11-24 17:11:17 +00002142 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel56a125e2008-11-22 23:50:42 +00002143 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2144 N, N, ShufMaskVec));
2145 } else {
2146 // Variable index: Rotate the requested element into slot 0, then replicate
2147 // slot 0 across the vector
2148 MVT VecVT = N.getValueType();
2149 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2150 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2151 abort();
2152 }
2153
2154 // Make life easier by making sure the index is zero-extended to i32
2155 if (Elt.getValueType() != MVT::i32)
2156 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2157
2158 // Scale the index to a bit/byte shift quantity
2159 APInt scaleFactor =
Scott Michelc630c412008-11-24 17:11:17 +00002160 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2161 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel56a125e2008-11-22 23:50:42 +00002162 SDValue vecShift;
Scott Michel56a125e2008-11-22 23:50:42 +00002163
Scott Michelc630c412008-11-24 17:11:17 +00002164 if (scaleShift > 0) {
2165 // Scale the shift factor:
Scott Michel56a125e2008-11-22 23:50:42 +00002166 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel0718cd82008-12-01 17:56:02 +00002167 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel56a125e2008-11-22 23:50:42 +00002168 }
2169
Scott Michelc630c412008-11-24 17:11:17 +00002170 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2171
2172 // Replicate the bytes starting at byte 0 across the entire vector (for
2173 // consistency with the notion of a unified register set)
Scott Michel56a125e2008-11-22 23:50:42 +00002174 SDValue replicate;
2175
2176 switch (VT.getSimpleVT()) {
2177 default:
2178 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2179 abort();
2180 /*NOTREACHED*/
2181 case MVT::i8: {
Scott Michelc630c412008-11-24 17:11:17 +00002182 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002183 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2184 factor, factor);
2185 break;
2186 }
2187 case MVT::i16: {
Scott Michelc630c412008-11-24 17:11:17 +00002188 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002189 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2190 factor, factor);
2191 break;
2192 }
2193 case MVT::i32:
2194 case MVT::f32: {
2195 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2196 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2197 factor, factor);
2198 break;
2199 }
2200 case MVT::i64:
2201 case MVT::f64: {
2202 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2203 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2204 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2205 loFactor, hiFactor);
2206 break;
2207 }
2208 }
2209
Scott Michelc630c412008-11-24 17:11:17 +00002210 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel0718cd82008-12-01 17:56:02 +00002211 DAG.getNode(SPUISD::SHUFB, VecVT,
2212 vecShift, vecShift, replicate));
Scott Michel8efdca42007-12-04 22:23:35 +00002213 }
2214
Scott Michel56a125e2008-11-22 23:50:42 +00002215 return retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002216}
2217
Dan Gohman8181bd12008-07-27 21:46:04 +00002218static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2219 SDValue VecOp = Op.getOperand(0);
2220 SDValue ValOp = Op.getOperand(1);
2221 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002222 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002223
2224 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2225 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2226
Duncan Sands92c43912008-06-06 12:08:01 +00002227 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel0718cd82008-12-01 17:56:02 +00002228 // Use $sp ($1) because it's always 16-byte aligned and it's available:
2229 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
2230 DAG.getRegister(SPU::R1, PtrVT),
2231 DAG.getConstant(CN->getSExtValue(), PtrVT));
2232 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, VT, Pointer);
Scott Michel8efdca42007-12-04 22:23:35 +00002233
Dan Gohman8181bd12008-07-27 21:46:04 +00002234 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002235 DAG.getNode(SPUISD::SHUFB, VT,
2236 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
Scott Michel0718cd82008-12-01 17:56:02 +00002237 VecOp,
2238 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, ShufMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002239
2240 return result;
2241}
2242
Dan Gohman8181bd12008-07-27 21:46:04 +00002243static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002244{
Dan Gohman8181bd12008-07-27 21:46:04 +00002245 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel8efdca42007-12-04 22:23:35 +00002246
2247 assert(Op.getValueType() == MVT::i8);
2248 switch (Opc) {
2249 default:
2250 assert(0 && "Unhandled i8 math operator");
2251 /*NOTREACHED*/
2252 break;
2253 case ISD::SUB: {
2254 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2255 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002256 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002257 N0 = (N0.getOpcode() != ISD::Constant
2258 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002259 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2260 MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00002261 N1 = (N1.getOpcode() != ISD::Constant
2262 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002263 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2264 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002265 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002266 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002267 }
Scott Michel8efdca42007-12-04 22:23:35 +00002268 case ISD::ROTR:
2269 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002270 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002271 unsigned N1Opc;
2272 N0 = (N0.getOpcode() != ISD::Constant
2273 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002274 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2275 MVT::i16));
Duncan Sands7aef60d2008-10-30 19:24:28 +00002276 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greife9f7f582008-08-31 15:37:04 +00002277 ? ISD::ZERO_EXTEND
2278 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002279 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sands7aef60d2008-10-30 19:24:28 +00002280 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002281 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sands7aef60d2008-10-30 19:24:28 +00002282 MVT::i32));
Dan Gohman8181bd12008-07-27 21:46:04 +00002283 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002284 DAG.getNode(ISD::OR, MVT::i16, N0,
2285 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sands7aef60d2008-10-30 19:24:28 +00002286 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002287 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002288 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2289 }
2290 case ISD::SRL:
2291 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002292 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002293 unsigned N1Opc;
2294 N0 = (N0.getOpcode() != ISD::Constant
2295 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002296 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2297 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002298 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2299 ? ISD::ZERO_EXTEND
2300 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002301 N1 = (N1.getOpcode() != ISD::Constant
2302 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002303 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2304 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002305 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002306 DAG.getNode(Opc, MVT::i16, N0, N1));
2307 }
2308 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002309 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002310 unsigned N1Opc;
2311 N0 = (N0.getOpcode() != ISD::Constant
2312 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002313 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2314 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002315 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2316 ? ISD::SIGN_EXTEND
2317 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002318 N1 = (N1.getOpcode() != ISD::Constant
2319 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002320 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2321 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002322 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002323 DAG.getNode(Opc, MVT::i16, N0, N1));
2324 }
2325 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002326 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002327 unsigned N1Opc;
2328 N0 = (N0.getOpcode() != ISD::Constant
2329 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002330 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2331 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002332 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002333 N1 = (N1.getOpcode() != ISD::Constant
2334 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002335 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2336 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002337 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002338 DAG.getNode(Opc, MVT::i16, N0, N1));
2339 break;
2340 }
2341 }
2342
Dan Gohman8181bd12008-07-27 21:46:04 +00002343 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002344}
2345
Dan Gohman8181bd12008-07-27 21:46:04 +00002346static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002347{
Duncan Sands92c43912008-06-06 12:08:01 +00002348 MVT VT = Op.getValueType();
2349 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002350
Dan Gohman8181bd12008-07-27 21:46:04 +00002351 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002352
2353 switch (Opc) {
2354 case ISD::ZERO_EXTEND:
2355 case ISD::SIGN_EXTEND:
2356 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002357 MVT Op0VT = Op0.getValueType();
2358 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002359
2360 assert(Op0VT == MVT::i32
2361 && "CellSPU: Zero/sign extending something other than i32");
2362
Scott Michelc630c412008-11-24 17:11:17 +00002363 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2364
Dan Gohman8181bd12008-07-27 21:46:04 +00002365 SDValue PromoteScalar =
Scott Michelc630c412008-11-24 17:11:17 +00002366 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
Scott Michel97872d32008-02-23 18:41:37 +00002367
Scott Michelc630c412008-11-24 17:11:17 +00002368 if (Opc != ISD::SIGN_EXTEND) {
Scott Michelf2df6cb2008-11-24 18:20:46 +00002369 // Use a shuffle to zero extend the i32 to i64 directly:
2370 SDValue shufMask =
2371 DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2372 DAG.getConstant(0x80808080, MVT::i32),
2373 DAG.getConstant(0x00010203, MVT::i32),
2374 DAG.getConstant(0x80808080, MVT::i32),
2375 DAG.getConstant(0x08090a0b, MVT::i32));
2376 SDValue zextShuffle =
2377 DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2378 PromoteScalar, PromoteScalar, shufMask);
2379
Scott Michelc630c412008-11-24 17:11:17 +00002380 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michelf2df6cb2008-11-24 18:20:46 +00002381 DAG.getNode(ISD::BIT_CONVERT, VecVT, zextShuffle));
Scott Michelc630c412008-11-24 17:11:17 +00002382 } else {
2383 // SPU has no "rotate quadword and replicate bit 0" (i.e. rotate/shift
2384 // right and propagate the sign bit) instruction.
Scott Michelf2df6cb2008-11-24 18:20:46 +00002385 SDValue RotQuad =
2386 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, Op0VecVT,
2387 PromoteScalar, DAG.getConstant(4, MVT::i32));
Scott Michelc630c412008-11-24 17:11:17 +00002388 SDValue SignQuad =
2389 DAG.getNode(SPUISD::VEC_SRA, Op0VecVT,
2390 PromoteScalar, DAG.getConstant(32, MVT::i32));
2391 SDValue SelMask =
2392 DAG.getNode(SPUISD::SELECT_MASK, Op0VecVT,
2393 DAG.getConstant(0xf0f0, MVT::i16));
2394 SDValue CombineQuad =
2395 DAG.getNode(SPUISD::SELB, Op0VecVT,
2396 SignQuad, RotQuad, SelMask);
2397
2398 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2399 DAG.getNode(ISD::BIT_CONVERT, VecVT, CombineQuad));
2400 }
Scott Michel97872d32008-02-23 18:41:37 +00002401 }
2402
Scott Michel67224b22008-06-02 22:18:03 +00002403 case ISD::ADD: {
2404 // Turn operands into vectors to satisfy type checking (shufb works on
2405 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002406 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002407 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002408 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002409 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002410 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002411
2412 // Create the shuffle mask for "rotating" the borrow up one register slot
2413 // once the borrow is generated.
2414 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2415 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2416 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2417 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2418
Dan Gohman8181bd12008-07-27 21:46:04 +00002419 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002420 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002421 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002422 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2423 CarryGen, CarryGen,
2424 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2425 &ShufBytes[0], ShufBytes.size()));
2426
Scott Michelc630c412008-11-24 17:11:17 +00002427 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002428 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2429 Op0, Op1, ShiftedCarry));
2430 }
2431
2432 case ISD::SUB: {
2433 // Turn operands into vectors to satisfy type checking (shufb works on
2434 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002435 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002436 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002437 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002438 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002439 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002440
2441 // Create the shuffle mask for "rotating" the borrow up one register slot
2442 // once the borrow is generated.
2443 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2444 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2445 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2446 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2447
Dan Gohman8181bd12008-07-27 21:46:04 +00002448 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002449 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002450 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002451 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2452 BorrowGen, BorrowGen,
2453 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2454 &ShufBytes[0], ShufBytes.size()));
2455
Scott Michelc630c412008-11-24 17:11:17 +00002456 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002457 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2458 Op0, Op1, ShiftedBorrow));
2459 }
2460
Scott Michel97872d32008-02-23 18:41:37 +00002461 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002462 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002463 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002464 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2465 SDValue MaskLower =
Scott Michel97872d32008-02-23 18:41:37 +00002466 DAG.getNode(SPUISD::SELB, VecVT,
2467 Op0Vec,
2468 DAG.getConstant(0, VecVT),
Scott Michel67224b22008-06-02 22:18:03 +00002469 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michel97872d32008-02-23 18:41:37 +00002470 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman8181bd12008-07-27 21:46:04 +00002471 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002472 DAG.getNode(ISD::SRL, ShiftAmtVT,
2473 ShiftAmt,
2474 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002475 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002476 DAG.getNode(ISD::AND, ShiftAmtVT,
2477 ShiftAmt,
2478 DAG.getConstant(7, ShiftAmtVT));
2479
Scott Michelc630c412008-11-24 17:11:17 +00002480 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel97872d32008-02-23 18:41:37 +00002481 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2482 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2483 MaskLower, ShiftAmtBytes),
2484 ShiftAmtBits));
2485 }
2486
2487 case ISD::SRL: {
Duncan Sands92c43912008-06-06 12:08:01 +00002488 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002489 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002490 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002491 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002492 DAG.getNode(ISD::SRL, ShiftAmtVT,
2493 ShiftAmt,
2494 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002495 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002496 DAG.getNode(ISD::AND, ShiftAmtVT,
2497 ShiftAmt,
2498 DAG.getConstant(7, ShiftAmtVT));
2499
2500 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2501 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2502 Op0, ShiftAmtBytes),
2503 ShiftAmtBits);
2504 }
Scott Michel67224b22008-06-02 22:18:03 +00002505
2506 case ISD::SRA: {
2507 // Promote Op0 to vector
Dan Gohman8181bd12008-07-27 21:46:04 +00002508 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002509 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002510 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002511 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel67224b22008-06-02 22:18:03 +00002512
2513 // Negate variable shift amounts
2514 if (!isa<ConstantSDNode>(ShiftAmt)) {
2515 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2516 DAG.getConstant(0, ShiftVT), ShiftAmt);
2517 }
2518
Dan Gohman8181bd12008-07-27 21:46:04 +00002519 SDValue UpperHalfSign =
Scott Michelc630c412008-11-24 17:11:17 +00002520 DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i32,
Scott Michel67224b22008-06-02 22:18:03 +00002521 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2522 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2523 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman8181bd12008-07-27 21:46:04 +00002524 SDValue UpperHalfSignMask =
Scott Michel67224b22008-06-02 22:18:03 +00002525 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman8181bd12008-07-27 21:46:04 +00002526 SDValue UpperLowerMask =
Scott Michel67224b22008-06-02 22:18:03 +00002527 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2528 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman8181bd12008-07-27 21:46:04 +00002529 SDValue UpperLowerSelect =
Scott Michel67224b22008-06-02 22:18:03 +00002530 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2531 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman8181bd12008-07-27 21:46:04 +00002532 SDValue RotateLeftBytes =
Scott Michel67224b22008-06-02 22:18:03 +00002533 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2534 UpperLowerSelect, ShiftAmt);
Dan Gohman8181bd12008-07-27 21:46:04 +00002535 SDValue RotateLeftBits =
Scott Michel67224b22008-06-02 22:18:03 +00002536 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2537 RotateLeftBytes, ShiftAmt);
2538
Scott Michelc630c412008-11-24 17:11:17 +00002539 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002540 RotateLeftBits);
2541 }
Scott Michel97872d32008-02-23 18:41:37 +00002542 }
2543
Dan Gohman8181bd12008-07-27 21:46:04 +00002544 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002545}
2546
Scott Michel8efdca42007-12-04 22:23:35 +00002547//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002548static SDValue
2549LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2550 SDValue ConstVec;
2551 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002552 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002553
2554 ConstVec = Op.getOperand(0);
2555 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002556 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2557 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002558 ConstVec = ConstVec.getOperand(0);
2559 } else {
2560 ConstVec = Op.getOperand(1);
2561 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002562 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002563 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002564 }
2565 }
2566 }
2567
Gabor Greif1c80d112008-08-28 21:40:38 +00002568 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002569 uint64_t VectorBits[2];
2570 uint64_t UndefBits[2];
2571 uint64_t SplatBits, SplatUndef;
2572 int SplatSize;
2573
Gabor Greif1c80d112008-08-28 21:40:38 +00002574 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002575 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002576 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002577 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002578 SDValue tcVec[16];
2579 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002580 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2581
2582 // Turn the BUILD_VECTOR into a set of target constants:
2583 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002584 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002585
Gabor Greif1c80d112008-08-28 21:40:38 +00002586 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002587 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002588 }
2589 }
Nate Begeman7569e762008-07-29 19:07:27 +00002590 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2591 // lowered. Return the operation, rather than a null SDValue.
2592 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002593}
2594
2595//! Lower i32 multiplication
Dan Gohman8181bd12008-07-27 21:46:04 +00002596static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel8efdca42007-12-04 22:23:35 +00002597 unsigned Opc) {
Duncan Sands92c43912008-06-06 12:08:01 +00002598 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00002599 default:
2600 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands92c43912008-06-06 12:08:01 +00002601 << Op.getValueType().getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +00002602 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +00002603 abort();
2604 /*NOTREACHED*/
2605
2606 case MVT::i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002607 SDValue rA = Op.getOperand(0);
2608 SDValue rB = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002609
2610 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002611 DAG.getNode(ISD::ADD, MVT::i32,
2612 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2613 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2614 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00002615 }
2616 }
2617
Dan Gohman8181bd12008-07-27 21:46:04 +00002618 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002619}
2620
2621//! Custom lowering for CTPOP (count population)
2622/*!
2623 Custom lowering code that counts the number ones in the input
2624 operand. SPU has such an instruction, but it counts the number of
2625 ones per byte, which then have to be accumulated.
2626*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002627static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002628 MVT VT = Op.getValueType();
2629 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002630
Duncan Sands92c43912008-06-06 12:08:01 +00002631 switch (VT.getSimpleVT()) {
2632 default:
2633 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002634 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002635 SDValue N = Op.getOperand(0);
2636 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002637
Dan Gohman8181bd12008-07-27 21:46:04 +00002638 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2639 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002640
2641 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2642 }
2643
2644 case MVT::i16: {
2645 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002646 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002647
Chris Lattner1b989192007-12-31 04:13:23 +00002648 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002649
Dan Gohman8181bd12008-07-27 21:46:04 +00002650 SDValue N = Op.getOperand(0);
2651 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2652 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sands7aef60d2008-10-30 19:24:28 +00002653 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002654
Dan Gohman8181bd12008-07-27 21:46:04 +00002655 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2656 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002657
2658 // CNTB_result becomes the chain to which all of the virtual registers
2659 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002660 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002661 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002662
Dan Gohman8181bd12008-07-27 21:46:04 +00002663 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002664 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2665
Dan Gohman8181bd12008-07-27 21:46:04 +00002666 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002667
2668 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002669 DAG.getNode(ISD::ADD, MVT::i16,
2670 DAG.getNode(ISD::SRL, MVT::i16,
2671 Tmp1, Shift1),
2672 Tmp1),
2673 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002674 }
2675
2676 case MVT::i32: {
2677 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002678 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002679
Chris Lattner1b989192007-12-31 04:13:23 +00002680 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2681 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002682
Dan Gohman8181bd12008-07-27 21:46:04 +00002683 SDValue N = Op.getOperand(0);
2684 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2685 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2686 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2687 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002688
Dan Gohman8181bd12008-07-27 21:46:04 +00002689 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2690 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002691
2692 // CNTB_result becomes the chain to which all of the virtual registers
2693 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002694 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002695 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002696
Dan Gohman8181bd12008-07-27 21:46:04 +00002697 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002698 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2699
Dan Gohman8181bd12008-07-27 21:46:04 +00002700 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002701 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002702 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002703
Dan Gohman8181bd12008-07-27 21:46:04 +00002704 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002705 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002706 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002707
Dan Gohman8181bd12008-07-27 21:46:04 +00002708 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002709 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2710
Dan Gohman8181bd12008-07-27 21:46:04 +00002711 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002712 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002713 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2714 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002715 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002716 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002717 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002718
2719 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2720 }
2721
2722 case MVT::i64:
2723 break;
2724 }
2725
Dan Gohman8181bd12008-07-27 21:46:04 +00002726 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002727}
2728
Scott Michel56a125e2008-11-22 23:50:42 +00002729//! Lower ISD::SELECT_CC
2730/*!
2731 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2732 SELB instruction.
2733
2734 \note Need to revisit this in the future: if the code path through the true
2735 and false value computations is longer than the latency of a branch (6
2736 cycles), then it would be more advantageous to branch and insert a new basic
2737 block and branch on the condition. However, this code does not make that
2738 assumption, given the simplisitc uses so far.
2739 */
2740
2741static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
2742 MVT VT = Op.getValueType();
2743 SDValue lhs = Op.getOperand(0);
2744 SDValue rhs = Op.getOperand(1);
2745 SDValue trueval = Op.getOperand(2);
2746 SDValue falseval = Op.getOperand(3);
2747 SDValue condition = Op.getOperand(4);
2748
2749 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2750 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2751 // with another "cannot select select_cc" assert:
2752
2753 SDValue compare = DAG.getNode(ISD::SETCC, VT, lhs, rhs, condition);
2754 return DAG.getNode(SPUISD::SELB, VT, trueval, falseval, compare);
2755}
2756
Scott Michelec8c82e2008-12-02 19:53:53 +00002757//! Custom lower ISD::TRUNCATE
2758static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
2759{
2760 MVT VT = Op.getValueType();
2761 MVT::SimpleValueType simpleVT = VT.getSimpleVT();
2762 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
2763
2764 SDValue Op0 = Op.getOperand(0);
2765 MVT Op0VT = Op0.getValueType();
2766 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
2767
2768 SDValue PromoteScalar = DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2769
2770 unsigned maskLow;
2771 unsigned maskHigh;
2772
2773 // Create shuffle mask
2774 switch (Op0VT.getSimpleVT()) {
2775 case MVT::i128:
2776 switch (simpleVT) {
2777 case MVT::i64:
2778 // least significant doubleword of quadword
2779 maskHigh = 0x08090a0b;
2780 maskLow = 0x0c0d0e0f;
2781 break;
2782 case MVT::i32:
2783 // least significant word of quadword
2784 maskHigh = maskLow = 0x0c0d0e0f;
2785 break;
2786 case MVT::i16:
2787 // least significant halfword of quadword
2788 maskHigh = maskLow = 0x0e0f0e0f;
2789 break;
2790 case MVT::i8:
2791 // least significant byte of quadword
2792 maskHigh = maskLow = 0x0f0f0f0f;
2793 break;
2794 default:
2795 cerr << "Truncation to illegal type!";
2796 abort();
2797 }
2798 break;
2799 case MVT::i64:
2800 switch (simpleVT) {
2801 case MVT::i32:
2802 // least significant word of doubleword
2803 maskHigh = maskLow = 0x04050607;
2804 break;
2805 case MVT::i16:
2806 // least significant halfword of doubleword
2807 maskHigh = maskLow = 0x06070607;
2808 break;
2809 case MVT::i8:
2810 // least significant byte of doubleword
2811 maskHigh = maskLow = 0x07070707;
2812 break;
2813 default:
2814 cerr << "Truncation to illegal type!";
2815 abort();
2816 }
2817 break;
2818 case MVT::i32:
2819 case MVT::i16:
2820 switch (simpleVT) {
2821 case MVT::i16:
2822 // least significant halfword of word
2823 maskHigh = maskLow = 0x02030203;
2824 break;
2825 case MVT::i8:
2826 // least significant byte of word/halfword
2827 maskHigh = maskLow = 0x03030303;
2828 break;
2829 default:
2830 cerr << "Truncation to illegal type!";
2831 abort();
2832 }
2833 break;
2834 default:
2835 cerr << "Trying to lower truncation from illegal type!";
2836 abort();
2837 }
2838
2839 // Use a shuffle to perform the truncation
2840 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2841 DAG.getConstant(maskHigh, MVT::i32),
2842 DAG.getConstant(maskLow, MVT::i32),
2843 DAG.getConstant(maskHigh, MVT::i32),
2844 DAG.getConstant(maskLow, MVT::i32));
2845
2846 SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2847 PromoteScalar, PromoteScalar, shufMask);
2848
2849 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2850 DAG.getNode(ISD::BIT_CONVERT, VecVT, truncShuffle));
2851}
2852
Scott Michel56a125e2008-11-22 23:50:42 +00002853//! Custom (target-specific) lowering entry point
2854/*!
2855 This is where LLVM's DAG selection process calls to do target-specific
2856 lowering of nodes.
2857 */
Dan Gohman8181bd12008-07-27 21:46:04 +00002858SDValue
2859SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel8efdca42007-12-04 22:23:35 +00002860{
Scott Michel97872d32008-02-23 18:41:37 +00002861 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands92c43912008-06-06 12:08:01 +00002862 MVT VT = Op.getValueType();
Scott Michel97872d32008-02-23 18:41:37 +00002863
2864 switch (Opc) {
Scott Michel8efdca42007-12-04 22:23:35 +00002865 default: {
2866 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michel97872d32008-02-23 18:41:37 +00002867 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greif1c80d112008-08-28 21:40:38 +00002868 cerr << "*Op.getNode():\n";
2869 Op.getNode()->dump();
Scott Michel8efdca42007-12-04 22:23:35 +00002870 abort();
2871 }
2872 case ISD::LOAD:
Scott Michelec8c82e2008-12-02 19:53:53 +00002873 case ISD::EXTLOAD:
Scott Michel8efdca42007-12-04 22:23:35 +00002874 case ISD::SEXTLOAD:
2875 case ISD::ZEXTLOAD:
2876 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2877 case ISD::STORE:
2878 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2879 case ISD::ConstantPool:
2880 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2881 case ISD::GlobalAddress:
2882 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2883 case ISD::JumpTable:
2884 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2885 case ISD::Constant:
2886 return LowerConstant(Op, DAG);
2887 case ISD::ConstantFP:
2888 return LowerConstantFP(Op, DAG);
Scott Michel394e26d2008-01-17 20:38:41 +00002889 case ISD::BRCOND:
2890 return LowerBRCOND(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002891 case ISD::FORMAL_ARGUMENTS:
Scott Michel394e26d2008-01-17 20:38:41 +00002892 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel8efdca42007-12-04 22:23:35 +00002893 case ISD::CALL:
Scott Micheldbac4cf2008-01-11 02:53:15 +00002894 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel8efdca42007-12-04 22:23:35 +00002895 case ISD::RET:
2896 return LowerRET(Op, DAG, getTargetMachine());
2897
Scott Michel97872d32008-02-23 18:41:37 +00002898
2899 // i8, i64 math ops:
2900 case ISD::ZERO_EXTEND:
2901 case ISD::SIGN_EXTEND:
2902 case ISD::ANY_EXTEND:
Scott Michel67224b22008-06-02 22:18:03 +00002903 case ISD::ADD:
Scott Michel8efdca42007-12-04 22:23:35 +00002904 case ISD::SUB:
2905 case ISD::ROTR:
2906 case ISD::ROTL:
2907 case ISD::SRL:
2908 case ISD::SHL:
Scott Michel67224b22008-06-02 22:18:03 +00002909 case ISD::SRA: {
Scott Michel97872d32008-02-23 18:41:37 +00002910 if (VT == MVT::i8)
2911 return LowerI8Math(Op, DAG, Opc);
2912 else if (VT == MVT::i64)
2913 return LowerI64Math(Op, DAG, Opc);
2914 break;
Scott Michel67224b22008-06-02 22:18:03 +00002915 }
Scott Michel8efdca42007-12-04 22:23:35 +00002916
2917 // Vector-related lowering.
2918 case ISD::BUILD_VECTOR:
2919 return LowerBUILD_VECTOR(Op, DAG);
2920 case ISD::SCALAR_TO_VECTOR:
2921 return LowerSCALAR_TO_VECTOR(Op, DAG);
2922 case ISD::VECTOR_SHUFFLE:
2923 return LowerVECTOR_SHUFFLE(Op, DAG);
2924 case ISD::EXTRACT_VECTOR_ELT:
2925 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2926 case ISD::INSERT_VECTOR_ELT:
2927 return LowerINSERT_VECTOR_ELT(Op, DAG);
2928
2929 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2930 case ISD::AND:
2931 case ISD::OR:
2932 case ISD::XOR:
2933 return LowerByteImmed(Op, DAG);
2934
2935 // Vector and i8 multiply:
2936 case ISD::MUL:
Duncan Sands92c43912008-06-06 12:08:01 +00002937 if (VT.isVector())
Scott Michel8efdca42007-12-04 22:23:35 +00002938 return LowerVectorMUL(Op, DAG);
Scott Michel97872d32008-02-23 18:41:37 +00002939 else if (VT == MVT::i8)
2940 return LowerI8Math(Op, DAG, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002941 else
Scott Michel97872d32008-02-23 18:41:37 +00002942 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002943
2944 case ISD::FDIV:
Scott Michel97872d32008-02-23 18:41:37 +00002945 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel8efdca42007-12-04 22:23:35 +00002946 return LowerFDIVf32(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002947#if 0
2948 // This is probably a libcall
2949 else if (Op.getValueType() == MVT::f64)
2950 return LowerFDIVf64(Op, DAG);
2951#endif
Scott Michel8efdca42007-12-04 22:23:35 +00002952 else
2953 assert(0 && "Calling FDIV on unsupported MVT");
2954
2955 case ISD::CTPOP:
2956 return LowerCTPOP(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002957
2958 case ISD::SELECT_CC:
2959 return LowerSELECT_CC(Op, DAG);
Scott Michelec8c82e2008-12-02 19:53:53 +00002960
2961 case ISD::TRUNCATE:
2962 return LowerTRUNCATE(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002963 }
2964
Dan Gohman8181bd12008-07-27 21:46:04 +00002965 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002966}
2967
Duncan Sands7d9834b2008-12-01 11:39:25 +00002968void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
2969 SmallVectorImpl<SDValue>&Results,
2970 SelectionDAG &DAG)
Scott Michel6e2d68b2008-11-10 23:43:06 +00002971{
2972#if 0
2973 unsigned Opc = (unsigned) N->getOpcode();
2974 MVT OpVT = N->getValueType(0);
2975
2976 switch (Opc) {
2977 default: {
2978 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2979 cerr << "Op.getOpcode() = " << Opc << "\n";
2980 cerr << "*Op.getNode():\n";
2981 N->dump();
2982 abort();
2983 /*NOTREACHED*/
2984 }
2985 }
2986#endif
2987
2988 /* Otherwise, return unchanged */
Scott Michel6e2d68b2008-11-10 23:43:06 +00002989}
2990
Scott Michel8efdca42007-12-04 22:23:35 +00002991//===----------------------------------------------------------------------===//
Scott Michel8efdca42007-12-04 22:23:35 +00002992// Target Optimization Hooks
2993//===----------------------------------------------------------------------===//
2994
Dan Gohman8181bd12008-07-27 21:46:04 +00002995SDValue
Scott Michel8efdca42007-12-04 22:23:35 +00002996SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2997{
2998#if 0
2999 TargetMachine &TM = getTargetMachine();
Scott Michelf9f42e62008-01-29 02:16:57 +00003000#endif
3001 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel8efdca42007-12-04 22:23:35 +00003002 SelectionDAG &DAG = DCI.DAG;
Scott Michel0718cd82008-12-01 17:56:02 +00003003 SDValue Op0 = N->getOperand(0); // everything has at least one operand
3004 MVT NodeVT = N->getValueType(0); // The node's value type
3005 MVT Op0VT = Op0.getValueType(); // The first operand's result
3006 SDValue Result; // Initially, empty result
Scott Michel8efdca42007-12-04 22:23:35 +00003007
3008 switch (N->getOpcode()) {
3009 default: break;
Scott Michelf9f42e62008-01-29 02:16:57 +00003010 case ISD::ADD: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003011 SDValue Op1 = N->getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003012
Scott Michel67224b22008-06-02 22:18:03 +00003013 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003014 SDValue Op01 = Op0.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003015 if (Op01.getOpcode() == ISD::Constant
3016 || Op01.getOpcode() == ISD::TargetConstant) {
3017 // (add <const>, (SPUindirect <arg>, <const>)) ->
3018 // (SPUindirect <arg>, <const + const>)
3019 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
3020 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman8181bd12008-07-27 21:46:04 +00003021 SDValue combinedConst =
Scott Michel0718cd82008-12-01 17:56:02 +00003022 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(), Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00003023
Scott Michel8c2746e2008-12-04 17:16:59 +00003024#if !defined(NDEBUG)
Scott Michel6ccefab2008-12-04 03:02:42 +00003025 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
3026 cerr << "\n"
3027 << "Replace: (add " << CN0->getZExtValue() << ", "
3028 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n"
3029 << "With: (SPUindirect <arg>, "
3030 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n";
3031 }
3032#endif
3033
Scott Michel0718cd82008-12-01 17:56:02 +00003034 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
Scott Michelf9f42e62008-01-29 02:16:57 +00003035 Op0.getOperand(0), combinedConst);
3036 }
Scott Michel67224b22008-06-02 22:18:03 +00003037 } else if (isa<ConstantSDNode>(Op0)
Scott Michelf9f42e62008-01-29 02:16:57 +00003038 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003039 SDValue Op11 = Op1.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003040 if (Op11.getOpcode() == ISD::Constant
3041 || Op11.getOpcode() == ISD::TargetConstant) {
3042 // (add (SPUindirect <arg>, <const>), <const>) ->
3043 // (SPUindirect <arg>, <const + const>)
3044 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
3045 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman8181bd12008-07-27 21:46:04 +00003046 SDValue combinedConst =
Scott Michel0718cd82008-12-01 17:56:02 +00003047 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(), Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00003048
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003049 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
3050 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00003051 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003052 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00003053
3054 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
3055 Op1.getOperand(0), combinedConst);
3056 }
3057 }
Scott Michel97872d32008-02-23 18:41:37 +00003058 break;
3059 }
3060 case ISD::SIGN_EXTEND:
3061 case ISD::ZERO_EXTEND:
3062 case ISD::ANY_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00003063 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
Scott Michel97872d32008-02-23 18:41:37 +00003064 // (any_extend (SPUextract_elt0 <arg>)) ->
3065 // (SPUextract_elt0 <arg>)
3066 // Types must match, however...
Scott Michel8c2746e2008-12-04 17:16:59 +00003067#if !defined(NDEBUG)
3068 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel6ccefab2008-12-04 03:02:42 +00003069 cerr << "\nReplace: ";
3070 N->dump(&DAG);
3071 cerr << "\nWith: ";
3072 Op0.getNode()->dump(&DAG);
3073 cerr << "\n";
Scott Michel8c2746e2008-12-04 17:16:59 +00003074 }
Scott Michel6ccefab2008-12-04 03:02:42 +00003075#endif
Scott Michel97872d32008-02-23 18:41:37 +00003076
3077 return Op0;
3078 }
3079 break;
3080 }
3081 case SPUISD::IndirectAddr: {
3082 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
3083 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003084 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00003085 // (SPUindirect (SPUaform <addr>, 0), 0) ->
3086 // (SPUaform <addr>, 0)
3087
3088 DEBUG(cerr << "Replace: ");
3089 DEBUG(N->dump(&DAG));
3090 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003091 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003092 DEBUG(cerr << "\n");
3093
3094 return Op0;
3095 }
3096 }
3097 break;
3098 }
3099 case SPUISD::SHLQUAD_L_BITS:
3100 case SPUISD::SHLQUAD_L_BYTES:
3101 case SPUISD::VEC_SHL:
3102 case SPUISD::VEC_SRL:
3103 case SPUISD::VEC_SRA:
3104 case SPUISD::ROTQUAD_RZ_BYTES:
3105 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003106 SDValue Op1 = N->getOperand(1);
Scott Michel97872d32008-02-23 18:41:37 +00003107
3108 if (isa<ConstantSDNode>(Op1)) {
3109 // Kill degenerate vector shifts:
3110 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003111 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00003112 Result = Op0;
3113 }
3114 }
3115 break;
3116 }
3117 case SPUISD::PROMOTE_SCALAR: {
3118 switch (Op0.getOpcode()) {
3119 default:
3120 break;
3121 case ISD::ANY_EXTEND:
3122 case ISD::ZERO_EXTEND:
3123 case ISD::SIGN_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00003124 // (SPUpromote_scalar (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
Scott Michel97872d32008-02-23 18:41:37 +00003125 // <arg>
3126 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman8181bd12008-07-27 21:46:04 +00003127 SDValue Op00 = Op0.getOperand(0);
Scott Michelc630c412008-11-24 17:11:17 +00003128 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003129 SDValue Op000 = Op00.getOperand(0);
Scott Michel0718cd82008-12-01 17:56:02 +00003130 if (Op000.getValueType() == NodeVT) {
Scott Michel97872d32008-02-23 18:41:37 +00003131 Result = Op000;
3132 }
3133 }
3134 break;
3135 }
Scott Michelc630c412008-11-24 17:11:17 +00003136 case SPUISD::VEC2PREFSLOT: {
Scott Michel0718cd82008-12-01 17:56:02 +00003137 // (SPUpromote_scalar (SPUvec2prefslot <arg>)) ->
Scott Michel97872d32008-02-23 18:41:37 +00003138 // <arg>
3139 Result = Op0.getOperand(0);
3140 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003141 }
Scott Michel97872d32008-02-23 18:41:37 +00003142 }
3143 break;
Scott Michelf9f42e62008-01-29 02:16:57 +00003144 }
3145 }
Scott Michel394e26d2008-01-17 20:38:41 +00003146 // Otherwise, return unchanged.
Scott Michel0718cd82008-12-01 17:56:02 +00003147#ifndef NDEBUG
Gabor Greif1c80d112008-08-28 21:40:38 +00003148 if (Result.getNode()) {
Scott Michel97872d32008-02-23 18:41:37 +00003149 DEBUG(cerr << "\nReplace.SPU: ");
3150 DEBUG(N->dump(&DAG));
3151 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003152 DEBUG(Result.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003153 DEBUG(cerr << "\n");
3154 }
3155#endif
3156
3157 return Result;
Scott Michel8efdca42007-12-04 22:23:35 +00003158}
3159
3160//===----------------------------------------------------------------------===//
3161// Inline Assembly Support
3162//===----------------------------------------------------------------------===//
3163
3164/// getConstraintType - Given a constraint letter, return the type of
3165/// constraint it is for this target.
Scott Michel4ec722e2008-07-16 17:17:29 +00003166SPUTargetLowering::ConstraintType
Scott Michel8efdca42007-12-04 22:23:35 +00003167SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3168 if (ConstraintLetter.size() == 1) {
3169 switch (ConstraintLetter[0]) {
3170 default: break;
3171 case 'b':
3172 case 'r':
3173 case 'f':
3174 case 'v':
3175 case 'y':
3176 return C_RegisterClass;
Scott Michel4ec722e2008-07-16 17:17:29 +00003177 }
Scott Michel8efdca42007-12-04 22:23:35 +00003178 }
3179 return TargetLowering::getConstraintType(ConstraintLetter);
3180}
3181
Scott Michel4ec722e2008-07-16 17:17:29 +00003182std::pair<unsigned, const TargetRegisterClass*>
Scott Michel8efdca42007-12-04 22:23:35 +00003183SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands92c43912008-06-06 12:08:01 +00003184 MVT VT) const
Scott Michel8efdca42007-12-04 22:23:35 +00003185{
3186 if (Constraint.size() == 1) {
3187 // GCC RS6000 Constraint Letters
3188 switch (Constraint[0]) {
3189 case 'b': // R1-R31
3190 case 'r': // R0-R31
3191 if (VT == MVT::i64)
3192 return std::make_pair(0U, SPU::R64CRegisterClass);
3193 return std::make_pair(0U, SPU::R32CRegisterClass);
3194 case 'f':
3195 if (VT == MVT::f32)
3196 return std::make_pair(0U, SPU::R32FPRegisterClass);
3197 else if (VT == MVT::f64)
3198 return std::make_pair(0U, SPU::R64FPRegisterClass);
3199 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003200 case 'v':
Scott Michel8efdca42007-12-04 22:23:35 +00003201 return std::make_pair(0U, SPU::GPRCRegisterClass);
3202 }
3203 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003204
Scott Michel8efdca42007-12-04 22:23:35 +00003205 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3206}
3207
Scott Michel97872d32008-02-23 18:41:37 +00003208//! Compute used/known bits for a SPU operand
Scott Michel8efdca42007-12-04 22:23:35 +00003209void
Dan Gohman8181bd12008-07-27 21:46:04 +00003210SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohmand0dfc772008-02-13 22:28:48 +00003211 const APInt &Mask,
Scott Michel4ec722e2008-07-16 17:17:29 +00003212 APInt &KnownZero,
Dan Gohman229fa052008-02-13 00:35:47 +00003213 APInt &KnownOne,
Scott Michel5a6f17b2008-01-30 02:55:46 +00003214 const SelectionDAG &DAG,
3215 unsigned Depth ) const {
Scott Michelbc5fbc12008-04-30 00:30:08 +00003216#if 0
Scott Michel97872d32008-02-23 18:41:37 +00003217 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michelbc5fbc12008-04-30 00:30:08 +00003218#endif
Scott Michel97872d32008-02-23 18:41:37 +00003219
3220 switch (Op.getOpcode()) {
3221 default:
3222 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3223 break;
3224
3225#if 0
3226 case CALL:
3227 case SHUFB:
Scott Michel56a125e2008-11-22 23:50:42 +00003228 case SHUFFLE_MASK:
Scott Michel97872d32008-02-23 18:41:37 +00003229 case CNTB:
3230#endif
3231
3232 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003233 SDValue Op0 = Op.getOperand(0);
Duncan Sands92c43912008-06-06 12:08:01 +00003234 MVT Op0VT = Op0.getValueType();
3235 unsigned Op0VTBits = Op0VT.getSizeInBits();
3236 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003237 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3238 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003239 break;
3240 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003241
Scott Michel97872d32008-02-23 18:41:37 +00003242 case SPUISD::LDRESULT:
Scott Michel6ccefab2008-12-04 03:02:42 +00003243 case SPUISD::VEC2PREFSLOT: {
Duncan Sands92c43912008-06-06 12:08:01 +00003244 MVT OpVT = Op.getValueType();
3245 unsigned OpVTBits = OpVT.getSizeInBits();
3246 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003247 KnownZero |= APInt(OpVTBits, ~InMask, false);
3248 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003249 break;
3250 }
3251
3252#if 0
Scott Michel97872d32008-02-23 18:41:37 +00003253 case MPY:
3254 case MPYU:
3255 case MPYH:
3256 case MPYHH:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003257 case SPUISD::SHLQUAD_L_BITS:
3258 case SPUISD::SHLQUAD_L_BYTES:
3259 case SPUISD::VEC_SHL:
3260 case SPUISD::VEC_SRL:
3261 case SPUISD::VEC_SRA:
3262 case SPUISD::VEC_ROTL:
3263 case SPUISD::VEC_ROTR:
3264 case SPUISD::ROTQUAD_RZ_BYTES:
3265 case SPUISD::ROTQUAD_RZ_BITS:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003266 case SPUISD::ROTBYTES_LEFT:
Scott Michel67224b22008-06-02 22:18:03 +00003267 case SPUISD::SELECT_MASK:
3268 case SPUISD::SELB:
3269 case SPUISD::FPInterp:
3270 case SPUISD::FPRecipEst:
3271 case SPUISD::SEXT32TO64:
Scott Michel97872d32008-02-23 18:41:37 +00003272#endif
3273 }
Scott Michel8efdca42007-12-04 22:23:35 +00003274}
3275
Scott Michelbc5fbc12008-04-30 00:30:08 +00003276// LowerAsmOperandForConstraint
3277void
Dan Gohman8181bd12008-07-27 21:46:04 +00003278SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003279 char ConstraintLetter,
Evan Cheng7f250d62008-09-24 00:05:32 +00003280 bool hasMemory,
Dan Gohman8181bd12008-07-27 21:46:04 +00003281 std::vector<SDValue> &Ops,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003282 SelectionDAG &DAG) const {
3283 // Default, for the time being, to the base class handler
Evan Cheng7f250d62008-09-24 00:05:32 +00003284 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3285 Ops, DAG);
Scott Michelbc5fbc12008-04-30 00:30:08 +00003286}
3287
Scott Michel8efdca42007-12-04 22:23:35 +00003288/// isLegalAddressImmediate - Return true if the integer value can be used
3289/// as the offset of the target addressing mode.
Gabor Greife9f7f582008-08-31 15:37:04 +00003290bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3291 const Type *Ty) const {
Scott Michel8efdca42007-12-04 22:23:35 +00003292 // SPU's addresses are 256K:
3293 return (V > -(1 << 18) && V < (1 << 18) - 1);
3294}
3295
3296bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel4ec722e2008-07-16 17:17:29 +00003297 return false;
Scott Michel8efdca42007-12-04 22:23:35 +00003298}
Dan Gohman36322c72008-10-18 02:06:02 +00003299
3300bool
3301SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3302 // The SPU target isn't yet aware of offsets.
3303 return false;
3304}