blob: c3c31e0f47090d398d001c6b1b6bb35ab351f906 [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 Michel8efdca42007-12-04 22:23:35 +0000133 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng08c171a2008-10-14 21:26:46 +0000134 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
135 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
136 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +0000137
Evan Cheng08c171a2008-10-14 21:26:46 +0000138 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
139 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
140 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Scott Michel55252632008-11-20 04:26:21 +0000141 setTruncStoreAction(MVT::i8, MVT::i8, Custom);
142 setTruncStoreAction(MVT::i16, MVT::i8, Custom);
143 setTruncStoreAction(MVT::i32, MVT::i8, Custom);
144 setTruncStoreAction(MVT::i64, MVT::i8, Custom);
145 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000146
Evan Cheng08c171a2008-10-14 21:26:46 +0000147 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
148 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
149 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000150
Scott Michelec8c82e2008-12-02 19:53:53 +0000151 setLoadExtAction(ISD::EXTLOAD, MVT::f32, Custom);
152
Scott Michel8efdca42007-12-04 22:23:35 +0000153 // SPU constant load actions are custom lowered:
154 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begeman78125042008-02-14 18:43:04 +0000155 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000156 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
157
158 // SPU's loads and stores have to be custom lowered:
Scott Michele1006032008-11-19 17:45:08 +0000159 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel8efdca42007-12-04 22:23:35 +0000160 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000161 MVT VT = (MVT::SimpleValueType)sctype;
162
163 setOperationAction(ISD::LOAD, VT, Custom);
164 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000165 }
166
Scott Michel33d73eb2008-11-21 02:56:16 +0000167 // Custom lower BRCOND for i8 to "promote" the result to i16
Scott Michel394e26d2008-01-17 20:38:41 +0000168 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000169
170 // Expand the jumptable branches
171 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
172 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel56a125e2008-11-22 23:50:42 +0000173
174 // Custom lower SELECT_CC for most cases, but expand by default
Scott Michel4ec722e2008-07-16 17:17:29 +0000175 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel56a125e2008-11-22 23:50:42 +0000176 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
177 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
178 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
Scott Michelfa888632008-11-25 00:23:16 +0000179#if 0
Scott Michel56a125e2008-11-22 23:50:42 +0000180 setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
Scott Michelfa888632008-11-25 00:23:16 +0000181#endif
Scott Michel8efdca42007-12-04 22:23:35 +0000182
183 // SPU has no intrinsics for these particular operations:
Andrew Lenharth0531ec52008-02-16 14:46:26 +0000184 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
185
Scott Michel8efdca42007-12-04 22:23:35 +0000186 // PowerPC has no SREM/UREM instructions
187 setOperationAction(ISD::SREM, MVT::i32, Expand);
188 setOperationAction(ISD::UREM, MVT::i32, Expand);
189 setOperationAction(ISD::SREM, MVT::i64, Expand);
190 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000191
Scott Michel8efdca42007-12-04 22:23:35 +0000192 // We don't support sin/cos/sqrt/fmod
193 setOperationAction(ISD::FSIN , MVT::f64, Expand);
194 setOperationAction(ISD::FCOS , MVT::f64, Expand);
195 setOperationAction(ISD::FREM , MVT::f64, Expand);
196 setOperationAction(ISD::FSIN , MVT::f32, Expand);
197 setOperationAction(ISD::FCOS , MVT::f32, Expand);
198 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000199
Scott Michel8efdca42007-12-04 22:23:35 +0000200 // If we're enabling GP optimizations, use hardware square root
201 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
202 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000203
Scott Michel8efdca42007-12-04 22:23:35 +0000204 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
205 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
206
207 // SPU can do rotate right and left, so legalize it... but customize for i8
208 // because instructions don't exist.
Bill Wendling965299c2008-08-31 02:59:23 +0000209
210 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
211 // .td files.
212 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
213 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
214 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
215
Scott Michel8efdca42007-12-04 22:23:35 +0000216 setOperationAction(ISD::ROTL, MVT::i32, Legal);
217 setOperationAction(ISD::ROTL, MVT::i16, Legal);
218 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Michelabb8ca12008-11-20 16:36:33 +0000219
Scott Michel8efdca42007-12-04 22:23:35 +0000220 // SPU has no native version of shift left/right for i8
221 setOperationAction(ISD::SHL, MVT::i8, Custom);
222 setOperationAction(ISD::SRL, MVT::i8, Custom);
223 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000224
225 // SPU needs custom lowering for shift left/right for i64
Scott Michel97872d32008-02-23 18:41:37 +0000226 setOperationAction(ISD::SHL, MVT::i64, Custom);
227 setOperationAction(ISD::SRL, MVT::i64, Custom);
228 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000229
Scott Michel4ec722e2008-07-16 17:17:29 +0000230 // Custom lower i8, i32 and i64 multiplications
231 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000232 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000233 setOperationAction(ISD::MUL, MVT::i64, Expand); // libcall
234
235 // SMUL_LOHI, UMUL_LOHI
Scott Michel61895fe2008-12-10 00:15:19 +0000236#if 0
237 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
238 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
239 setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
240 setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
241#endif
Scott Michel8efdca42007-12-04 22:23:35 +0000242
Scott Michel67224b22008-06-02 22:18:03 +0000243 // Need to custom handle (some) common i8, i64 math ops
244 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000245 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000246 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000247
Scott Michel8efdca42007-12-04 22:23:35 +0000248 // SPU does not have BSWAP. It does have i32 support CTLZ.
249 // CTPOP has to be custom lowered.
250 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
251 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
252
253 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
254 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
255 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
256 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
257
258 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
259 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
260
261 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000262
Scott Michel67224b22008-06-02 22:18:03 +0000263 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel978b96f2008-03-10 23:49:09 +0000264 // select ought to work:
Scott Michel53ab7792008-03-10 16:58:52 +0000265 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000266 setOperationAction(ISD::SELECT, MVT::i16, Legal);
267 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000268 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000269
Scott Michel53ab7792008-03-10 16:58:52 +0000270 setOperationAction(ISD::SETCC, MVT::i8, Legal);
271 setOperationAction(ISD::SETCC, MVT::i16, Legal);
272 setOperationAction(ISD::SETCC, MVT::i32, Legal);
273 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michel6baba072008-03-05 23:02:02 +0000274
Scott Michel97872d32008-02-23 18:41:37 +0000275 // Zero extension and sign extension for i64 have to be
276 // custom legalized
277 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
278 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
279 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000280
Scott Michelec8c82e2008-12-02 19:53:53 +0000281 // Custom lower truncates
282 setOperationAction(ISD::TRUNCATE, MVT::i8, Custom);
283 setOperationAction(ISD::TRUNCATE, MVT::i16, Custom);
284 setOperationAction(ISD::TRUNCATE, MVT::i32, Custom);
285 setOperationAction(ISD::TRUNCATE, MVT::i64, Custom);
286
Scott Michel8efdca42007-12-04 22:23:35 +0000287 // SPU has a legal FP -> signed INT instruction
288 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
289 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
290 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
291 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
292
293 // FDIV on SPU requires custom lowering
294 setOperationAction(ISD::FDIV, MVT::f32, Custom);
295 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
296
297 // SPU has [U|S]INT_TO_FP
298 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
299 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
300 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
301 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
302 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
303 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
304 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
305 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
306
Scott Michel754d8662007-12-20 00:44:13 +0000307 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
308 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
309 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
310 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000311
312 // We cannot sextinreg(i1). Expand to shifts.
313 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000314
Scott Michel8efdca42007-12-04 22:23:35 +0000315 // Support label based line numbers.
Dan Gohman472d12c2008-06-30 20:59:49 +0000316 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000317 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000318
319 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel8efdca42007-12-04 22:23:35 +0000320 // appropriate instructions to materialize the address.
Scott Michel33d73eb2008-11-21 02:56:16 +0000321 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michelf9f42e62008-01-29 02:16:57 +0000322 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000323 MVT VT = (MVT::SimpleValueType)sctype;
324
325 setOperationAction(ISD::GlobalAddress, VT, Custom);
326 setOperationAction(ISD::ConstantPool, VT, Custom);
327 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michelf9f42e62008-01-29 02:16:57 +0000328 }
Scott Michel8efdca42007-12-04 22:23:35 +0000329
330 // RET must be custom lowered, to meet ABI requirements
331 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000332
Scott Michel8efdca42007-12-04 22:23:35 +0000333 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
334 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000335
Scott Michel8efdca42007-12-04 22:23:35 +0000336 // Use the default implementation.
337 setOperationAction(ISD::VAARG , MVT::Other, Expand);
338 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
339 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000340 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000341 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
342 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
343 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
344
345 // Cell SPU has instructions for converting between i64 and fp.
346 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
347 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000348
Scott Michel8efdca42007-12-04 22:23:35 +0000349 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
350 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
351
352 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
353 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
354
355 // First set operation action for all vector types to expand. Then we
356 // will selectively turn on ones that can be effectively codegen'd.
357 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
358 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
359 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
360 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
361 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
362 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
363
Duncan Sands92c43912008-06-06 12:08:01 +0000364 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
365 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
366 MVT VT = (MVT::SimpleValueType)i;
Scott Michel8efdca42007-12-04 22:23:35 +0000367
Duncan Sands92c43912008-06-06 12:08:01 +0000368 // add/sub are legal for all supported vector VT's.
369 setOperationAction(ISD::ADD , VT, Legal);
370 setOperationAction(ISD::SUB , VT, Legal);
371 // mul has to be custom lowered.
372 setOperationAction(ISD::MUL , VT, Custom);
373
374 setOperationAction(ISD::AND , VT, Legal);
375 setOperationAction(ISD::OR , VT, Legal);
376 setOperationAction(ISD::XOR , VT, Legal);
377 setOperationAction(ISD::LOAD , VT, Legal);
378 setOperationAction(ISD::SELECT, VT, Legal);
379 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000380
Scott Michel8efdca42007-12-04 22:23:35 +0000381 // These operations need to be expanded:
Duncan Sands92c43912008-06-06 12:08:01 +0000382 setOperationAction(ISD::SDIV, VT, Expand);
383 setOperationAction(ISD::SREM, VT, Expand);
384 setOperationAction(ISD::UDIV, VT, Expand);
385 setOperationAction(ISD::UREM, VT, Expand);
386 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000387
388 // Custom lower build_vector, constant pool spills, insert and
389 // extract vector elements:
Duncan Sands92c43912008-06-06 12:08:01 +0000390 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
391 setOperationAction(ISD::ConstantPool, VT, Custom);
392 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
393 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
394 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
395 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000396 }
397
398 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
399 setOperationAction(ISD::AND, MVT::v16i8, Custom);
400 setOperationAction(ISD::OR, MVT::v16i8, Custom);
401 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
402 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000403
Scott Michel8efdca42007-12-04 22:23:35 +0000404 setShiftAmountType(MVT::i32);
Duncan Sands8cf4a822008-11-23 15:47:28 +0000405 setBooleanContents(ZeroOrOneBooleanContent);
Scott Michel4ec722e2008-07-16 17:17:29 +0000406
Scott Michel8efdca42007-12-04 22:23:35 +0000407 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel4ec722e2008-07-16 17:17:29 +0000408
Scott Michel8efdca42007-12-04 22:23:35 +0000409 // We have target-specific dag combine patterns for the following nodes:
Scott Michelf9f42e62008-01-29 02:16:57 +0000410 setTargetDAGCombine(ISD::ADD);
Scott Michel97872d32008-02-23 18:41:37 +0000411 setTargetDAGCombine(ISD::ZERO_EXTEND);
412 setTargetDAGCombine(ISD::SIGN_EXTEND);
413 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel4ec722e2008-07-16 17:17:29 +0000414
Scott Michel8efdca42007-12-04 22:23:35 +0000415 computeRegisterProperties();
Scott Michel56a125e2008-11-22 23:50:42 +0000416
Scott Michel2c261072008-12-09 03:37:19 +0000417 // Set pre-RA register scheduler default to BURR, which produces slightly
418 // better code than the default (could also be TDRR, but TargetLowering.h
419 // needs a mod to support that model):
420 setSchedulingPreference(SchedulingForRegPressure);
Scott Michel8efdca42007-12-04 22:23:35 +0000421}
422
423const char *
424SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
425{
426 if (node_names.empty()) {
427 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
428 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
429 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
430 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Micheldbac4cf2008-01-11 02:53:15 +0000431 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michelf9f42e62008-01-29 02:16:57 +0000432 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel8efdca42007-12-04 22:23:35 +0000433 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
434 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
435 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel56a125e2008-11-22 23:50:42 +0000436 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000437 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
438 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
Scott Michelc630c412008-11-24 17:11:17 +0000439 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
Scott Michel8efdca42007-12-04 22:23:35 +0000440 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
441 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
442 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
443 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michel97872d32008-02-23 18:41:37 +0000444 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
445 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel8efdca42007-12-04 22:23:35 +0000446 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
447 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
448 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
449 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
450 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michel97872d32008-02-23 18:41:37 +0000451 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
452 "SPUISD::ROTQUAD_RZ_BYTES";
453 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
454 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel8efdca42007-12-04 22:23:35 +0000455 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
Scott Michel67224b22008-06-02 22:18:03 +0000456 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
457 "SPUISD::ROTBYTES_LEFT_BITS";
458 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000459 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel67224b22008-06-02 22:18:03 +0000460 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
461 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
462 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
463 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel8efdca42007-12-04 22:23:35 +0000464 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
465 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
466 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
467 }
468
469 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
470
471 return ((i != node_names.end()) ? i->second : 0);
472}
473
Dan Gohman8181bd12008-07-27 21:46:04 +0000474MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands92c43912008-06-06 12:08:01 +0000475 MVT VT = Op.getValueType();
Scott Michela313fb02008-10-30 01:51:48 +0000476 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel53ab7792008-03-10 16:58:52 +0000477}
478
Scott Michel8efdca42007-12-04 22:23:35 +0000479//===----------------------------------------------------------------------===//
480// Calling convention code:
481//===----------------------------------------------------------------------===//
482
483#include "SPUGenCallingConv.inc"
484
485//===----------------------------------------------------------------------===//
486// LowerOperation implementation
487//===----------------------------------------------------------------------===//
488
Scott Micheldbac4cf2008-01-11 02:53:15 +0000489/// Aligned load common code for CellSPU
490/*!
491 \param[in] Op The SelectionDAG load or store operand
492 \param[in] DAG The selection DAG
493 \param[in] ST CellSPU subtarget information structure
494 \param[in,out] alignment Caller initializes this to the load or store node's
495 value from getAlignment(), may be updated while generating the aligned load
496 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
497 offset (divisible by 16, modulo 16 == 0)
498 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
499 offset of the preferred slot (modulo 16 != 0)
500 \param[in,out] VT Caller initializes this value type to the the load or store
501 node's loaded or stored value type; may be updated if an i1-extended load or
502 store.
503 \param[out] was16aligned true if the base pointer had 16-byte alignment,
504 otherwise false. Can help to determine if the chunk needs to be rotated.
505
506 Both load and store lowering load a block of data aligned on a 16-byte
507 boundary. This is the common aligned load code shared between both.
508 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000509static SDValue
510AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Micheldbac4cf2008-01-11 02:53:15 +0000511 LSBaseSDNode *LSN,
512 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands92c43912008-06-06 12:08:01 +0000513 MVT &VT, bool &was16aligned)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000514{
Duncan Sands92c43912008-06-06 12:08:01 +0000515 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000516 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman8181bd12008-07-27 21:46:04 +0000517 SDValue basePtr = LSN->getBasePtr();
518 SDValue chain = LSN->getChain();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000519
520 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greif1c80d112008-08-28 21:40:38 +0000521 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000522
Gabor Greife9f7f582008-08-31 15:37:04 +0000523 if (Op1.getOpcode() == ISD::Constant
524 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel394e26d2008-01-17 20:38:41 +0000525 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000526
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000527 alignOffs = (int) CN->getZExtValue();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000528 prefSlotOffs = (int) (alignOffs & 0xf);
529
530 // Adjust the rotation amount to ensure that the final result ends up in
531 // the preferred slot:
532 prefSlotOffs -= vtm->prefslot_byte;
533 basePtr = basePtr.getOperand(0);
534
Scott Michel394e26d2008-01-17 20:38:41 +0000535 // Loading from memory, can we adjust alignment?
536 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000537 SDValue APtr = basePtr.getOperand(0);
Scott Michel394e26d2008-01-17 20:38:41 +0000538 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
539 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
540 alignment = GSDN->getGlobal()->getAlignment();
541 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000542 }
543 } else {
544 alignOffs = 0;
545 prefSlotOffs = -vtm->prefslot_byte;
546 }
Scott Michelbc5fbc12008-04-30 00:30:08 +0000547 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
548 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
549 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
550 prefSlotOffs = (int) (alignOffs & 0xf);
551 prefSlotOffs -= vtm->prefslot_byte;
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;
Scott Michele2641a12008-12-04 21:01:44 +00001130 case MVT::v2i64:
1131 case MVT::v2f64:
Scott Michel8efdca42007-12-04 22:23:35 +00001132 case MVT::v4f32:
1133 case MVT::v4i32:
1134 case MVT::v8i16:
1135 case MVT::v16i8:
1136 if (ArgRegIdx != NumArgRegs) {
1137 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1138 } else {
1139 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001140 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001141 }
1142 break;
1143 }
1144 }
1145
1146 // Update number of stack bytes actually used, insert a call sequence start
1147 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001148 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1149 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001150
1151 if (!MemOpChains.empty()) {
1152 // Adjust the stack pointer for the stack arguments.
1153 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1154 &MemOpChains[0], MemOpChains.size());
1155 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001156
Scott Michel8efdca42007-12-04 22:23:35 +00001157 // Build a sequence of copy-to-reg nodes chained together with token chain
1158 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001159 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001160 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1161 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1162 InFlag);
1163 InFlag = Chain.getValue(1);
1164 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001165
Dan Gohman8181bd12008-07-27 21:46:04 +00001166 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001167 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001168
Bill Wendlingfef06052008-09-16 21:48:12 +00001169 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1170 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1171 // node so that legalize doesn't hack it.
Scott Michel5974f432008-11-11 03:06:06 +00001172 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001173 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001174 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001175 SDValue Zero = DAG.getConstant(0, PtrVT);
1176 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001177
Scott Micheldbac4cf2008-01-11 02:53:15 +00001178 if (!ST->usingLargeMem()) {
1179 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1180 // style calls, otherwise, external symbols are BRASL calls. This assumes
1181 // that declared/defined symbols are in the same compilation unit and can
1182 // be reached through PC-relative jumps.
1183 //
1184 // NOTE:
1185 // This may be an unsafe assumption for JIT and really large compilation
1186 // units.
1187 if (GV->isDeclaration()) {
1188 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1189 } else {
1190 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1191 }
Scott Michel8efdca42007-12-04 22:23:35 +00001192 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001193 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1194 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001195 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001196 }
Scott Michel5974f432008-11-11 03:06:06 +00001197 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendlingfef06052008-09-16 21:48:12 +00001198 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Micheldbac4cf2008-01-11 02:53:15 +00001199 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001200 // If this is an absolute destination address that appears to be a legal
1201 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001202 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001203 }
Scott Michel8efdca42007-12-04 22:23:35 +00001204
1205 Ops.push_back(Chain);
1206 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001207
Scott Michel8efdca42007-12-04 22:23:35 +00001208 // Add argument registers to the end of the list so that they are known live
1209 // into the call.
1210 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001211 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001212 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001213
Gabor Greif1c80d112008-08-28 21:40:38 +00001214 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001215 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001216 // Returns a chain and a flag for retval copy to use.
1217 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1218 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001219 InFlag = Chain.getValue(1);
1220
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001221 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1222 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001223 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001224 InFlag = Chain.getValue(1);
1225
Dan Gohman8181bd12008-07-27 21:46:04 +00001226 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001227 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001228
Scott Michel8efdca42007-12-04 22:23:35 +00001229 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001230 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001231 default: assert(0 && "Unexpected ret value!");
1232 case MVT::Other: break;
1233 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001234 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001235 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1236 ResultVals[0] = Chain.getValue(0);
1237 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1238 Chain.getValue(2)).getValue(1);
1239 ResultVals[1] = Chain.getValue(0);
1240 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001241 } else {
1242 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1243 ResultVals[0] = Chain.getValue(0);
1244 NumResults = 1;
1245 }
Scott Michel8efdca42007-12-04 22:23:35 +00001246 break;
1247 case MVT::i64:
1248 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1249 ResultVals[0] = Chain.getValue(0);
1250 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001251 break;
1252 case MVT::f32:
1253 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001254 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001255 InFlag).getValue(1);
1256 ResultVals[0] = Chain.getValue(0);
1257 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001258 break;
1259 case MVT::v2f64:
Scott Michele2641a12008-12-04 21:01:44 +00001260 case MVT::v2i64:
Scott Michel8efdca42007-12-04 22:23:35 +00001261 case MVT::v4f32:
1262 case MVT::v4i32:
1263 case MVT::v8i16:
1264 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001265 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001266 InFlag).getValue(1);
1267 ResultVals[0] = Chain.getValue(0);
1268 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001269 break;
1270 }
Duncan Sands698842f2008-07-02 17:40:58 +00001271
Scott Michel8efdca42007-12-04 22:23:35 +00001272 // If the function returns void, just return the chain.
1273 if (NumResults == 0)
1274 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001275
Scott Michel8efdca42007-12-04 22:23:35 +00001276 // Otherwise, merge everything together with a MERGE_VALUES node.
1277 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001278 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001279 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001280}
1281
Dan Gohman8181bd12008-07-27 21:46:04 +00001282static SDValue
1283LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001284 SmallVector<CCValAssign, 16> RVLocs;
1285 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1286 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1287 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001288 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001289
Scott Michel8efdca42007-12-04 22:23:35 +00001290 // If this is the first return lowered for this function, add the regs to the
1291 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001292 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001293 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001294 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001295 }
1296
Dan Gohman8181bd12008-07-27 21:46:04 +00001297 SDValue Chain = Op.getOperand(0);
1298 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001299
Scott Michel8efdca42007-12-04 22:23:35 +00001300 // Copy the result values into the output registers.
1301 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1302 CCValAssign &VA = RVLocs[i];
1303 assert(VA.isRegLoc() && "Can only return in registers!");
1304 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1305 Flag = Chain.getValue(1);
1306 }
1307
Gabor Greif1c80d112008-08-28 21:40:38 +00001308 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001309 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1310 else
1311 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1312}
1313
1314
1315//===----------------------------------------------------------------------===//
1316// Vector related lowering:
1317//===----------------------------------------------------------------------===//
1318
1319static ConstantSDNode *
1320getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001321 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001322
Scott Michel8efdca42007-12-04 22:23:35 +00001323 // Check to see if this buildvec has a single non-undef value in its elements.
1324 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1325 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001326 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001327 OpVal = N->getOperand(i);
1328 else if (OpVal != N->getOperand(i))
1329 return 0;
1330 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001331
Gabor Greif1c80d112008-08-28 21:40:38 +00001332 if (OpVal.getNode() != 0) {
Scott Michel5974f432008-11-11 03:06:06 +00001333 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001334 return CN;
1335 }
1336 }
1337
1338 return 0; // All UNDEF: use implicit def.; not Constant node
1339}
1340
1341/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1342/// and the value fits into an unsigned 18-bit constant, and if so, return the
1343/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001344SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001345 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001346 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001347 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001348 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001349 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001350 uint32_t upper = uint32_t(UValue >> 32);
1351 uint32_t lower = uint32_t(UValue);
1352 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001353 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001354 Value = Value >> 32;
1355 }
Scott Michel8efdca42007-12-04 22:23:35 +00001356 if (Value <= 0x3ffff)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001357 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001358 }
1359
Dan Gohman8181bd12008-07-27 21:46:04 +00001360 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001361}
1362
1363/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1364/// and the value fits into a signed 16-bit constant, and if so, return the
1365/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001366SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001367 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001368 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001369 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001370 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001371 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001372 uint32_t upper = uint32_t(UValue >> 32);
1373 uint32_t lower = uint32_t(UValue);
1374 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001375 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001376 Value = Value >> 32;
1377 }
Scott Michel6baba072008-03-05 23:02:02 +00001378 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001379 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001380 }
1381 }
1382
Dan Gohman8181bd12008-07-27 21:46:04 +00001383 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001384}
1385
1386/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1387/// and the value fits into a signed 10-bit constant, and if so, return the
1388/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001389SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001390 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001391 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001392 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001393 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001394 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001395 uint32_t upper = uint32_t(UValue >> 32);
1396 uint32_t lower = uint32_t(UValue);
1397 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001398 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001399 Value = Value >> 32;
1400 }
Scott Michel6baba072008-03-05 23:02:02 +00001401 if (isS10Constant(Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001402 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001403 }
1404
Dan Gohman8181bd12008-07-27 21:46:04 +00001405 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001406}
1407
1408/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1409/// and the value fits into a signed 8-bit constant, and if so, return the
1410/// constant.
1411///
1412/// @note: The incoming vector is v16i8 because that's the only way we can load
1413/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1414/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001415SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001416 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001417 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001418 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001419 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001420 && Value <= 0xffff /* truncated from uint64_t */
1421 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001422 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001423 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001424 && (Value & 0xff) == Value)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001425 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001426 }
1427
Dan Gohman8181bd12008-07-27 21:46:04 +00001428 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001429}
1430
1431/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1432/// and the value fits into a signed 16-bit constant, and if so, return the
1433/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001434SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001435 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001436 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001437 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001438 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001439 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1440 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001441 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001442 }
1443
Dan Gohman8181bd12008-07-27 21:46:04 +00001444 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001445}
1446
1447/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001448SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001449 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001450 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001451 }
1452
Dan Gohman8181bd12008-07-27 21:46:04 +00001453 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001454}
1455
1456/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001457SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001458 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001459 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001460 }
1461
Dan Gohman8181bd12008-07-27 21:46:04 +00001462 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001463}
1464
1465// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001466// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001467// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1468// zero. Return true if this is not an array of constants, false if it is.
1469//
1470static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1471 uint64_t UndefBits[2]) {
1472 // Start with zero'd results.
1473 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001474
Duncan Sands92c43912008-06-06 12:08:01 +00001475 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001476 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001477 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001478
Scott Michel8efdca42007-12-04 22:23:35 +00001479 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1480 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1481
1482 uint64_t EltBits = 0;
1483 if (OpVal.getOpcode() == ISD::UNDEF) {
1484 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1485 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1486 continue;
Scott Michel5974f432008-11-11 03:06:06 +00001487 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001488 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel5974f432008-11-11 03:06:06 +00001489 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001490 const APFloat &apf = CN->getValueAPF();
1491 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001492 ? FloatToBits(apf.convertToFloat())
1493 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001494 } else {
1495 // Nonconstant element.
1496 return true;
1497 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001498
Scott Michel8efdca42007-12-04 22:23:35 +00001499 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1500 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001501
1502 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001503 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1504 return false;
1505}
1506
1507/// If this is a splat (repetition) of a value across the whole vector, return
1508/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001509/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001510/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001511static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001512 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001513 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001514 uint64_t &SplatBits, uint64_t &SplatUndef,
1515 int &SplatSize) {
1516 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1517 // the same as the lower 64-bits, ignoring undefs.
1518 uint64_t Bits64 = Bits128[0] | Bits128[1];
1519 uint64_t Undef64 = Undef128[0] & Undef128[1];
1520 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1521 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1522 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1523 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1524
1525 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1526 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001527
Scott Michel8efdca42007-12-04 22:23:35 +00001528 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1529 // undefs.
1530 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001531 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001532
Scott Michel5a6f17b2008-01-30 02:55:46 +00001533 // If the top 16-bits are different than the lower 16-bits, ignoring
1534 // undefs, we have an i32 splat.
1535 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1536 if (MinSplatBits < 16) {
1537 // If the top 8-bits are different than the lower 8-bits, ignoring
1538 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001539 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1540 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001541 // Otherwise, we have an 8-bit splat.
1542 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1543 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1544 SplatSize = 1;
1545 return true;
1546 }
1547 } else {
1548 SplatBits = Bits16;
1549 SplatUndef = Undef16;
1550 SplatSize = 2;
1551 return true;
1552 }
1553 }
1554 } else {
1555 SplatBits = Bits32;
1556 SplatUndef = Undef32;
1557 SplatSize = 4;
1558 return true;
1559 }
Scott Michel8efdca42007-12-04 22:23:35 +00001560 }
1561 } else {
1562 SplatBits = Bits128[0];
1563 SplatUndef = Undef128[0];
1564 SplatSize = 8;
1565 return true;
1566 }
1567 }
1568
1569 return false; // Can't be a splat if two pieces don't match.
1570}
1571
1572// If this is a case we can't handle, return null and let the default
1573// expansion code take care of it. If we CAN select this case, and if it
1574// selects to a single instruction, return Op. Otherwise, if we can codegen
1575// this case more efficiently than a constant pool load, lower it to the
1576// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001577static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001578 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001579 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001580 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001581 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001582 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001583 uint64_t VectorBits[2];
1584 uint64_t UndefBits[2];
1585 uint64_t SplatBits, SplatUndef;
1586 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001587 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001588 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001589 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001590 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001591 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001592
Duncan Sands92c43912008-06-06 12:08:01 +00001593 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001594 default:
1595 case MVT::v4f32: {
1596 uint32_t Value32 = SplatBits;
1597 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001598 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001599 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001600 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001601 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001602 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001603 break;
1604 }
1605 case MVT::v2f64: {
1606 uint64_t f64val = SplatBits;
1607 assert(SplatSize == 8
Scott Michelc630c412008-11-24 17:11:17 +00001608 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel8efdca42007-12-04 22:23:35 +00001609 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001610 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001611 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001612 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001613 break;
1614 }
1615 case MVT::v16i8: {
1616 // 8-bit constants have to be expanded to 16-bits
1617 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001618 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001619 for (int i = 0; i < 8; ++i)
1620 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1621 return DAG.getNode(ISD::BIT_CONVERT, VT,
1622 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1623 }
1624 case MVT::v8i16: {
1625 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001626 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001627 Value16 = (unsigned short) (SplatBits & 0xffff);
1628 else
1629 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001630 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1631 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001632 for (int i = 0; i < 8; ++i) Ops[i] = T;
1633 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1634 }
1635 case MVT::v4i32: {
1636 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001637 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001638 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1639 }
1640 case MVT::v2i64: {
1641 uint64_t val = SplatBits;
1642 uint32_t upper = uint32_t(val >> 32);
1643 uint32_t lower = uint32_t(val);
1644
Scott Michelbcc7b672008-03-06 04:02:54 +00001645 if (upper == lower) {
1646 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001647 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001648 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001649 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001650 SDValue LO32;
1651 SDValue HI32;
1652 SmallVector<SDValue, 16> ShufBytes;
1653 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001654 bool upper_special, lower_special;
1655
1656 // NOTE: This code creates common-case shuffle masks that can be easily
1657 // detected as common expressions. It is not attempting to create highly
1658 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1659
1660 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michelc630c412008-11-24 17:11:17 +00001661 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1662 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel8efdca42007-12-04 22:23:35 +00001663
1664 // Create lower vector if not a special pattern
1665 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001666 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001667 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1668 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1669 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001670 }
1671
1672 // Create upper vector if not a special pattern
1673 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001674 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001675 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1676 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1677 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001678 }
1679
1680 // If either upper or lower are special, then the two input operands are
1681 // the same (basically, one of them is a "don't care")
1682 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001683 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001684 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001685 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001686 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001687 // Unhappy situation... both upper and lower are special, so punt with
1688 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001689 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001690 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001691 Zero, Zero);
1692 }
1693
1694 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001695 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001696 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001697 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001698 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001699 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001700 process_upper = (upper_special && (i & 1) == 0);
1701 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001702
Scott Michel5a6f17b2008-01-30 02:55:46 +00001703 if (process_upper || process_lower) {
1704 if ((process_upper && upper == 0)
1705 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001706 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001707 else if ((process_upper && upper == 0xffffffff)
1708 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001709 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001710 else if ((process_upper && upper == 0x80000000)
1711 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001712 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001713 } else
Scott Michel67224b22008-06-02 22:18:03 +00001714 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001715 }
Scott Michel67224b22008-06-02 22:18:03 +00001716
1717 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001718 }
1719
1720 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001721 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001722 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001723 }
1724 }
1725 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001726
Dan Gohman8181bd12008-07-27 21:46:04 +00001727 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001728}
1729
1730/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1731/// which the Cell can operate. The code inspects V3 to ascertain whether the
1732/// permutation vector, V3, is monotonically increasing with one "exception"
1733/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel56a125e2008-11-22 23:50:42 +00001734/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel8efdca42007-12-04 22:23:35 +00001735/// In either case, the net result is going to eventually invoke SHUFB to
1736/// permute/shuffle the bytes from V1 and V2.
1737/// \note
Scott Michel56a125e2008-11-22 23:50:42 +00001738/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel8efdca42007-12-04 22:23:35 +00001739/// control word for byte/halfword/word insertion. This takes care of a single
1740/// element move from V2 into V1.
1741/// \note
1742/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001743static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1744 SDValue V1 = Op.getOperand(0);
1745 SDValue V2 = Op.getOperand(1);
1746 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001747
Scott Michel8efdca42007-12-04 22:23:35 +00001748 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001749
Scott Michel8efdca42007-12-04 22:23:35 +00001750 // If we have a single element being moved from V1 to V2, this can be handled
1751 // using the C*[DX] compute mask instructions, but the vector elements have
1752 // to be monotonically increasing with one exception element.
Scott Michele2641a12008-12-04 21:01:44 +00001753 MVT VecVT = V1.getValueType();
1754 MVT EltVT = VecVT.getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001755 unsigned EltsFromV2 = 0;
1756 unsigned V2Elt = 0;
1757 unsigned V2EltIdx0 = 0;
1758 unsigned CurrElt = 0;
Scott Michele2641a12008-12-04 21:01:44 +00001759 unsigned MaxElts = VecVT.getVectorNumElements();
1760 unsigned PrevElt = 0;
1761 unsigned V0Elt = 0;
Scott Michel8efdca42007-12-04 22:23:35 +00001762 bool monotonic = true;
Scott Michele2641a12008-12-04 21:01:44 +00001763 bool rotate = true;
1764
1765 if (EltVT == MVT::i8) {
Scott Michel8efdca42007-12-04 22:23:35 +00001766 V2EltIdx0 = 16;
Scott Michele2641a12008-12-04 21:01:44 +00001767 } else if (EltVT == MVT::i16) {
Scott Michel8efdca42007-12-04 22:23:35 +00001768 V2EltIdx0 = 8;
Scott Michele2641a12008-12-04 21:01:44 +00001769 } else if (EltVT == MVT::i32 || EltVT == MVT::f32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001770 V2EltIdx0 = 4;
Scott Michele2641a12008-12-04 21:01:44 +00001771 } else if (EltVT == MVT::i64 || EltVT == MVT::f64) {
1772 V2EltIdx0 = 2;
1773 } else
Scott Michel8efdca42007-12-04 22:23:35 +00001774 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1775
Scott Michele2641a12008-12-04 21:01:44 +00001776 for (unsigned i = 0; i != PermMask.getNumOperands(); ++i) {
1777 if (PermMask.getOperand(i).getOpcode() != ISD::UNDEF) {
1778 unsigned SrcElt = cast<ConstantSDNode > (PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001779
Scott Michele2641a12008-12-04 21:01:44 +00001780 if (monotonic) {
1781 if (SrcElt >= V2EltIdx0) {
1782 if (1 >= (++EltsFromV2)) {
1783 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1784 }
1785 } else if (CurrElt != SrcElt) {
1786 monotonic = false;
1787 }
1788
1789 ++CurrElt;
1790 }
1791
1792 if (rotate) {
1793 if (PrevElt > 0 && SrcElt < MaxElts) {
1794 if ((PrevElt == SrcElt - 1)
1795 || (PrevElt == MaxElts - 1 && SrcElt == 0)) {
1796 PrevElt = SrcElt;
1797 if (SrcElt == 0)
1798 V0Elt = i;
1799 } else {
1800 rotate = false;
1801 }
1802 } else if (PrevElt == 0) {
1803 // First time through, need to keep track of previous element
1804 PrevElt = SrcElt;
1805 } else {
1806 // This isn't a rotation, takes elements from vector 2
1807 rotate = false;
1808 }
1809 }
Scott Michel8efdca42007-12-04 22:23:35 +00001810 }
Scott Michel8efdca42007-12-04 22:23:35 +00001811 }
1812
1813 if (EltsFromV2 == 1 && monotonic) {
1814 // Compute mask and shuffle
1815 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001816 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1817 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001818 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001819 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001820 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001821 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel56a125e2008-11-22 23:50:42 +00001822 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001823 SDValue ShufMaskOp =
Scott Michel0718cd82008-12-01 17:56:02 +00001824 DAG.getNode(SPUISD::SHUFFLE_MASK, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001825 DAG.getTargetConstant(V2Elt, MVT::i32),
1826 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001827 // Use shuffle mask in SHUFB synthetic instruction:
1828 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
Scott Michele2641a12008-12-04 21:01:44 +00001829 } else if (rotate) {
1830 int rotamt = (MaxElts - V0Elt) * EltVT.getSizeInBits()/8;
1831
1832 return DAG.getNode(SPUISD::ROTBYTES_LEFT, V1.getValueType(),
1833 V1, DAG.getConstant(rotamt, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001834 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001835 // Convert the SHUFFLE_VECTOR mask's input element units to the
1836 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001837 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001838
Dan Gohman8181bd12008-07-27 21:46:04 +00001839 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001840 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1841 unsigned SrcElt;
1842 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001843 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001844 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001845 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001846
Scott Michel97872d32008-02-23 18:41:37 +00001847 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001848 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1849 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001850 }
1851 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001852
Dan Gohman8181bd12008-07-27 21:46:04 +00001853 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel0718cd82008-12-01 17:56:02 +00001854 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001855 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1856 }
1857}
1858
Dan Gohman8181bd12008-07-27 21:46:04 +00001859static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1860 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001861
Gabor Greif1c80d112008-08-28 21:40:38 +00001862 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001863 // For a constant, build the appropriate constant vector, which will
1864 // eventually simplify to a vector register load.
1865
Gabor Greif1c80d112008-08-28 21:40:38 +00001866 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001867 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001868 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001869 size_t n_copies;
1870
1871 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001872 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001873 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001874 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001875 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1876 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1877 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1878 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1879 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1880 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1881 }
1882
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001883 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001884 for (size_t j = 0; j < n_copies; ++j)
1885 ConstVecValues.push_back(CValue);
1886
1887 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001888 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001889 } else {
1890 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001891 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001892 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1893 case MVT::i8:
1894 case MVT::i16:
1895 case MVT::i32:
1896 case MVT::i64:
1897 case MVT::f32:
1898 case MVT::f64:
1899 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1900 }
1901 }
1902
Dan Gohman8181bd12008-07-27 21:46:04 +00001903 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001904}
1905
Dan Gohman8181bd12008-07-27 21:46:04 +00001906static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001907 switch (Op.getValueType().getSimpleVT()) {
1908 default:
1909 cerr << "CellSPU: Unknown vector multiplication, got "
1910 << Op.getValueType().getMVTString()
1911 << "\n";
1912 abort();
1913 /*NOTREACHED*/
1914
Scott Michel8efdca42007-12-04 22:23:35 +00001915 case MVT::v4i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001916 SDValue rA = Op.getOperand(0);
1917 SDValue rB = Op.getOperand(1);
1918 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1919 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1920 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1921 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel8efdca42007-12-04 22:23:35 +00001922
1923 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1924 break;
1925 }
1926
1927 // Multiply two v8i16 vectors (pipeline friendly version):
1928 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1929 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1930 // c) Use SELB to select upper and lower halves from the intermediate results
1931 //
Scott Michel67224b22008-06-02 22:18:03 +00001932 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel8efdca42007-12-04 22:23:35 +00001933 // dual-issue. This code does manage to do this, even if it's a little on
1934 // the wacky side
1935 case MVT::v8i16: {
1936 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001937 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman8181bd12008-07-27 21:46:04 +00001938 SDValue Chain = Op.getOperand(0);
1939 SDValue rA = Op.getOperand(0);
1940 SDValue rB = Op.getOperand(1);
Chris Lattner1b989192007-12-31 04:13:23 +00001941 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1942 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00001943
Dan Gohman8181bd12008-07-27 21:46:04 +00001944 SDValue FSMBOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001945 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel67224b22008-06-02 22:18:03 +00001946 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001947 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel8efdca42007-12-04 22:23:35 +00001948
Dan Gohman8181bd12008-07-27 21:46:04 +00001949 SDValue HHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001950 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001951 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001952
Dan Gohman8181bd12008-07-27 21:46:04 +00001953 SDValue HHProd_v4i32 =
Scott Michel8efdca42007-12-04 22:23:35 +00001954 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001955 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001956
1957 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001958 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1959 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1960 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1961 HHProd_v4i32,
1962 DAG.getConstant(16, MVT::i16))),
1963 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001964 }
1965
1966 // This M00sE is N@stI! (apologies to Monty Python)
1967 //
1968 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1969 // is to break it all apart, sign extend, and reassemble the various
1970 // intermediate products.
1971 case MVT::v16i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001972 SDValue rA = Op.getOperand(0);
1973 SDValue rB = Op.getOperand(1);
1974 SDValue c8 = DAG.getConstant(8, MVT::i32);
1975 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001976
Dan Gohman8181bd12008-07-27 21:46:04 +00001977 SDValue LLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001978 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001979 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1980 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001981
Dan Gohman8181bd12008-07-27 21:46:04 +00001982 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001983
Dan Gohman8181bd12008-07-27 21:46:04 +00001984 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001985
Dan Gohman8181bd12008-07-27 21:46:04 +00001986 SDValue LHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001987 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001988 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001989
Dan Gohman8181bd12008-07-27 21:46:04 +00001990 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001991 DAG.getConstant(0x2222, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001992
Dan Gohman8181bd12008-07-27 21:46:04 +00001993 SDValue LoProdParts =
Scott Michel97872d32008-02-23 18:41:37 +00001994 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1995 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1996 LLProd, LHProd, FSMBmask));
Scott Michel8efdca42007-12-04 22:23:35 +00001997
Dan Gohman8181bd12008-07-27 21:46:04 +00001998 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001999
Dan Gohman8181bd12008-07-27 21:46:04 +00002000 SDValue LoProd =
Scott Michel8efdca42007-12-04 22:23:35 +00002001 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michel97872d32008-02-23 18:41:37 +00002002 LoProdParts,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002003 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2004 LoProdMask, LoProdMask,
2005 LoProdMask, LoProdMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002006
Dan Gohman8181bd12008-07-27 21:46:04 +00002007 SDValue rAH =
Scott Michel8efdca42007-12-04 22:23:35 +00002008 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002009 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002010
Dan Gohman8181bd12008-07-27 21:46:04 +00002011 SDValue rBH =
Scott Michel8efdca42007-12-04 22:23:35 +00002012 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002013 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002014
Dan Gohman8181bd12008-07-27 21:46:04 +00002015 SDValue HLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00002016 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002017 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2018 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel8efdca42007-12-04 22:23:35 +00002019
Dan Gohman8181bd12008-07-27 21:46:04 +00002020 SDValue HHProd_1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002021 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002022 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00002023 DAG.getNode(SPUISD::VEC_SRA,
2024 MVT::v4i32, rAH, c8)),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002025 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00002026 DAG.getNode(SPUISD::VEC_SRA,
2027 MVT::v4i32, rBH, c8)));
Scott Michel8efdca42007-12-04 22:23:35 +00002028
Dan Gohman8181bd12008-07-27 21:46:04 +00002029 SDValue HHProd =
Scott Michel97872d32008-02-23 18:41:37 +00002030 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2031 HLProd,
2032 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2033 FSMBmask);
Scott Michel8efdca42007-12-04 22:23:35 +00002034
Dan Gohman8181bd12008-07-27 21:46:04 +00002035 SDValue HiProd =
Scott Michel97872d32008-02-23 18:41:37 +00002036 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002037
2038 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002039 DAG.getNode(ISD::OR, MVT::v4i32,
2040 LoProd, HiProd));
Scott Michel8efdca42007-12-04 22:23:35 +00002041 }
Scott Michel8efdca42007-12-04 22:23:35 +00002042 }
2043
Dan Gohman8181bd12008-07-27 21:46:04 +00002044 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002045}
2046
Dan Gohman8181bd12008-07-27 21:46:04 +00002047static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00002048 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002049 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002050
Dan Gohman8181bd12008-07-27 21:46:04 +00002051 SDValue A = Op.getOperand(0);
2052 SDValue B = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002053 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002054
2055 unsigned VRegBR, VRegC;
2056
2057 if (VT == MVT::f32) {
Chris Lattner1b989192007-12-31 04:13:23 +00002058 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2059 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002060 } else {
Chris Lattner1b989192007-12-31 04:13:23 +00002061 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2062 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002063 }
2064 // TODO: make sure we're feeding FPInterp the right arguments
2065 // Right now: fi B, frest(B)
2066
2067 // Computes BRcpl =
2068 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman8181bd12008-07-27 21:46:04 +00002069 SDValue BRcpl =
Scott Michel4ec722e2008-07-16 17:17:29 +00002070 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2071 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002072 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002073
Scott Michel8efdca42007-12-04 22:23:35 +00002074 // Computes A * BRcpl and stores in a temporary register
Dan Gohman8181bd12008-07-27 21:46:04 +00002075 SDValue AxBRcpl =
Scott Michel8efdca42007-12-04 22:23:35 +00002076 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel4ec722e2008-07-16 17:17:29 +00002077 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002078 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel8efdca42007-12-04 22:23:35 +00002079 // What's the Chain variable do? It's magic!
2080 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel4ec722e2008-07-16 17:17:29 +00002081
2082 return DAG.getNode(ISD::FADD, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002083 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel4ec722e2008-07-16 17:17:29 +00002084 DAG.getNode(ISD::FMUL, VT,
2085 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002086 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel4ec722e2008-07-16 17:17:29 +00002087 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002088 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel8efdca42007-12-04 22:23:35 +00002089}
2090
Dan Gohman8181bd12008-07-27 21:46:04 +00002091static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002092 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002093 SDValue N = Op.getOperand(0);
2094 SDValue Elt = Op.getOperand(1);
Scott Michel56a125e2008-11-22 23:50:42 +00002095 SDValue retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002096
Scott Michel56a125e2008-11-22 23:50:42 +00002097 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2098 // Constant argument:
2099 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002100
Scott Michel56a125e2008-11-22 23:50:42 +00002101 // sanity checks:
2102 if (VT == MVT::i8 && EltNo >= 16)
2103 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2104 else if (VT == MVT::i16 && EltNo >= 8)
2105 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2106 else if (VT == MVT::i32 && EltNo >= 4)
2107 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2108 else if (VT == MVT::i64 && EltNo >= 2)
2109 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel8efdca42007-12-04 22:23:35 +00002110
Scott Michel56a125e2008-11-22 23:50:42 +00002111 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2112 // i32 and i64: Element 0 is the preferred slot
Scott Michelc630c412008-11-24 17:11:17 +00002113 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel56a125e2008-11-22 23:50:42 +00002114 }
Scott Michel8efdca42007-12-04 22:23:35 +00002115
Scott Michel56a125e2008-11-22 23:50:42 +00002116 // Need to generate shuffle mask and extract:
2117 int prefslot_begin = -1, prefslot_end = -1;
2118 int elt_byte = EltNo * VT.getSizeInBits() / 8;
2119
2120 switch (VT.getSimpleVT()) {
2121 default:
2122 assert(false && "Invalid value type!");
2123 case MVT::i8: {
2124 prefslot_begin = prefslot_end = 3;
2125 break;
2126 }
2127 case MVT::i16: {
2128 prefslot_begin = 2; prefslot_end = 3;
2129 break;
2130 }
2131 case MVT::i32:
2132 case MVT::f32: {
2133 prefslot_begin = 0; prefslot_end = 3;
2134 break;
2135 }
2136 case MVT::i64:
2137 case MVT::f64: {
2138 prefslot_begin = 0; prefslot_end = 7;
2139 break;
2140 }
2141 }
2142
2143 assert(prefslot_begin != -1 && prefslot_end != -1 &&
2144 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2145
2146 unsigned int ShufBytes[16];
2147 for (int i = 0; i < 16; ++i) {
2148 // zero fill uppper part of preferred slot, don't care about the
2149 // other slots:
2150 unsigned int mask_val;
2151 if (i <= prefslot_end) {
2152 mask_val =
2153 ((i < prefslot_begin)
2154 ? 0x80
2155 : elt_byte + (i - prefslot_begin));
2156
2157 ShufBytes[i] = mask_val;
2158 } else
2159 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2160 }
2161
2162 SDValue ShufMask[4];
2163 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
Scott Michele2641a12008-12-04 21:01:44 +00002164 unsigned bidx = i * 4;
Scott Michel56a125e2008-11-22 23:50:42 +00002165 unsigned int bits = ((ShufBytes[bidx] << 24) |
2166 (ShufBytes[bidx+1] << 16) |
2167 (ShufBytes[bidx+2] << 8) |
2168 ShufBytes[bidx+3]);
2169 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
2170 }
2171
2172 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2173 &ShufMask[0],
2174 sizeof(ShufMask) / sizeof(ShufMask[0]));
2175
Scott Michelc630c412008-11-24 17:11:17 +00002176 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel56a125e2008-11-22 23:50:42 +00002177 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2178 N, N, ShufMaskVec));
2179 } else {
2180 // Variable index: Rotate the requested element into slot 0, then replicate
2181 // slot 0 across the vector
2182 MVT VecVT = N.getValueType();
2183 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2184 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2185 abort();
2186 }
2187
2188 // Make life easier by making sure the index is zero-extended to i32
2189 if (Elt.getValueType() != MVT::i32)
2190 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2191
2192 // Scale the index to a bit/byte shift quantity
2193 APInt scaleFactor =
Scott Michelc630c412008-11-24 17:11:17 +00002194 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2195 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel56a125e2008-11-22 23:50:42 +00002196 SDValue vecShift;
Scott Michel56a125e2008-11-22 23:50:42 +00002197
Scott Michelc630c412008-11-24 17:11:17 +00002198 if (scaleShift > 0) {
2199 // Scale the shift factor:
Scott Michel56a125e2008-11-22 23:50:42 +00002200 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel0718cd82008-12-01 17:56:02 +00002201 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel56a125e2008-11-22 23:50:42 +00002202 }
2203
Scott Michelc630c412008-11-24 17:11:17 +00002204 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2205
2206 // Replicate the bytes starting at byte 0 across the entire vector (for
2207 // consistency with the notion of a unified register set)
Scott Michel56a125e2008-11-22 23:50:42 +00002208 SDValue replicate;
2209
2210 switch (VT.getSimpleVT()) {
2211 default:
2212 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2213 abort();
2214 /*NOTREACHED*/
2215 case MVT::i8: {
Scott Michelc630c412008-11-24 17:11:17 +00002216 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002217 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2218 factor, factor);
2219 break;
2220 }
2221 case MVT::i16: {
Scott Michelc630c412008-11-24 17:11:17 +00002222 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002223 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2224 factor, factor);
2225 break;
2226 }
2227 case MVT::i32:
2228 case MVT::f32: {
2229 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2230 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2231 factor, factor);
2232 break;
2233 }
2234 case MVT::i64:
2235 case MVT::f64: {
2236 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2237 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2238 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2239 loFactor, hiFactor);
2240 break;
2241 }
2242 }
2243
Scott Michelc630c412008-11-24 17:11:17 +00002244 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel0718cd82008-12-01 17:56:02 +00002245 DAG.getNode(SPUISD::SHUFB, VecVT,
2246 vecShift, vecShift, replicate));
Scott Michel8efdca42007-12-04 22:23:35 +00002247 }
2248
Scott Michel56a125e2008-11-22 23:50:42 +00002249 return retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002250}
2251
Dan Gohman8181bd12008-07-27 21:46:04 +00002252static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2253 SDValue VecOp = Op.getOperand(0);
2254 SDValue ValOp = Op.getOperand(1);
2255 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002256 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002257
2258 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2259 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2260
Duncan Sands92c43912008-06-06 12:08:01 +00002261 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel0718cd82008-12-01 17:56:02 +00002262 // Use $sp ($1) because it's always 16-byte aligned and it's available:
2263 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
2264 DAG.getRegister(SPU::R1, PtrVT),
2265 DAG.getConstant(CN->getSExtValue(), PtrVT));
2266 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, VT, Pointer);
Scott Michel8efdca42007-12-04 22:23:35 +00002267
Dan Gohman8181bd12008-07-27 21:46:04 +00002268 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002269 DAG.getNode(SPUISD::SHUFB, VT,
2270 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
Scott Michel0718cd82008-12-01 17:56:02 +00002271 VecOp,
2272 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, ShufMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002273
2274 return result;
2275}
2276
Dan Gohman8181bd12008-07-27 21:46:04 +00002277static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002278{
Dan Gohman8181bd12008-07-27 21:46:04 +00002279 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel8efdca42007-12-04 22:23:35 +00002280
2281 assert(Op.getValueType() == MVT::i8);
2282 switch (Opc) {
2283 default:
2284 assert(0 && "Unhandled i8 math operator");
2285 /*NOTREACHED*/
2286 break;
2287 case ISD::SUB: {
2288 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2289 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002290 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002291 N0 = (N0.getOpcode() != ISD::Constant
2292 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002293 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2294 MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00002295 N1 = (N1.getOpcode() != ISD::Constant
2296 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002297 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2298 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002299 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002300 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002301 }
Scott Michel8efdca42007-12-04 22:23:35 +00002302 case ISD::ROTR:
2303 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002304 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002305 unsigned N1Opc;
2306 N0 = (N0.getOpcode() != ISD::Constant
2307 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002308 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2309 MVT::i16));
Duncan Sands7aef60d2008-10-30 19:24:28 +00002310 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greife9f7f582008-08-31 15:37:04 +00002311 ? ISD::ZERO_EXTEND
2312 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002313 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sands7aef60d2008-10-30 19:24:28 +00002314 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002315 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sands7aef60d2008-10-30 19:24:28 +00002316 MVT::i32));
Dan Gohman8181bd12008-07-27 21:46:04 +00002317 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002318 DAG.getNode(ISD::OR, MVT::i16, N0,
2319 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sands7aef60d2008-10-30 19:24:28 +00002320 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002321 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002322 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2323 }
2324 case ISD::SRL:
2325 case ISD::SHL: {
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::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002330 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2331 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002332 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2333 ? ISD::ZERO_EXTEND
2334 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002335 N1 = (N1.getOpcode() != ISD::Constant
2336 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002337 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2338 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002339 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002340 DAG.getNode(Opc, MVT::i16, N0, N1));
2341 }
2342 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002343 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002344 unsigned N1Opc;
2345 N0 = (N0.getOpcode() != ISD::Constant
2346 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002347 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2348 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002349 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2350 ? ISD::SIGN_EXTEND
2351 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002352 N1 = (N1.getOpcode() != ISD::Constant
2353 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002354 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2355 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002356 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002357 DAG.getNode(Opc, MVT::i16, N0, N1));
2358 }
2359 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002360 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002361 unsigned N1Opc;
2362 N0 = (N0.getOpcode() != ISD::Constant
2363 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002364 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2365 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002366 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002367 N1 = (N1.getOpcode() != ISD::Constant
2368 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002369 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2370 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002371 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002372 DAG.getNode(Opc, MVT::i16, N0, N1));
2373 break;
2374 }
2375 }
2376
Dan Gohman8181bd12008-07-27 21:46:04 +00002377 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002378}
2379
Dan Gohman8181bd12008-07-27 21:46:04 +00002380static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002381{
Duncan Sands92c43912008-06-06 12:08:01 +00002382 MVT VT = Op.getValueType();
2383 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002384
Dan Gohman8181bd12008-07-27 21:46:04 +00002385 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002386
2387 switch (Opc) {
2388 case ISD::ZERO_EXTEND:
2389 case ISD::SIGN_EXTEND:
2390 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002391 MVT Op0VT = Op0.getValueType();
2392 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002393
2394 assert(Op0VT == MVT::i32
2395 && "CellSPU: Zero/sign extending something other than i32");
2396
Scott Michelc630c412008-11-24 17:11:17 +00002397 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2398
Dan Gohman8181bd12008-07-27 21:46:04 +00002399 SDValue PromoteScalar =
Scott Michelc630c412008-11-24 17:11:17 +00002400 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
Scott Michel97872d32008-02-23 18:41:37 +00002401
Scott Michelc630c412008-11-24 17:11:17 +00002402 if (Opc != ISD::SIGN_EXTEND) {
Scott Michelf2df6cb2008-11-24 18:20:46 +00002403 // Use a shuffle to zero extend the i32 to i64 directly:
2404 SDValue shufMask =
2405 DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2406 DAG.getConstant(0x80808080, MVT::i32),
2407 DAG.getConstant(0x00010203, MVT::i32),
2408 DAG.getConstant(0x80808080, MVT::i32),
2409 DAG.getConstant(0x08090a0b, MVT::i32));
2410 SDValue zextShuffle =
2411 DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2412 PromoteScalar, PromoteScalar, shufMask);
2413
Scott Michelc630c412008-11-24 17:11:17 +00002414 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michelf2df6cb2008-11-24 18:20:46 +00002415 DAG.getNode(ISD::BIT_CONVERT, VecVT, zextShuffle));
Scott Michelc630c412008-11-24 17:11:17 +00002416 } else {
2417 // SPU has no "rotate quadword and replicate bit 0" (i.e. rotate/shift
2418 // right and propagate the sign bit) instruction.
Scott Michelf2df6cb2008-11-24 18:20:46 +00002419 SDValue RotQuad =
2420 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, Op0VecVT,
2421 PromoteScalar, DAG.getConstant(4, MVT::i32));
Scott Michelc630c412008-11-24 17:11:17 +00002422 SDValue SignQuad =
2423 DAG.getNode(SPUISD::VEC_SRA, Op0VecVT,
2424 PromoteScalar, DAG.getConstant(32, MVT::i32));
2425 SDValue SelMask =
2426 DAG.getNode(SPUISD::SELECT_MASK, Op0VecVT,
2427 DAG.getConstant(0xf0f0, MVT::i16));
2428 SDValue CombineQuad =
2429 DAG.getNode(SPUISD::SELB, Op0VecVT,
2430 SignQuad, RotQuad, SelMask);
2431
2432 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2433 DAG.getNode(ISD::BIT_CONVERT, VecVT, CombineQuad));
2434 }
Scott Michel97872d32008-02-23 18:41:37 +00002435 }
2436
Scott Michel67224b22008-06-02 22:18:03 +00002437 case ISD::ADD: {
2438 // Turn operands into vectors to satisfy type checking (shufb works on
2439 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002440 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002441 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002442 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002443 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002444 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002445
2446 // Create the shuffle mask for "rotating" the borrow up one register slot
2447 // once the borrow is generated.
2448 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2449 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2450 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2451 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2452
Dan Gohman8181bd12008-07-27 21:46:04 +00002453 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002454 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002455 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002456 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2457 CarryGen, CarryGen,
2458 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2459 &ShufBytes[0], ShufBytes.size()));
2460
Scott Michelc630c412008-11-24 17:11:17 +00002461 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002462 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2463 Op0, Op1, ShiftedCarry));
2464 }
2465
2466 case ISD::SUB: {
2467 // Turn operands into vectors to satisfy type checking (shufb works on
2468 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002469 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002470 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002471 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002472 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002473 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002474
2475 // Create the shuffle mask for "rotating" the borrow up one register slot
2476 // once the borrow is generated.
2477 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2478 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2479 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2480 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2481
Dan Gohman8181bd12008-07-27 21:46:04 +00002482 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002483 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002484 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002485 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2486 BorrowGen, BorrowGen,
2487 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2488 &ShufBytes[0], ShufBytes.size()));
2489
Scott Michelc630c412008-11-24 17:11:17 +00002490 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002491 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2492 Op0, Op1, ShiftedBorrow));
2493 }
2494
Scott Michel97872d32008-02-23 18:41:37 +00002495 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002496 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002497 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002498 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2499 SDValue MaskLower =
Scott Michel97872d32008-02-23 18:41:37 +00002500 DAG.getNode(SPUISD::SELB, VecVT,
2501 Op0Vec,
2502 DAG.getConstant(0, VecVT),
Scott Michel67224b22008-06-02 22:18:03 +00002503 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michel97872d32008-02-23 18:41:37 +00002504 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman8181bd12008-07-27 21:46:04 +00002505 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002506 DAG.getNode(ISD::SRL, ShiftAmtVT,
2507 ShiftAmt,
2508 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002509 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002510 DAG.getNode(ISD::AND, ShiftAmtVT,
2511 ShiftAmt,
2512 DAG.getConstant(7, ShiftAmtVT));
2513
Scott Michelc630c412008-11-24 17:11:17 +00002514 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel97872d32008-02-23 18:41:37 +00002515 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2516 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2517 MaskLower, ShiftAmtBytes),
2518 ShiftAmtBits));
2519 }
2520
2521 case ISD::SRL: {
Duncan Sands92c43912008-06-06 12:08:01 +00002522 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002523 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002524 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002525 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002526 DAG.getNode(ISD::SRL, ShiftAmtVT,
2527 ShiftAmt,
2528 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002529 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002530 DAG.getNode(ISD::AND, ShiftAmtVT,
2531 ShiftAmt,
2532 DAG.getConstant(7, ShiftAmtVT));
2533
2534 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2535 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2536 Op0, ShiftAmtBytes),
2537 ShiftAmtBits);
2538 }
Scott Michel67224b22008-06-02 22:18:03 +00002539
2540 case ISD::SRA: {
2541 // Promote Op0 to vector
Dan Gohman8181bd12008-07-27 21:46:04 +00002542 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002543 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002544 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002545 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel67224b22008-06-02 22:18:03 +00002546
2547 // Negate variable shift amounts
2548 if (!isa<ConstantSDNode>(ShiftAmt)) {
2549 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2550 DAG.getConstant(0, ShiftVT), ShiftAmt);
2551 }
2552
Dan Gohman8181bd12008-07-27 21:46:04 +00002553 SDValue UpperHalfSign =
Scott Michelc630c412008-11-24 17:11:17 +00002554 DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i32,
Scott Michel67224b22008-06-02 22:18:03 +00002555 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2556 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2557 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman8181bd12008-07-27 21:46:04 +00002558 SDValue UpperHalfSignMask =
Scott Michel67224b22008-06-02 22:18:03 +00002559 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman8181bd12008-07-27 21:46:04 +00002560 SDValue UpperLowerMask =
Scott Michel67224b22008-06-02 22:18:03 +00002561 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2562 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman8181bd12008-07-27 21:46:04 +00002563 SDValue UpperLowerSelect =
Scott Michel67224b22008-06-02 22:18:03 +00002564 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2565 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman8181bd12008-07-27 21:46:04 +00002566 SDValue RotateLeftBytes =
Scott Michel67224b22008-06-02 22:18:03 +00002567 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2568 UpperLowerSelect, ShiftAmt);
Dan Gohman8181bd12008-07-27 21:46:04 +00002569 SDValue RotateLeftBits =
Scott Michel67224b22008-06-02 22:18:03 +00002570 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2571 RotateLeftBytes, ShiftAmt);
2572
Scott Michelc630c412008-11-24 17:11:17 +00002573 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002574 RotateLeftBits);
2575 }
Scott Michel97872d32008-02-23 18:41:37 +00002576 }
2577
Dan Gohman8181bd12008-07-27 21:46:04 +00002578 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002579}
2580
Scott Michel8efdca42007-12-04 22:23:35 +00002581//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002582static SDValue
2583LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2584 SDValue ConstVec;
2585 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002586 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002587
2588 ConstVec = Op.getOperand(0);
2589 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002590 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2591 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002592 ConstVec = ConstVec.getOperand(0);
2593 } else {
2594 ConstVec = Op.getOperand(1);
2595 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002596 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002597 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002598 }
2599 }
2600 }
2601
Gabor Greif1c80d112008-08-28 21:40:38 +00002602 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002603 uint64_t VectorBits[2];
2604 uint64_t UndefBits[2];
2605 uint64_t SplatBits, SplatUndef;
2606 int SplatSize;
2607
Gabor Greif1c80d112008-08-28 21:40:38 +00002608 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002609 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002610 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002611 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002612 SDValue tcVec[16];
2613 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002614 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2615
2616 // Turn the BUILD_VECTOR into a set of target constants:
2617 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002618 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002619
Gabor Greif1c80d112008-08-28 21:40:38 +00002620 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002621 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002622 }
2623 }
Nate Begeman7569e762008-07-29 19:07:27 +00002624 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2625 // lowered. Return the operation, rather than a null SDValue.
2626 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002627}
2628
2629//! Lower i32 multiplication
Dan Gohman8181bd12008-07-27 21:46:04 +00002630static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel8efdca42007-12-04 22:23:35 +00002631 unsigned Opc) {
Duncan Sands92c43912008-06-06 12:08:01 +00002632 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00002633 default:
2634 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands92c43912008-06-06 12:08:01 +00002635 << Op.getValueType().getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +00002636 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +00002637 abort();
2638 /*NOTREACHED*/
2639
2640 case MVT::i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002641 SDValue rA = Op.getOperand(0);
2642 SDValue rB = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002643
2644 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002645 DAG.getNode(ISD::ADD, MVT::i32,
2646 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2647 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2648 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00002649 }
2650 }
2651
Dan Gohman8181bd12008-07-27 21:46:04 +00002652 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002653}
2654
2655//! Custom lowering for CTPOP (count population)
2656/*!
2657 Custom lowering code that counts the number ones in the input
2658 operand. SPU has such an instruction, but it counts the number of
2659 ones per byte, which then have to be accumulated.
2660*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002661static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002662 MVT VT = Op.getValueType();
2663 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002664
Duncan Sands92c43912008-06-06 12:08:01 +00002665 switch (VT.getSimpleVT()) {
2666 default:
2667 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002668 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002669 SDValue N = Op.getOperand(0);
2670 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002671
Dan Gohman8181bd12008-07-27 21:46:04 +00002672 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2673 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002674
2675 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2676 }
2677
2678 case MVT::i16: {
2679 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002680 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002681
Chris Lattner1b989192007-12-31 04:13:23 +00002682 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002683
Dan Gohman8181bd12008-07-27 21:46:04 +00002684 SDValue N = Op.getOperand(0);
2685 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2686 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sands7aef60d2008-10-30 19:24:28 +00002687 SDValue Shift1 = 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::i16, 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 Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002701
2702 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002703 DAG.getNode(ISD::ADD, MVT::i16,
2704 DAG.getNode(ISD::SRL, MVT::i16,
2705 Tmp1, Shift1),
2706 Tmp1),
2707 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002708 }
2709
2710 case MVT::i32: {
2711 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002712 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002713
Chris Lattner1b989192007-12-31 04:13:23 +00002714 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2715 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002716
Dan Gohman8181bd12008-07-27 21:46:04 +00002717 SDValue N = Op.getOperand(0);
2718 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2719 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2720 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2721 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002722
Dan Gohman8181bd12008-07-27 21:46:04 +00002723 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2724 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002725
2726 // CNTB_result becomes the chain to which all of the virtual registers
2727 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002728 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002729 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002730
Dan Gohman8181bd12008-07-27 21:46:04 +00002731 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002732 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2733
Dan Gohman8181bd12008-07-27 21:46:04 +00002734 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002735 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002736 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002737
Dan Gohman8181bd12008-07-27 21:46:04 +00002738 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002739 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002740 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002741
Dan Gohman8181bd12008-07-27 21:46:04 +00002742 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002743 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2744
Dan Gohman8181bd12008-07-27 21:46:04 +00002745 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002746 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002747 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2748 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002749 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002750 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002751 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002752
2753 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2754 }
2755
2756 case MVT::i64:
2757 break;
2758 }
2759
Dan Gohman8181bd12008-07-27 21:46:04 +00002760 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002761}
2762
Scott Michel56a125e2008-11-22 23:50:42 +00002763//! Lower ISD::SELECT_CC
2764/*!
2765 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2766 SELB instruction.
2767
2768 \note Need to revisit this in the future: if the code path through the true
2769 and false value computations is longer than the latency of a branch (6
2770 cycles), then it would be more advantageous to branch and insert a new basic
2771 block and branch on the condition. However, this code does not make that
2772 assumption, given the simplisitc uses so far.
2773 */
2774
2775static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
2776 MVT VT = Op.getValueType();
2777 SDValue lhs = Op.getOperand(0);
2778 SDValue rhs = Op.getOperand(1);
2779 SDValue trueval = Op.getOperand(2);
2780 SDValue falseval = Op.getOperand(3);
2781 SDValue condition = Op.getOperand(4);
2782
2783 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2784 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2785 // with another "cannot select select_cc" assert:
2786
2787 SDValue compare = DAG.getNode(ISD::SETCC, VT, lhs, rhs, condition);
2788 return DAG.getNode(SPUISD::SELB, VT, trueval, falseval, compare);
2789}
2790
Scott Michelec8c82e2008-12-02 19:53:53 +00002791//! Custom lower ISD::TRUNCATE
2792static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
2793{
2794 MVT VT = Op.getValueType();
2795 MVT::SimpleValueType simpleVT = VT.getSimpleVT();
2796 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
2797
2798 SDValue Op0 = Op.getOperand(0);
2799 MVT Op0VT = Op0.getValueType();
2800 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
2801
2802 SDValue PromoteScalar = DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2803
2804 unsigned maskLow;
2805 unsigned maskHigh;
2806
2807 // Create shuffle mask
2808 switch (Op0VT.getSimpleVT()) {
2809 case MVT::i128:
2810 switch (simpleVT) {
2811 case MVT::i64:
2812 // least significant doubleword of quadword
2813 maskHigh = 0x08090a0b;
2814 maskLow = 0x0c0d0e0f;
2815 break;
2816 case MVT::i32:
2817 // least significant word of quadword
2818 maskHigh = maskLow = 0x0c0d0e0f;
2819 break;
2820 case MVT::i16:
2821 // least significant halfword of quadword
2822 maskHigh = maskLow = 0x0e0f0e0f;
2823 break;
2824 case MVT::i8:
2825 // least significant byte of quadword
2826 maskHigh = maskLow = 0x0f0f0f0f;
2827 break;
2828 default:
2829 cerr << "Truncation to illegal type!";
2830 abort();
2831 }
2832 break;
2833 case MVT::i64:
2834 switch (simpleVT) {
2835 case MVT::i32:
2836 // least significant word of doubleword
2837 maskHigh = maskLow = 0x04050607;
2838 break;
2839 case MVT::i16:
2840 // least significant halfword of doubleword
2841 maskHigh = maskLow = 0x06070607;
2842 break;
2843 case MVT::i8:
2844 // least significant byte of doubleword
2845 maskHigh = maskLow = 0x07070707;
2846 break;
2847 default:
2848 cerr << "Truncation to illegal type!";
2849 abort();
2850 }
2851 break;
2852 case MVT::i32:
2853 case MVT::i16:
2854 switch (simpleVT) {
2855 case MVT::i16:
2856 // least significant halfword of word
2857 maskHigh = maskLow = 0x02030203;
2858 break;
2859 case MVT::i8:
2860 // least significant byte of word/halfword
2861 maskHigh = maskLow = 0x03030303;
2862 break;
2863 default:
2864 cerr << "Truncation to illegal type!";
2865 abort();
2866 }
2867 break;
2868 default:
2869 cerr << "Trying to lower truncation from illegal type!";
2870 abort();
2871 }
2872
2873 // Use a shuffle to perform the truncation
2874 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2875 DAG.getConstant(maskHigh, MVT::i32),
2876 DAG.getConstant(maskLow, MVT::i32),
2877 DAG.getConstant(maskHigh, MVT::i32),
2878 DAG.getConstant(maskLow, MVT::i32));
2879
2880 SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2881 PromoteScalar, PromoteScalar, shufMask);
2882
2883 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2884 DAG.getNode(ISD::BIT_CONVERT, VecVT, truncShuffle));
2885}
2886
Scott Michel56a125e2008-11-22 23:50:42 +00002887//! Custom (target-specific) lowering entry point
2888/*!
2889 This is where LLVM's DAG selection process calls to do target-specific
2890 lowering of nodes.
2891 */
Dan Gohman8181bd12008-07-27 21:46:04 +00002892SDValue
2893SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel8efdca42007-12-04 22:23:35 +00002894{
Scott Michel97872d32008-02-23 18:41:37 +00002895 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands92c43912008-06-06 12:08:01 +00002896 MVT VT = Op.getValueType();
Scott Michel97872d32008-02-23 18:41:37 +00002897
2898 switch (Opc) {
Scott Michel8efdca42007-12-04 22:23:35 +00002899 default: {
2900 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michel97872d32008-02-23 18:41:37 +00002901 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greif1c80d112008-08-28 21:40:38 +00002902 cerr << "*Op.getNode():\n";
2903 Op.getNode()->dump();
Scott Michel8efdca42007-12-04 22:23:35 +00002904 abort();
2905 }
2906 case ISD::LOAD:
Scott Michelec8c82e2008-12-02 19:53:53 +00002907 case ISD::EXTLOAD:
Scott Michel8efdca42007-12-04 22:23:35 +00002908 case ISD::SEXTLOAD:
2909 case ISD::ZEXTLOAD:
2910 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2911 case ISD::STORE:
2912 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2913 case ISD::ConstantPool:
2914 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2915 case ISD::GlobalAddress:
2916 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2917 case ISD::JumpTable:
2918 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2919 case ISD::Constant:
2920 return LowerConstant(Op, DAG);
2921 case ISD::ConstantFP:
2922 return LowerConstantFP(Op, DAG);
Scott Michel394e26d2008-01-17 20:38:41 +00002923 case ISD::BRCOND:
2924 return LowerBRCOND(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002925 case ISD::FORMAL_ARGUMENTS:
Scott Michel394e26d2008-01-17 20:38:41 +00002926 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel8efdca42007-12-04 22:23:35 +00002927 case ISD::CALL:
Scott Micheldbac4cf2008-01-11 02:53:15 +00002928 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel8efdca42007-12-04 22:23:35 +00002929 case ISD::RET:
2930 return LowerRET(Op, DAG, getTargetMachine());
2931
Scott Michel97872d32008-02-23 18:41:37 +00002932
2933 // i8, i64 math ops:
2934 case ISD::ZERO_EXTEND:
2935 case ISD::SIGN_EXTEND:
2936 case ISD::ANY_EXTEND:
Scott Michel67224b22008-06-02 22:18:03 +00002937 case ISD::ADD:
Scott Michel8efdca42007-12-04 22:23:35 +00002938 case ISD::SUB:
2939 case ISD::ROTR:
2940 case ISD::ROTL:
2941 case ISD::SRL:
2942 case ISD::SHL:
Scott Michel67224b22008-06-02 22:18:03 +00002943 case ISD::SRA: {
Scott Michel97872d32008-02-23 18:41:37 +00002944 if (VT == MVT::i8)
2945 return LowerI8Math(Op, DAG, Opc);
2946 else if (VT == MVT::i64)
2947 return LowerI64Math(Op, DAG, Opc);
2948 break;
Scott Michel67224b22008-06-02 22:18:03 +00002949 }
Scott Michel8efdca42007-12-04 22:23:35 +00002950
2951 // Vector-related lowering.
2952 case ISD::BUILD_VECTOR:
2953 return LowerBUILD_VECTOR(Op, DAG);
2954 case ISD::SCALAR_TO_VECTOR:
2955 return LowerSCALAR_TO_VECTOR(Op, DAG);
2956 case ISD::VECTOR_SHUFFLE:
2957 return LowerVECTOR_SHUFFLE(Op, DAG);
2958 case ISD::EXTRACT_VECTOR_ELT:
2959 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2960 case ISD::INSERT_VECTOR_ELT:
2961 return LowerINSERT_VECTOR_ELT(Op, DAG);
2962
2963 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2964 case ISD::AND:
2965 case ISD::OR:
2966 case ISD::XOR:
2967 return LowerByteImmed(Op, DAG);
2968
2969 // Vector and i8 multiply:
2970 case ISD::MUL:
Duncan Sands92c43912008-06-06 12:08:01 +00002971 if (VT.isVector())
Scott Michel8efdca42007-12-04 22:23:35 +00002972 return LowerVectorMUL(Op, DAG);
Scott Michel97872d32008-02-23 18:41:37 +00002973 else if (VT == MVT::i8)
2974 return LowerI8Math(Op, DAG, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002975 else
Scott Michel97872d32008-02-23 18:41:37 +00002976 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002977
2978 case ISD::FDIV:
Scott Michel97872d32008-02-23 18:41:37 +00002979 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel8efdca42007-12-04 22:23:35 +00002980 return LowerFDIVf32(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002981#if 0
2982 // This is probably a libcall
2983 else if (Op.getValueType() == MVT::f64)
2984 return LowerFDIVf64(Op, DAG);
2985#endif
Scott Michel8efdca42007-12-04 22:23:35 +00002986 else
2987 assert(0 && "Calling FDIV on unsupported MVT");
2988
2989 case ISD::CTPOP:
2990 return LowerCTPOP(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002991
2992 case ISD::SELECT_CC:
2993 return LowerSELECT_CC(Op, DAG);
Scott Michelec8c82e2008-12-02 19:53:53 +00002994
2995 case ISD::TRUNCATE:
2996 return LowerTRUNCATE(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002997 }
2998
Dan Gohman8181bd12008-07-27 21:46:04 +00002999 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00003000}
3001
Duncan Sands7d9834b2008-12-01 11:39:25 +00003002void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
3003 SmallVectorImpl<SDValue>&Results,
3004 SelectionDAG &DAG)
Scott Michel6e2d68b2008-11-10 23:43:06 +00003005{
3006#if 0
3007 unsigned Opc = (unsigned) N->getOpcode();
3008 MVT OpVT = N->getValueType(0);
3009
3010 switch (Opc) {
3011 default: {
3012 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
3013 cerr << "Op.getOpcode() = " << Opc << "\n";
3014 cerr << "*Op.getNode():\n";
3015 N->dump();
3016 abort();
3017 /*NOTREACHED*/
3018 }
3019 }
3020#endif
3021
3022 /* Otherwise, return unchanged */
Scott Michel6e2d68b2008-11-10 23:43:06 +00003023}
3024
Scott Michel8efdca42007-12-04 22:23:35 +00003025//===----------------------------------------------------------------------===//
Scott Michel8efdca42007-12-04 22:23:35 +00003026// Target Optimization Hooks
3027//===----------------------------------------------------------------------===//
3028
Dan Gohman8181bd12008-07-27 21:46:04 +00003029SDValue
Scott Michel8efdca42007-12-04 22:23:35 +00003030SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
3031{
3032#if 0
3033 TargetMachine &TM = getTargetMachine();
Scott Michelf9f42e62008-01-29 02:16:57 +00003034#endif
3035 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel8efdca42007-12-04 22:23:35 +00003036 SelectionDAG &DAG = DCI.DAG;
Scott Michel0718cd82008-12-01 17:56:02 +00003037 SDValue Op0 = N->getOperand(0); // everything has at least one operand
3038 MVT NodeVT = N->getValueType(0); // The node's value type
3039 MVT Op0VT = Op0.getValueType(); // The first operand's result
3040 SDValue Result; // Initially, empty result
Scott Michel8efdca42007-12-04 22:23:35 +00003041
3042 switch (N->getOpcode()) {
3043 default: break;
Scott Michelf9f42e62008-01-29 02:16:57 +00003044 case ISD::ADD: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003045 SDValue Op1 = N->getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003046
Scott Michel67224b22008-06-02 22:18:03 +00003047 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003048 SDValue Op01 = Op0.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003049 if (Op01.getOpcode() == ISD::Constant
3050 || Op01.getOpcode() == ISD::TargetConstant) {
3051 // (add <const>, (SPUindirect <arg>, <const>)) ->
3052 // (SPUindirect <arg>, <const + const>)
3053 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
3054 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman8181bd12008-07-27 21:46:04 +00003055 SDValue combinedConst =
Scott Michel0718cd82008-12-01 17:56:02 +00003056 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(), Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00003057
Scott Michel8c2746e2008-12-04 17:16:59 +00003058#if !defined(NDEBUG)
Scott Michel6ccefab2008-12-04 03:02:42 +00003059 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
3060 cerr << "\n"
3061 << "Replace: (add " << CN0->getZExtValue() << ", "
3062 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n"
3063 << "With: (SPUindirect <arg>, "
3064 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n";
3065 }
3066#endif
3067
Scott Michel0718cd82008-12-01 17:56:02 +00003068 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
Scott Michelf9f42e62008-01-29 02:16:57 +00003069 Op0.getOperand(0), combinedConst);
3070 }
Scott Michel67224b22008-06-02 22:18:03 +00003071 } else if (isa<ConstantSDNode>(Op0)
Scott Michelf9f42e62008-01-29 02:16:57 +00003072 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003073 SDValue Op11 = Op1.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00003074 if (Op11.getOpcode() == ISD::Constant
3075 || Op11.getOpcode() == ISD::TargetConstant) {
3076 // (add (SPUindirect <arg>, <const>), <const>) ->
3077 // (SPUindirect <arg>, <const + const>)
3078 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
3079 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman8181bd12008-07-27 21:46:04 +00003080 SDValue combinedConst =
Scott Michel0718cd82008-12-01 17:56:02 +00003081 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(), Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00003082
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003083 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
3084 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00003085 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003086 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00003087
3088 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
3089 Op1.getOperand(0), combinedConst);
3090 }
3091 }
Scott Michel97872d32008-02-23 18:41:37 +00003092 break;
3093 }
3094 case ISD::SIGN_EXTEND:
3095 case ISD::ZERO_EXTEND:
3096 case ISD::ANY_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00003097 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
Scott Michel97872d32008-02-23 18:41:37 +00003098 // (any_extend (SPUextract_elt0 <arg>)) ->
3099 // (SPUextract_elt0 <arg>)
3100 // Types must match, however...
Scott Michel8c2746e2008-12-04 17:16:59 +00003101#if !defined(NDEBUG)
3102 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel6ccefab2008-12-04 03:02:42 +00003103 cerr << "\nReplace: ";
3104 N->dump(&DAG);
3105 cerr << "\nWith: ";
3106 Op0.getNode()->dump(&DAG);
3107 cerr << "\n";
Scott Michel8c2746e2008-12-04 17:16:59 +00003108 }
Scott Michel6ccefab2008-12-04 03:02:42 +00003109#endif
Scott Michel97872d32008-02-23 18:41:37 +00003110
3111 return Op0;
3112 }
3113 break;
3114 }
3115 case SPUISD::IndirectAddr: {
3116 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
3117 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003118 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00003119 // (SPUindirect (SPUaform <addr>, 0), 0) ->
3120 // (SPUaform <addr>, 0)
3121
3122 DEBUG(cerr << "Replace: ");
3123 DEBUG(N->dump(&DAG));
3124 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003125 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003126 DEBUG(cerr << "\n");
3127
3128 return Op0;
3129 }
3130 }
3131 break;
3132 }
3133 case SPUISD::SHLQUAD_L_BITS:
3134 case SPUISD::SHLQUAD_L_BYTES:
3135 case SPUISD::VEC_SHL:
3136 case SPUISD::VEC_SRL:
3137 case SPUISD::VEC_SRA:
3138 case SPUISD::ROTQUAD_RZ_BYTES:
3139 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003140 SDValue Op1 = N->getOperand(1);
Scott Michel97872d32008-02-23 18:41:37 +00003141
3142 if (isa<ConstantSDNode>(Op1)) {
3143 // Kill degenerate vector shifts:
3144 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003145 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00003146 Result = Op0;
3147 }
3148 }
3149 break;
3150 }
3151 case SPUISD::PROMOTE_SCALAR: {
3152 switch (Op0.getOpcode()) {
3153 default:
3154 break;
3155 case ISD::ANY_EXTEND:
3156 case ISD::ZERO_EXTEND:
3157 case ISD::SIGN_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00003158 // (SPUpromote_scalar (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
Scott Michel97872d32008-02-23 18:41:37 +00003159 // <arg>
3160 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman8181bd12008-07-27 21:46:04 +00003161 SDValue Op00 = Op0.getOperand(0);
Scott Michelc630c412008-11-24 17:11:17 +00003162 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003163 SDValue Op000 = Op00.getOperand(0);
Scott Michel0718cd82008-12-01 17:56:02 +00003164 if (Op000.getValueType() == NodeVT) {
Scott Michel97872d32008-02-23 18:41:37 +00003165 Result = Op000;
3166 }
3167 }
3168 break;
3169 }
Scott Michelc630c412008-11-24 17:11:17 +00003170 case SPUISD::VEC2PREFSLOT: {
Scott Michel0718cd82008-12-01 17:56:02 +00003171 // (SPUpromote_scalar (SPUvec2prefslot <arg>)) ->
Scott Michel97872d32008-02-23 18:41:37 +00003172 // <arg>
3173 Result = Op0.getOperand(0);
3174 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003175 }
Scott Michel97872d32008-02-23 18:41:37 +00003176 }
3177 break;
Scott Michelf9f42e62008-01-29 02:16:57 +00003178 }
3179 }
Scott Michel394e26d2008-01-17 20:38:41 +00003180 // Otherwise, return unchanged.
Scott Michel0718cd82008-12-01 17:56:02 +00003181#ifndef NDEBUG
Gabor Greif1c80d112008-08-28 21:40:38 +00003182 if (Result.getNode()) {
Scott Michel97872d32008-02-23 18:41:37 +00003183 DEBUG(cerr << "\nReplace.SPU: ");
3184 DEBUG(N->dump(&DAG));
3185 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003186 DEBUG(Result.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003187 DEBUG(cerr << "\n");
3188 }
3189#endif
3190
3191 return Result;
Scott Michel8efdca42007-12-04 22:23:35 +00003192}
3193
3194//===----------------------------------------------------------------------===//
3195// Inline Assembly Support
3196//===----------------------------------------------------------------------===//
3197
3198/// getConstraintType - Given a constraint letter, return the type of
3199/// constraint it is for this target.
Scott Michel4ec722e2008-07-16 17:17:29 +00003200SPUTargetLowering::ConstraintType
Scott Michel8efdca42007-12-04 22:23:35 +00003201SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3202 if (ConstraintLetter.size() == 1) {
3203 switch (ConstraintLetter[0]) {
3204 default: break;
3205 case 'b':
3206 case 'r':
3207 case 'f':
3208 case 'v':
3209 case 'y':
3210 return C_RegisterClass;
Scott Michel4ec722e2008-07-16 17:17:29 +00003211 }
Scott Michel8efdca42007-12-04 22:23:35 +00003212 }
3213 return TargetLowering::getConstraintType(ConstraintLetter);
3214}
3215
Scott Michel4ec722e2008-07-16 17:17:29 +00003216std::pair<unsigned, const TargetRegisterClass*>
Scott Michel8efdca42007-12-04 22:23:35 +00003217SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands92c43912008-06-06 12:08:01 +00003218 MVT VT) const
Scott Michel8efdca42007-12-04 22:23:35 +00003219{
3220 if (Constraint.size() == 1) {
3221 // GCC RS6000 Constraint Letters
3222 switch (Constraint[0]) {
3223 case 'b': // R1-R31
3224 case 'r': // R0-R31
3225 if (VT == MVT::i64)
3226 return std::make_pair(0U, SPU::R64CRegisterClass);
3227 return std::make_pair(0U, SPU::R32CRegisterClass);
3228 case 'f':
3229 if (VT == MVT::f32)
3230 return std::make_pair(0U, SPU::R32FPRegisterClass);
3231 else if (VT == MVT::f64)
3232 return std::make_pair(0U, SPU::R64FPRegisterClass);
3233 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003234 case 'v':
Scott Michel8efdca42007-12-04 22:23:35 +00003235 return std::make_pair(0U, SPU::GPRCRegisterClass);
3236 }
3237 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003238
Scott Michel8efdca42007-12-04 22:23:35 +00003239 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3240}
3241
Scott Michel97872d32008-02-23 18:41:37 +00003242//! Compute used/known bits for a SPU operand
Scott Michel8efdca42007-12-04 22:23:35 +00003243void
Dan Gohman8181bd12008-07-27 21:46:04 +00003244SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohmand0dfc772008-02-13 22:28:48 +00003245 const APInt &Mask,
Scott Michel4ec722e2008-07-16 17:17:29 +00003246 APInt &KnownZero,
Dan Gohman229fa052008-02-13 00:35:47 +00003247 APInt &KnownOne,
Scott Michel5a6f17b2008-01-30 02:55:46 +00003248 const SelectionDAG &DAG,
3249 unsigned Depth ) const {
Scott Michelbc5fbc12008-04-30 00:30:08 +00003250#if 0
Scott Michel97872d32008-02-23 18:41:37 +00003251 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michelbc5fbc12008-04-30 00:30:08 +00003252#endif
Scott Michel97872d32008-02-23 18:41:37 +00003253
3254 switch (Op.getOpcode()) {
3255 default:
3256 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3257 break;
3258
3259#if 0
3260 case CALL:
3261 case SHUFB:
Scott Michel56a125e2008-11-22 23:50:42 +00003262 case SHUFFLE_MASK:
Scott Michel97872d32008-02-23 18:41:37 +00003263 case CNTB:
3264#endif
3265
3266 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003267 SDValue Op0 = Op.getOperand(0);
Duncan Sands92c43912008-06-06 12:08:01 +00003268 MVT Op0VT = Op0.getValueType();
3269 unsigned Op0VTBits = Op0VT.getSizeInBits();
3270 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003271 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3272 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003273 break;
3274 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003275
Scott Michel97872d32008-02-23 18:41:37 +00003276 case SPUISD::LDRESULT:
Scott Michel6ccefab2008-12-04 03:02:42 +00003277 case SPUISD::VEC2PREFSLOT: {
Duncan Sands92c43912008-06-06 12:08:01 +00003278 MVT OpVT = Op.getValueType();
3279 unsigned OpVTBits = OpVT.getSizeInBits();
3280 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003281 KnownZero |= APInt(OpVTBits, ~InMask, false);
3282 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003283 break;
3284 }
3285
3286#if 0
Scott Michel97872d32008-02-23 18:41:37 +00003287 case MPY:
3288 case MPYU:
3289 case MPYH:
3290 case MPYHH:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003291 case SPUISD::SHLQUAD_L_BITS:
3292 case SPUISD::SHLQUAD_L_BYTES:
3293 case SPUISD::VEC_SHL:
3294 case SPUISD::VEC_SRL:
3295 case SPUISD::VEC_SRA:
3296 case SPUISD::VEC_ROTL:
3297 case SPUISD::VEC_ROTR:
3298 case SPUISD::ROTQUAD_RZ_BYTES:
3299 case SPUISD::ROTQUAD_RZ_BITS:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003300 case SPUISD::ROTBYTES_LEFT:
Scott Michel67224b22008-06-02 22:18:03 +00003301 case SPUISD::SELECT_MASK:
3302 case SPUISD::SELB:
3303 case SPUISD::FPInterp:
3304 case SPUISD::FPRecipEst:
3305 case SPUISD::SEXT32TO64:
Scott Michel97872d32008-02-23 18:41:37 +00003306#endif
3307 }
Scott Michel8efdca42007-12-04 22:23:35 +00003308}
3309
Scott Michelbc5fbc12008-04-30 00:30:08 +00003310// LowerAsmOperandForConstraint
3311void
Dan Gohman8181bd12008-07-27 21:46:04 +00003312SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003313 char ConstraintLetter,
Evan Cheng7f250d62008-09-24 00:05:32 +00003314 bool hasMemory,
Dan Gohman8181bd12008-07-27 21:46:04 +00003315 std::vector<SDValue> &Ops,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003316 SelectionDAG &DAG) const {
3317 // Default, for the time being, to the base class handler
Evan Cheng7f250d62008-09-24 00:05:32 +00003318 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3319 Ops, DAG);
Scott Michelbc5fbc12008-04-30 00:30:08 +00003320}
3321
Scott Michel8efdca42007-12-04 22:23:35 +00003322/// isLegalAddressImmediate - Return true if the integer value can be used
3323/// as the offset of the target addressing mode.
Gabor Greife9f7f582008-08-31 15:37:04 +00003324bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3325 const Type *Ty) const {
Scott Michel8efdca42007-12-04 22:23:35 +00003326 // SPU's addresses are 256K:
3327 return (V > -(1 << 18) && V < (1 << 18) - 1);
3328}
3329
3330bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel4ec722e2008-07-16 17:17:29 +00003331 return false;
Scott Michel8efdca42007-12-04 22:23:35 +00003332}
Dan Gohman36322c72008-10-18 02:06:02 +00003333
3334bool
3335SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3336 // The SPU target isn't yet aware of offsets.
3337 return false;
3338}