blob: 086a25f1d8961342b27f7f1a8b6eb2a1af8dc181 [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 {
Duncan Sands92c43912008-06-06 12:08:01 +000042 const MVT valtype;
Scott Michel5a6f17b2008-01-30 02:55:46 +000043 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);
Chris Lattner3bc08502008-01-17 19:59:44 +0000137 setTruncStoreAction(MVT::i8, MVT::i1, Custom);
138 setTruncStoreAction(MVT::i16, MVT::i1, Custom);
139 setTruncStoreAction(MVT::i32, MVT::i1, Custom);
140 setTruncStoreAction(MVT::i64, MVT::i1, Custom);
141 setTruncStoreAction(MVT::i128, MVT::i1, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000142
Evan Cheng08c171a2008-10-14 21:26:46 +0000143 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
144 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
145 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Chris Lattner3bc08502008-01-17 19:59:44 +0000146 setTruncStoreAction(MVT::i8 , MVT::i8, Custom);
147 setTruncStoreAction(MVT::i16 , MVT::i8, Custom);
148 setTruncStoreAction(MVT::i32 , MVT::i8, Custom);
149 setTruncStoreAction(MVT::i64 , MVT::i8, Custom);
150 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000151
Evan Cheng08c171a2008-10-14 21:26:46 +0000152 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
153 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
154 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000155
156 // SPU constant load actions are custom lowered:
157 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begeman78125042008-02-14 18:43:04 +0000158 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000159 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
160
161 // SPU's loads and stores have to be custom lowered:
162 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
163 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000164 MVT VT = (MVT::SimpleValueType)sctype;
165
166 setOperationAction(ISD::LOAD, VT, Custom);
167 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000168 }
169
Scott Michel394e26d2008-01-17 20:38:41 +0000170 // Custom lower BRCOND for i1, i8 to "promote" the result to
171 // i32 and i16, respectively.
172 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000173
174 // Expand the jumptable branches
175 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
176 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000177 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000178
179 // SPU has no intrinsics for these particular operations:
Andrew Lenharth0531ec52008-02-16 14:46:26 +0000180 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
181
Scott Michel8efdca42007-12-04 22:23:35 +0000182 // PowerPC has no SREM/UREM instructions
183 setOperationAction(ISD::SREM, MVT::i32, Expand);
184 setOperationAction(ISD::UREM, MVT::i32, Expand);
185 setOperationAction(ISD::SREM, MVT::i64, Expand);
186 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000187
Scott Michel8efdca42007-12-04 22:23:35 +0000188 // We don't support sin/cos/sqrt/fmod
189 setOperationAction(ISD::FSIN , MVT::f64, Expand);
190 setOperationAction(ISD::FCOS , MVT::f64, Expand);
191 setOperationAction(ISD::FREM , MVT::f64, Expand);
192 setOperationAction(ISD::FSIN , MVT::f32, Expand);
193 setOperationAction(ISD::FCOS , MVT::f32, Expand);
194 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000195
Scott Michel8efdca42007-12-04 22:23:35 +0000196 // If we're enabling GP optimizations, use hardware square root
197 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
198 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000199
Scott Michel8efdca42007-12-04 22:23:35 +0000200 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
201 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
202
203 // SPU can do rotate right and left, so legalize it... but customize for i8
204 // because instructions don't exist.
Bill Wendling965299c2008-08-31 02:59:23 +0000205
206 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
207 // .td files.
208 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
209 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
210 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
211
Scott Michel8efdca42007-12-04 22:23:35 +0000212 setOperationAction(ISD::ROTL, MVT::i32, Legal);
213 setOperationAction(ISD::ROTL, MVT::i16, Legal);
214 setOperationAction(ISD::ROTL, MVT::i8, Custom);
215 // SPU has no native version of shift left/right for i8
216 setOperationAction(ISD::SHL, MVT::i8, Custom);
217 setOperationAction(ISD::SRL, MVT::i8, Custom);
218 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel97872d32008-02-23 18:41:37 +0000219 // And SPU needs custom lowering for shift left/right for i64
220 setOperationAction(ISD::SHL, MVT::i64, Custom);
221 setOperationAction(ISD::SRL, MVT::i64, Custom);
222 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000223
Scott Michel4ec722e2008-07-16 17:17:29 +0000224 // Custom lower i8, i32 and i64 multiplications
225 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000226 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000227 setOperationAction(ISD::MUL, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000228
Scott Michel67224b22008-06-02 22:18:03 +0000229 // Need to custom handle (some) common i8, i64 math ops
230 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000231 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000232 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000233
Scott Michel8efdca42007-12-04 22:23:35 +0000234 // SPU does not have BSWAP. It does have i32 support CTLZ.
235 // CTPOP has to be custom lowered.
236 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
237 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
238
239 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
240 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
241 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
242 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
243
244 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
245 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
246
247 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000248
Scott Michel67224b22008-06-02 22:18:03 +0000249 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel978b96f2008-03-10 23:49:09 +0000250 // select ought to work:
Scott Michel53ab7792008-03-10 16:58:52 +0000251 setOperationAction(ISD::SELECT, MVT::i1, Promote);
252 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000253 setOperationAction(ISD::SELECT, MVT::i16, Legal);
254 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000255 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000256
Scott Michel53ab7792008-03-10 16:58:52 +0000257 setOperationAction(ISD::SETCC, MVT::i1, Promote);
258 setOperationAction(ISD::SETCC, MVT::i8, Legal);
259 setOperationAction(ISD::SETCC, MVT::i16, Legal);
260 setOperationAction(ISD::SETCC, MVT::i32, Legal);
261 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michel6baba072008-03-05 23:02:02 +0000262
Scott Michel97872d32008-02-23 18:41:37 +0000263 // Zero extension and sign extension for i64 have to be
264 // custom legalized
265 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
266 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
267 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000268
Scott Michel8efdca42007-12-04 22:23:35 +0000269 // SPU has a legal FP -> signed INT instruction
270 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
271 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
272 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
273 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
274
275 // FDIV on SPU requires custom lowering
276 setOperationAction(ISD::FDIV, MVT::f32, Custom);
277 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
278
279 // SPU has [U|S]INT_TO_FP
280 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
281 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
282 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
283 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
284 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
285 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
286 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
287 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
288
Scott Michel754d8662007-12-20 00:44:13 +0000289 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
290 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
291 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
292 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000293
294 // We cannot sextinreg(i1). Expand to shifts.
295 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000296
Scott Michel8efdca42007-12-04 22:23:35 +0000297 // Support label based line numbers.
Dan Gohman472d12c2008-06-30 20:59:49 +0000298 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000299 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000300
301 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel8efdca42007-12-04 22:23:35 +0000302 // appropriate instructions to materialize the address.
Scott Michelf9f42e62008-01-29 02:16:57 +0000303 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
304 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000305 MVT VT = (MVT::SimpleValueType)sctype;
306
307 setOperationAction(ISD::GlobalAddress, VT, Custom);
308 setOperationAction(ISD::ConstantPool, VT, Custom);
309 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michelf9f42e62008-01-29 02:16:57 +0000310 }
Scott Michel8efdca42007-12-04 22:23:35 +0000311
312 // RET must be custom lowered, to meet ABI requirements
313 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000314
Scott Michel8efdca42007-12-04 22:23:35 +0000315 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
316 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000317
Scott Michel8efdca42007-12-04 22:23:35 +0000318 // Use the default implementation.
319 setOperationAction(ISD::VAARG , MVT::Other, Expand);
320 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
321 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000322 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000323 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
324 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
325 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
326
327 // Cell SPU has instructions for converting between i64 and fp.
328 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
329 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000330
Scott Michel8efdca42007-12-04 22:23:35 +0000331 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
332 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
333
334 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
335 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
336
337 // First set operation action for all vector types to expand. Then we
338 // will selectively turn on ones that can be effectively codegen'd.
339 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
340 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
341 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
342 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
343 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
344 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
345
Duncan Sands92c43912008-06-06 12:08:01 +0000346 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
347 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
348 MVT VT = (MVT::SimpleValueType)i;
Scott Michel8efdca42007-12-04 22:23:35 +0000349
Duncan Sands92c43912008-06-06 12:08:01 +0000350 // add/sub are legal for all supported vector VT's.
351 setOperationAction(ISD::ADD , VT, Legal);
352 setOperationAction(ISD::SUB , VT, Legal);
353 // mul has to be custom lowered.
354 setOperationAction(ISD::MUL , VT, Custom);
355
356 setOperationAction(ISD::AND , VT, Legal);
357 setOperationAction(ISD::OR , VT, Legal);
358 setOperationAction(ISD::XOR , VT, Legal);
359 setOperationAction(ISD::LOAD , VT, Legal);
360 setOperationAction(ISD::SELECT, VT, Legal);
361 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000362
Scott Michel8efdca42007-12-04 22:23:35 +0000363 // These operations need to be expanded:
Duncan Sands92c43912008-06-06 12:08:01 +0000364 setOperationAction(ISD::SDIV, VT, Expand);
365 setOperationAction(ISD::SREM, VT, Expand);
366 setOperationAction(ISD::UDIV, VT, Expand);
367 setOperationAction(ISD::UREM, VT, Expand);
368 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000369
370 // Custom lower build_vector, constant pool spills, insert and
371 // extract vector elements:
Duncan Sands92c43912008-06-06 12:08:01 +0000372 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
373 setOperationAction(ISD::ConstantPool, VT, Custom);
374 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
375 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
376 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
377 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000378 }
379
380 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
381 setOperationAction(ISD::AND, MVT::v16i8, Custom);
382 setOperationAction(ISD::OR, MVT::v16i8, Custom);
383 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
384 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000385
Scott Michel8efdca42007-12-04 22:23:35 +0000386 setShiftAmountType(MVT::i32);
387 setSetCCResultContents(ZeroOrOneSetCCResult);
Scott Michel4ec722e2008-07-16 17:17:29 +0000388
Scott Michel8efdca42007-12-04 22:23:35 +0000389 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel4ec722e2008-07-16 17:17:29 +0000390
Scott Michel8efdca42007-12-04 22:23:35 +0000391 // We have target-specific dag combine patterns for the following nodes:
Scott Michelf9f42e62008-01-29 02:16:57 +0000392 setTargetDAGCombine(ISD::ADD);
Scott Michel97872d32008-02-23 18:41:37 +0000393 setTargetDAGCombine(ISD::ZERO_EXTEND);
394 setTargetDAGCombine(ISD::SIGN_EXTEND);
395 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel4ec722e2008-07-16 17:17:29 +0000396
Scott Michel8efdca42007-12-04 22:23:35 +0000397 computeRegisterProperties();
398}
399
400const char *
401SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
402{
403 if (node_names.empty()) {
404 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
405 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
406 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
407 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Micheldbac4cf2008-01-11 02:53:15 +0000408 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michelf9f42e62008-01-29 02:16:57 +0000409 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel8efdca42007-12-04 22:23:35 +0000410 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
411 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
412 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
413 node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
414 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
415 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
416 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
Gabor Greife9f7f582008-08-31 15:37:04 +0000417 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED]
418 = "SPUISD::EXTRACT_ELT0_CHAINED";
Scott Michel8efdca42007-12-04 22:23:35 +0000419 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
420 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
421 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
422 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
423 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
424 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
425 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
426 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michel97872d32008-02-23 18:41:37 +0000427 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
428 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel8efdca42007-12-04 22:23:35 +0000429 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
430 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
431 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
432 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
433 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michel97872d32008-02-23 18:41:37 +0000434 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
435 "SPUISD::ROTQUAD_RZ_BYTES";
436 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
437 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel8efdca42007-12-04 22:23:35 +0000438 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
439 "SPUISD::ROTBYTES_RIGHT_S";
440 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
441 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
442 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel67224b22008-06-02 22:18:03 +0000443 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
444 "SPUISD::ROTBYTES_LEFT_BITS";
445 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000446 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel67224b22008-06-02 22:18:03 +0000447 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
448 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
449 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
450 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel8efdca42007-12-04 22:23:35 +0000451 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
452 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
453 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
454 }
455
456 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
457
458 return ((i != node_names.end()) ? i->second : 0);
459}
460
Dan Gohman8181bd12008-07-27 21:46:04 +0000461MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands92c43912008-06-06 12:08:01 +0000462 MVT VT = Op.getValueType();
463 if (VT.isInteger())
Scott Michel978b96f2008-03-10 23:49:09 +0000464 return VT;
465 else
466 return MVT::i32;
Scott Michel53ab7792008-03-10 16:58:52 +0000467}
468
Scott Michel8efdca42007-12-04 22:23:35 +0000469//===----------------------------------------------------------------------===//
470// Calling convention code:
471//===----------------------------------------------------------------------===//
472
473#include "SPUGenCallingConv.inc"
474
475//===----------------------------------------------------------------------===//
476// LowerOperation implementation
477//===----------------------------------------------------------------------===//
478
Scott Micheldbac4cf2008-01-11 02:53:15 +0000479/// Aligned load common code for CellSPU
480/*!
481 \param[in] Op The SelectionDAG load or store operand
482 \param[in] DAG The selection DAG
483 \param[in] ST CellSPU subtarget information structure
484 \param[in,out] alignment Caller initializes this to the load or store node's
485 value from getAlignment(), may be updated while generating the aligned load
486 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
487 offset (divisible by 16, modulo 16 == 0)
488 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
489 offset of the preferred slot (modulo 16 != 0)
490 \param[in,out] VT Caller initializes this value type to the the load or store
491 node's loaded or stored value type; may be updated if an i1-extended load or
492 store.
493 \param[out] was16aligned true if the base pointer had 16-byte alignment,
494 otherwise false. Can help to determine if the chunk needs to be rotated.
495
496 Both load and store lowering load a block of data aligned on a 16-byte
497 boundary. This is the common aligned load code shared between both.
498 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000499static SDValue
500AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Micheldbac4cf2008-01-11 02:53:15 +0000501 LSBaseSDNode *LSN,
502 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands92c43912008-06-06 12:08:01 +0000503 MVT &VT, bool &was16aligned)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000504{
Duncan Sands92c43912008-06-06 12:08:01 +0000505 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000506 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman8181bd12008-07-27 21:46:04 +0000507 SDValue basePtr = LSN->getBasePtr();
508 SDValue chain = LSN->getChain();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000509
510 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greif1c80d112008-08-28 21:40:38 +0000511 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000512
Gabor Greife9f7f582008-08-31 15:37:04 +0000513 if (Op1.getOpcode() == ISD::Constant
514 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel394e26d2008-01-17 20:38:41 +0000515 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000516
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000517 alignOffs = (int) CN->getZExtValue();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000518 prefSlotOffs = (int) (alignOffs & 0xf);
519
520 // Adjust the rotation amount to ensure that the final result ends up in
521 // the preferred slot:
522 prefSlotOffs -= vtm->prefslot_byte;
523 basePtr = basePtr.getOperand(0);
524
Scott Michel394e26d2008-01-17 20:38:41 +0000525 // Loading from memory, can we adjust alignment?
526 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000527 SDValue APtr = basePtr.getOperand(0);
Scott Michel394e26d2008-01-17 20:38:41 +0000528 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
529 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
530 alignment = GSDN->getGlobal()->getAlignment();
531 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000532 }
533 } else {
534 alignOffs = 0;
535 prefSlotOffs = -vtm->prefslot_byte;
536 }
Scott Michelbc5fbc12008-04-30 00:30:08 +0000537 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
538 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
539 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
540 prefSlotOffs = (int) (alignOffs & 0xf);
541 prefSlotOffs -= vtm->prefslot_byte;
542 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000543 } else {
544 alignOffs = 0;
545 prefSlotOffs = -vtm->prefslot_byte;
546 }
547
548 if (alignment == 16) {
549 // Realign the base pointer as a D-Form address:
550 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel394e26d2008-01-17 20:38:41 +0000551 basePtr = DAG.getNode(ISD::ADD, PtrVT,
552 basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000553 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000554 }
555
556 // Emit the vector load:
557 was16aligned = true;
558 return DAG.getLoad(MVT::v16i8, chain, basePtr,
559 LSN->getSrcValue(), LSN->getSrcValueOffset(),
560 LSN->isVolatile(), 16);
561 }
562
563 // Unaligned load or we're using the "large memory" model, which means that
564 // we have to be very pessimistic:
Scott Michel394e26d2008-01-17 20:38:41 +0000565 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greife9f7f582008-08-31 15:37:04 +0000566 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
567 DAG.getConstant(0, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000568 }
569
570 // Add the offset
Scott Michelf9f42e62008-01-29 02:16:57 +0000571 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000572 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000573 was16aligned = false;
574 return DAG.getLoad(MVT::v16i8, chain, basePtr,
575 LSN->getSrcValue(), LSN->getSrcValueOffset(),
576 LSN->isVolatile(), 16);
577}
578
Scott Michel8efdca42007-12-04 22:23:35 +0000579/// Custom lower loads for CellSPU
580/*!
581 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
582 within a 16-byte block, we have to rotate to extract the requested element.
583 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000584static SDValue
585LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000586 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000587 SDValue the_chain = LN->getChain();
Duncan Sands92c43912008-06-06 12:08:01 +0000588 MVT VT = LN->getMemoryVT();
Gabor Greif1c80d112008-08-28 21:40:38 +0000589 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000590 ISD::LoadExtType ExtType = LN->getExtensionType();
591 unsigned alignment = LN->getAlignment();
Dan Gohman8181bd12008-07-27 21:46:04 +0000592 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +0000593
Scott Michel8efdca42007-12-04 22:23:35 +0000594 switch (LN->getAddressingMode()) {
595 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000596 int offset, rotamt;
597 bool was16aligned;
Dan Gohman8181bd12008-07-27 21:46:04 +0000598 SDValue result =
Scott Micheldbac4cf2008-01-11 02:53:15 +0000599 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000600
Gabor Greif1c80d112008-08-28 21:40:38 +0000601 if (result.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +0000602 return result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000603
604 the_chain = result.getValue(1);
605 // Rotate the chunk if necessary
606 if (rotamt < 0)
607 rotamt += 16;
Scott Michelabc58242008-01-11 21:01:19 +0000608 if (rotamt != 0 || !was16aligned) {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000609 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
610
Scott Michel394e26d2008-01-17 20:38:41 +0000611 Ops[0] = the_chain;
612 Ops[1] = result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000613 if (was16aligned) {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000614 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
615 } else {
Duncan Sands92c43912008-06-06 12:08:01 +0000616 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000617 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michelabc58242008-01-11 21:01:19 +0000618 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel5a6f17b2008-01-30 02:55:46 +0000619 DAG.getConstant(rotamt, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000620 }
621
622 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
623 the_chain = result.getValue(1);
Scott Michel8efdca42007-12-04 22:23:35 +0000624 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000625
626 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
627 SDVTList scalarvts;
Duncan Sands92c43912008-06-06 12:08:01 +0000628 MVT vecVT = MVT::v16i8;
Scott Michel4ec722e2008-07-16 17:17:29 +0000629
Scott Micheldbac4cf2008-01-11 02:53:15 +0000630 // Convert the loaded v16i8 vector to the appropriate vector type
631 // specified by the operand:
632 if (OpVT == VT) {
633 if (VT != MVT::i1)
Duncan Sands92c43912008-06-06 12:08:01 +0000634 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000635 } else
Duncan Sands92c43912008-06-06 12:08:01 +0000636 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000637
638 Ops[0] = the_chain;
639 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
640 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
641 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
642 the_chain = result.getValue(1);
643 } else {
644 // Handle the sign and zero-extending loads for i1 and i8:
645 unsigned NewOpC;
646
647 if (ExtType == ISD::SEXTLOAD) {
648 NewOpC = (OpVT == MVT::i1
649 ? SPUISD::EXTRACT_I1_SEXT
650 : SPUISD::EXTRACT_I8_SEXT);
651 } else {
652 assert(ExtType == ISD::ZEXTLOAD);
653 NewOpC = (OpVT == MVT::i1
654 ? SPUISD::EXTRACT_I1_ZEXT
655 : SPUISD::EXTRACT_I8_ZEXT);
656 }
657
658 result = DAG.getNode(NewOpC, OpVT, result);
659 }
660
661 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman8181bd12008-07-27 21:46:04 +0000662 SDValue retops[2] = {
Scott Michel394e26d2008-01-17 20:38:41 +0000663 result,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000664 the_chain
Scott Michel394e26d2008-01-17 20:38:41 +0000665 };
Scott Micheldbac4cf2008-01-11 02:53:15 +0000666
Scott Michel394e26d2008-01-17 20:38:41 +0000667 result = DAG.getNode(SPUISD::LDRESULT, retvts,
668 retops, sizeof(retops) / sizeof(retops[0]));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000669 return result;
Scott Michel8efdca42007-12-04 22:23:35 +0000670 }
671 case ISD::PRE_INC:
672 case ISD::PRE_DEC:
673 case ISD::POST_INC:
674 case ISD::POST_DEC:
675 case ISD::LAST_INDEXED_MODE:
676 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
677 "UNINDEXED\n";
678 cerr << (unsigned) LN->getAddressingMode() << "\n";
679 abort();
680 /*NOTREACHED*/
681 }
682
Dan Gohman8181bd12008-07-27 21:46:04 +0000683 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000684}
685
686/// Custom lower stores for CellSPU
687/*!
688 All CellSPU stores are aligned to 16-byte boundaries, so for elements
689 within a 16-byte block, we have to generate a shuffle to insert the
690 requested element into its place, then store the resulting block.
691 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000692static SDValue
693LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000694 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000695 SDValue Value = SN->getValue();
Duncan Sands92c43912008-06-06 12:08:01 +0000696 MVT VT = Value.getValueType();
697 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
698 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000699 unsigned alignment = SN->getAlignment();
Scott Michel8efdca42007-12-04 22:23:35 +0000700
701 switch (SN->getAddressingMode()) {
702 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000703 int chunk_offset, slot_offset;
704 bool was16aligned;
Scott Michel8efdca42007-12-04 22:23:35 +0000705
706 // The vector type we really want to load from the 16-byte chunk, except
707 // in the case of MVT::i1, which has to be v16i8.
Duncan Sands92c43912008-06-06 12:08:01 +0000708 MVT vecVT, stVecVT = MVT::v16i8;
Scott Michel4ec722e2008-07-16 17:17:29 +0000709
Scott Michel8efdca42007-12-04 22:23:35 +0000710 if (StVT != MVT::i1)
Duncan Sands92c43912008-06-06 12:08:01 +0000711 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
712 vecVT = MVT::getVectorVT(VT, (128 / VT.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;
739 SDValue insertEltOp;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000740
741 // If the base pointer is already a D-form address, then just create
742 // a new D-form address with a slot offset and the orignal base pointer.
743 // Otherwise generate a D-form address with the slot offset relative
744 // to the stack pointer, which is always aligned.
Scott Michelabc58242008-01-11 21:01:19 +0000745 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greif1c80d112008-08-28 21:40:38 +0000746 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michelabc58242008-01-11 21:01:19 +0000747 DEBUG(cerr << "\n");
748
Scott Michelf9f42e62008-01-29 02:16:57 +0000749 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
750 (basePtr.getOpcode() == ISD::ADD
751 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michelabc58242008-01-11 21:01:19 +0000752 insertEltPtr = basePtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000753 } else {
Scott Michelf9f42e62008-01-29 02:16:57 +0000754 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000755 }
756
757 insertEltOp = DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michel8efdca42007-12-04 22:23:35 +0000758 result = DAG.getNode(SPUISD::SHUFB, vecVT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000759 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue),
760 alignLoadVec,
761 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel8efdca42007-12-04 22:23:35 +0000762
Scott Micheldbac4cf2008-01-11 02:53:15 +0000763 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel8efdca42007-12-04 22:23:35 +0000764 LN->getSrcValue(), LN->getSrcValueOffset(),
765 LN->isVolatile(), LN->getAlignment());
766
767 return result;
768 /*UNREACHED*/
769 }
770 case ISD::PRE_INC:
771 case ISD::PRE_DEC:
772 case ISD::POST_INC:
773 case ISD::POST_DEC:
774 case ISD::LAST_INDEXED_MODE:
775 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
776 "UNINDEXED\n";
777 cerr << (unsigned) SN->getAddressingMode() << "\n";
778 abort();
779 /*NOTREACHED*/
780 }
781
Dan Gohman8181bd12008-07-27 21:46:04 +0000782 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000783}
784
785/// Generate the address of a constant pool entry.
Dan Gohman8181bd12008-07-27 21:46:04 +0000786static SDValue
787LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000788 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000789 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
790 Constant *C = CP->getConstVal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000791 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
792 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000793 const TargetMachine &TM = DAG.getTarget();
Scott Michel8efdca42007-12-04 22:23:35 +0000794
795 if (TM.getRelocationModel() == Reloc::Static) {
796 if (!ST->usingLargeMem()) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000797 // Just return the SDValue with the constant pool address in it.
Scott Michel394e26d2008-01-17 20:38:41 +0000798 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +0000799 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000800 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
801 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000802 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel8efdca42007-12-04 22:23:35 +0000803 }
804 }
805
806 assert(0 &&
Gabor Greife9f7f582008-08-31 15:37:04 +0000807 "LowerConstantPool: Relocation model other than static"
808 " not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000809 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000810}
811
Dan Gohman8181bd12008-07-27 21:46:04 +0000812static SDValue
813LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000814 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000815 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000816 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
817 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000818 const TargetMachine &TM = DAG.getTarget();
819
820 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel97872d32008-02-23 18:41:37 +0000821 if (!ST->usingLargeMem()) {
822 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
823 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000824 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
825 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000826 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
827 }
Scott Michel8efdca42007-12-04 22:23:35 +0000828 }
829
830 assert(0 &&
831 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000832 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000833}
834
Dan Gohman8181bd12008-07-27 21:46:04 +0000835static SDValue
836LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000837 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000838 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
839 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000840 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel8efdca42007-12-04 22:23:35 +0000841 const TargetMachine &TM = DAG.getTarget();
Dan Gohman8181bd12008-07-27 21:46:04 +0000842 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel4ec722e2008-07-16 17:17:29 +0000843
Scott Michel8efdca42007-12-04 22:23:35 +0000844 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michelf9f42e62008-01-29 02:16:57 +0000845 if (!ST->usingLargeMem()) {
846 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
847 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000848 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
849 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michelf9f42e62008-01-29 02:16:57 +0000850 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
851 }
Scott Michel8efdca42007-12-04 22:23:35 +0000852 } else {
853 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel5a6f17b2008-01-30 02:55:46 +0000854 << "supported.\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000855 abort();
856 /*NOTREACHED*/
857 }
858
Dan Gohman8181bd12008-07-27 21:46:04 +0000859 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000860}
861
862//! Custom lower i64 integer constants
863/*!
864 This code inserts all of the necessary juggling that needs to occur to load
865 a 64-bit constant into a register.
866 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000867static SDValue
868LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000869 MVT VT = Op.getValueType();
Gabor Greif1c80d112008-08-28 21:40:38 +0000870 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel8efdca42007-12-04 22:23:35 +0000871
872 if (VT == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000873 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +0000874 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000875 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +0000876 } else {
877 cerr << "LowerConstant: unhandled constant type "
Duncan Sands92c43912008-06-06 12:08:01 +0000878 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +0000879 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000880 abort();
881 /*NOTREACHED*/
882 }
883
Dan Gohman8181bd12008-07-27 21:46:04 +0000884 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000885}
886
Nate Begeman78125042008-02-14 18:43:04 +0000887//! Custom lower double precision floating point constants
Dan Gohman8181bd12008-07-27 21:46:04 +0000888static SDValue
889LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000890 MVT VT = Op.getValueType();
Gabor Greif1c80d112008-08-28 21:40:38 +0000891 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel8efdca42007-12-04 22:23:35 +0000892
893 assert((FP != 0) &&
Scott Michel5a6f17b2008-01-30 02:55:46 +0000894 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel8efdca42007-12-04 22:23:35 +0000895
Nate Begeman78125042008-02-14 18:43:04 +0000896 if (VT == MVT::f64) {
Scott Michel11e88bb2007-12-19 20:15:47 +0000897 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel8efdca42007-12-04 22:23:35 +0000898 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000899 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel8efdca42007-12-04 22:23:35 +0000900 }
901
Dan Gohman8181bd12008-07-27 21:46:04 +0000902 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000903}
904
Scott Michel394e26d2008-01-17 20:38:41 +0000905//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman8181bd12008-07-27 21:46:04 +0000906static SDValue
907LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel394e26d2008-01-17 20:38:41 +0000908{
Dan Gohman8181bd12008-07-27 21:46:04 +0000909 SDValue Cond = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +0000910 MVT CondVT = Cond.getValueType();
911 MVT CondNVT;
Scott Michel394e26d2008-01-17 20:38:41 +0000912
913 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
914 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
915 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
916 Op.getOperand(0),
917 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
918 Op.getOperand(2));
919 } else
Dan Gohman8181bd12008-07-27 21:46:04 +0000920 return SDValue(); // Unchanged
Scott Michel394e26d2008-01-17 20:38:41 +0000921}
922
Dan Gohman8181bd12008-07-27 21:46:04 +0000923static SDValue
924LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel8efdca42007-12-04 22:23:35 +0000925{
926 MachineFunction &MF = DAG.getMachineFunction();
927 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner1b989192007-12-31 04:13:23 +0000928 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman8181bd12008-07-27 21:46:04 +0000929 SmallVector<SDValue, 8> ArgValues;
930 SDValue Root = Op.getOperand(0);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000931 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel8efdca42007-12-04 22:23:35 +0000932
933 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
934 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel4ec722e2008-07-16 17:17:29 +0000935
Scott Michel8efdca42007-12-04 22:23:35 +0000936 unsigned ArgOffset = SPUFrameInfo::minStackSize();
937 unsigned ArgRegIdx = 0;
938 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel4ec722e2008-07-16 17:17:29 +0000939
Duncan Sands92c43912008-06-06 12:08:01 +0000940 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +0000941
Scott Michel8efdca42007-12-04 22:23:35 +0000942 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greife9f7f582008-08-31 15:37:04 +0000943 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
944 ArgNo != e; ++ArgNo) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000945 SDValue ArgVal;
Scott Michel8efdca42007-12-04 22:23:35 +0000946 bool needsLoad = false;
Duncan Sands92c43912008-06-06 12:08:01 +0000947 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
948 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michel8efdca42007-12-04 22:23:35 +0000949
Duncan Sands92c43912008-06-06 12:08:01 +0000950 switch (ObjectVT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +0000951 default: {
952 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
Duncan Sands92c43912008-06-06 12:08:01 +0000953 << ObjectVT.getMVTString()
Scott Michel8efdca42007-12-04 22:23:35 +0000954 << "\n";
955 abort();
956 }
957 case MVT::i8:
958 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner1b989192007-12-31 04:13:23 +0000959 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R8CRegClass);
960 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel8efdca42007-12-04 22:23:35 +0000961 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i8);
962 ++ArgRegIdx;
963 } else {
964 needsLoad = true;
965 }
966 break;
967 case MVT::i16:
968 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner1b989192007-12-31 04:13:23 +0000969 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
970 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel8efdca42007-12-04 22:23:35 +0000971 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i16);
972 ++ArgRegIdx;
973 } else {
974 needsLoad = true;
975 }
976 break;
977 case MVT::i32:
978 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner1b989192007-12-31 04:13:23 +0000979 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
980 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel8efdca42007-12-04 22:23:35 +0000981 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
982 ++ArgRegIdx;
983 } else {
984 needsLoad = true;
985 }
986 break;
987 case MVT::i64:
988 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner1b989192007-12-31 04:13:23 +0000989 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64CRegClass);
990 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel8efdca42007-12-04 22:23:35 +0000991 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64);
992 ++ArgRegIdx;
993 } else {
994 needsLoad = true;
995 }
996 break;
997 case MVT::f32:
998 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner1b989192007-12-31 04:13:23 +0000999 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
1000 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel8efdca42007-12-04 22:23:35 +00001001 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f32);
1002 ++ArgRegIdx;
1003 } else {
1004 needsLoad = true;
1005 }
1006 break;
1007 case MVT::f64:
1008 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner1b989192007-12-31 04:13:23 +00001009 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64FPRegClass);
1010 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel8efdca42007-12-04 22:23:35 +00001011 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f64);
1012 ++ArgRegIdx;
1013 } else {
1014 needsLoad = true;
1015 }
1016 break;
1017 case MVT::v2f64:
1018 case MVT::v4f32:
Scott Michel6baba072008-03-05 23:02:02 +00001019 case MVT::v2i64:
Scott Michel8efdca42007-12-04 22:23:35 +00001020 case MVT::v4i32:
1021 case MVT::v8i16:
1022 case MVT::v16i8:
1023 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner1b989192007-12-31 04:13:23 +00001024 unsigned VReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1025 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel8efdca42007-12-04 22:23:35 +00001026 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1027 ++ArgRegIdx;
1028 } else {
1029 needsLoad = true;
1030 }
1031 break;
1032 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001033
Scott Michel8efdca42007-12-04 22:23:35 +00001034 // We need to load the argument to a virtual register if we determined above
1035 // that we ran out of physical registers of the appropriate type
1036 if (needsLoad) {
Chris Lattner60069452008-02-13 07:35:30 +00001037 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +00001038 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner60069452008-02-13 07:35:30 +00001039 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +00001040 ArgOffset += StackSlotSize;
1041 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001042
Scott Michel8efdca42007-12-04 22:23:35 +00001043 ArgValues.push_back(ArgVal);
1044 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001045
Scott Michel8efdca42007-12-04 22:23:35 +00001046 // If the function takes variable number of arguments, make a frame index for
1047 // the start of the first vararg value... for expansion of llvm.va_start.
1048 if (isVarArg) {
Duncan Sands92c43912008-06-06 12:08:01 +00001049 VarArgsFrameIndex = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8,
Scott Michel8efdca42007-12-04 22:23:35 +00001050 ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +00001051 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001052 // If this function is vararg, store any remaining integer argument regs to
1053 // their spots on the stack so that they may be loaded by deferencing the
1054 // result of va_next.
Dan Gohman8181bd12008-07-27 21:46:04 +00001055 SmallVector<SDValue, 8> MemOps;
Scott Michel8efdca42007-12-04 22:23:35 +00001056 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Chris Lattner1b989192007-12-31 04:13:23 +00001057 unsigned VReg = RegInfo.createVirtualRegister(&SPU::GPRCRegClass);
1058 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Dan Gohman8181bd12008-07-27 21:46:04 +00001059 SDValue Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
1060 SDValue Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +00001061 MemOps.push_back(Store);
1062 // Increment the address by four for the next argument to store
Dan Gohman8181bd12008-07-27 21:46:04 +00001063 SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001064 FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
1065 }
1066 if (!MemOps.empty())
1067 Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
1068 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001069
Scott Michel8efdca42007-12-04 22:23:35 +00001070 ArgValues.push_back(Root);
Scott Michel4ec722e2008-07-16 17:17:29 +00001071
Scott Michel8efdca42007-12-04 22:23:35 +00001072 // Return the new list of results.
Gabor Greif1c80d112008-08-28 21:40:38 +00001073 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf19591c2008-06-30 10:19:09 +00001074 ArgValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001075}
1076
1077/// isLSAAddress - Return the immediate to use if the specified
1078/// value is representable as a LSA address.
Dan Gohman8181bd12008-07-27 21:46:04 +00001079static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001080 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
1081 if (!C) return 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001082
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001083 int Addr = C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001084 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1085 (Addr << 14 >> 14) != Addr)
1086 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel4ec722e2008-07-16 17:17:29 +00001087
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001088 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel8efdca42007-12-04 22:23:35 +00001089}
1090
1091static
Dan Gohman8181bd12008-07-27 21:46:04 +00001092SDValue
1093LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001094 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1095 SDValue Chain = TheCall->getChain();
Scott Michel8efdca42007-12-04 22:23:35 +00001096#if 0
Dan Gohman705e3f72008-09-13 01:54:27 +00001097 bool isVarArg = TheCall->isVarArg();
1098 bool isTailCall = TheCall->isTailCall();
Scott Michel8efdca42007-12-04 22:23:35 +00001099#endif
Dan Gohman705e3f72008-09-13 01:54:27 +00001100 SDValue Callee = TheCall->getCallee();
1101 unsigned NumOps = TheCall->getNumArgs();
Scott Michel8efdca42007-12-04 22:23:35 +00001102 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1103 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1104 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1105
1106 // Handy pointer type
Duncan Sands92c43912008-06-06 12:08:01 +00001107 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +00001108
Scott Michel8efdca42007-12-04 22:23:35 +00001109 // Accumulate how many bytes are to be pushed on the stack, including the
1110 // linkage area, and parameter passing area. According to the SPU ABI,
1111 // we minimally need space for [LR] and [SP]
1112 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel4ec722e2008-07-16 17:17:29 +00001113
Scott Michel8efdca42007-12-04 22:23:35 +00001114 // Set up a copy of the stack pointer for use loading and storing any
1115 // arguments that may not fit in the registers available for argument
1116 // passing.
Dan Gohman8181bd12008-07-27 21:46:04 +00001117 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel4ec722e2008-07-16 17:17:29 +00001118
Scott Michel8efdca42007-12-04 22:23:35 +00001119 // Figure out which arguments are going to go in registers, and which in
1120 // memory.
1121 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1122 unsigned ArgRegIdx = 0;
1123
1124 // Keep track of registers passing arguments
Dan Gohman8181bd12008-07-27 21:46:04 +00001125 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel8efdca42007-12-04 22:23:35 +00001126 // And the arguments passed on the stack
Dan Gohman8181bd12008-07-27 21:46:04 +00001127 SmallVector<SDValue, 8> MemOpChains;
Scott Michel8efdca42007-12-04 22:23:35 +00001128
1129 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001130 SDValue Arg = TheCall->getArg(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001131
Scott Michel8efdca42007-12-04 22:23:35 +00001132 // PtrOff will be used to store the current argument to the stack if a
1133 // register cannot be found for it.
Dan Gohman8181bd12008-07-27 21:46:04 +00001134 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel8efdca42007-12-04 22:23:35 +00001135 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1136
Duncan Sands92c43912008-06-06 12:08:01 +00001137 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001138 default: assert(0 && "Unexpected ValueType for argument!");
1139 case MVT::i32:
1140 case MVT::i64:
1141 case MVT::i128:
1142 if (ArgRegIdx != NumArgRegs) {
1143 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1144 } else {
1145 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001146 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001147 }
1148 break;
1149 case MVT::f32:
1150 case MVT::f64:
1151 if (ArgRegIdx != NumArgRegs) {
1152 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1153 } else {
1154 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001155 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001156 }
1157 break;
1158 case MVT::v4f32:
1159 case MVT::v4i32:
1160 case MVT::v8i16:
1161 case MVT::v16i8:
1162 if (ArgRegIdx != NumArgRegs) {
1163 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1164 } else {
1165 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001166 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001167 }
1168 break;
1169 }
1170 }
1171
1172 // Update number of stack bytes actually used, insert a call sequence start
1173 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001174 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1175 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001176
1177 if (!MemOpChains.empty()) {
1178 // Adjust the stack pointer for the stack arguments.
1179 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1180 &MemOpChains[0], MemOpChains.size());
1181 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001182
Scott Michel8efdca42007-12-04 22:23:35 +00001183 // Build a sequence of copy-to-reg nodes chained together with token chain
1184 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001185 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001186 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1187 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1188 InFlag);
1189 InFlag = Chain.getValue(1);
1190 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001191
Dan Gohman8181bd12008-07-27 21:46:04 +00001192 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001193 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001194
Bill Wendlingfef06052008-09-16 21:48:12 +00001195 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1196 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1197 // node so that legalize doesn't hack it.
Scott Michel8efdca42007-12-04 22:23:35 +00001198 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1199 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001200 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001201 SDValue Zero = DAG.getConstant(0, PtrVT);
1202 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001203
Scott Micheldbac4cf2008-01-11 02:53:15 +00001204 if (!ST->usingLargeMem()) {
1205 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1206 // style calls, otherwise, external symbols are BRASL calls. This assumes
1207 // that declared/defined symbols are in the same compilation unit and can
1208 // be reached through PC-relative jumps.
1209 //
1210 // NOTE:
1211 // This may be an unsafe assumption for JIT and really large compilation
1212 // units.
1213 if (GV->isDeclaration()) {
1214 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1215 } else {
1216 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1217 }
Scott Michel8efdca42007-12-04 22:23:35 +00001218 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001219 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1220 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001221 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001222 }
Bill Wendlingfef06052008-09-16 21:48:12 +00001223 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
1224 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Micheldbac4cf2008-01-11 02:53:15 +00001225 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001226 // If this is an absolute destination address that appears to be a legal
1227 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001228 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001229 }
Scott Michel8efdca42007-12-04 22:23:35 +00001230
1231 Ops.push_back(Chain);
1232 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001233
Scott Michel8efdca42007-12-04 22:23:35 +00001234 // Add argument registers to the end of the list so that they are known live
1235 // into the call.
1236 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001237 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001238 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001239
Gabor Greif1c80d112008-08-28 21:40:38 +00001240 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001241 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001242 // Returns a chain and a flag for retval copy to use.
1243 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1244 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001245 InFlag = Chain.getValue(1);
1246
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001247 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1248 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001249 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001250 InFlag = Chain.getValue(1);
1251
Dan Gohman8181bd12008-07-27 21:46:04 +00001252 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001253 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001254
Scott Michel8efdca42007-12-04 22:23:35 +00001255 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001256 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001257 default: assert(0 && "Unexpected ret value!");
1258 case MVT::Other: break;
1259 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001260 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001261 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1262 ResultVals[0] = Chain.getValue(0);
1263 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1264 Chain.getValue(2)).getValue(1);
1265 ResultVals[1] = Chain.getValue(0);
1266 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001267 } else {
1268 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1269 ResultVals[0] = Chain.getValue(0);
1270 NumResults = 1;
1271 }
Scott Michel8efdca42007-12-04 22:23:35 +00001272 break;
1273 case MVT::i64:
1274 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1275 ResultVals[0] = Chain.getValue(0);
1276 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001277 break;
1278 case MVT::f32:
1279 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001280 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001281 InFlag).getValue(1);
1282 ResultVals[0] = Chain.getValue(0);
1283 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001284 break;
1285 case MVT::v2f64:
1286 case MVT::v4f32:
1287 case MVT::v4i32:
1288 case MVT::v8i16:
1289 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001290 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001291 InFlag).getValue(1);
1292 ResultVals[0] = Chain.getValue(0);
1293 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001294 break;
1295 }
Duncan Sands698842f2008-07-02 17:40:58 +00001296
Scott Michel8efdca42007-12-04 22:23:35 +00001297 // If the function returns void, just return the chain.
1298 if (NumResults == 0)
1299 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001300
Scott Michel8efdca42007-12-04 22:23:35 +00001301 // Otherwise, merge everything together with a MERGE_VALUES node.
1302 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001303 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001304 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001305}
1306
Dan Gohman8181bd12008-07-27 21:46:04 +00001307static SDValue
1308LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001309 SmallVector<CCValAssign, 16> RVLocs;
1310 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1311 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1312 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001313 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001314
Scott Michel8efdca42007-12-04 22:23:35 +00001315 // If this is the first return lowered for this function, add the regs to the
1316 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001317 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001318 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001319 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001320 }
1321
Dan Gohman8181bd12008-07-27 21:46:04 +00001322 SDValue Chain = Op.getOperand(0);
1323 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001324
Scott Michel8efdca42007-12-04 22:23:35 +00001325 // Copy the result values into the output registers.
1326 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1327 CCValAssign &VA = RVLocs[i];
1328 assert(VA.isRegLoc() && "Can only return in registers!");
1329 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1330 Flag = Chain.getValue(1);
1331 }
1332
Gabor Greif1c80d112008-08-28 21:40:38 +00001333 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001334 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1335 else
1336 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1337}
1338
1339
1340//===----------------------------------------------------------------------===//
1341// Vector related lowering:
1342//===----------------------------------------------------------------------===//
1343
1344static ConstantSDNode *
1345getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001346 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001347
Scott Michel8efdca42007-12-04 22:23:35 +00001348 // Check to see if this buildvec has a single non-undef value in its elements.
1349 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1350 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001351 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001352 OpVal = N->getOperand(i);
1353 else if (OpVal != N->getOperand(i))
1354 return 0;
1355 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001356
Gabor Greif1c80d112008-08-28 21:40:38 +00001357 if (OpVal.getNode() != 0) {
Scott Michel8efdca42007-12-04 22:23:35 +00001358 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1359 return CN;
1360 }
1361 }
1362
1363 return 0; // All UNDEF: use implicit def.; not Constant node
1364}
1365
1366/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1367/// and the value fits into an unsigned 18-bit constant, and if so, return the
1368/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001369SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001370 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001371 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001372 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001373 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001374 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001375 uint32_t upper = uint32_t(UValue >> 32);
1376 uint32_t lower = uint32_t(UValue);
1377 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001378 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001379 Value = Value >> 32;
1380 }
Scott Michel8efdca42007-12-04 22:23:35 +00001381 if (Value <= 0x3ffff)
1382 return DAG.getConstant(Value, ValueType);
1383 }
1384
Dan Gohman8181bd12008-07-27 21:46:04 +00001385 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001386}
1387
1388/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1389/// and the value fits into a signed 16-bit constant, and if so, return the
1390/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001391SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001392 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001393 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001394 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001395 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001396 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001397 uint32_t upper = uint32_t(UValue >> 32);
1398 uint32_t lower = uint32_t(UValue);
1399 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001400 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001401 Value = Value >> 32;
1402 }
Scott Michel6baba072008-03-05 23:02:02 +00001403 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
1404 return DAG.getConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001405 }
1406 }
1407
Dan Gohman8181bd12008-07-27 21:46:04 +00001408 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001409}
1410
1411/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1412/// and the value fits into a signed 10-bit constant, and if so, return the
1413/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001414SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001415 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001416 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001417 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001418 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001419 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001420 uint32_t upper = uint32_t(UValue >> 32);
1421 uint32_t lower = uint32_t(UValue);
1422 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001423 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001424 Value = Value >> 32;
1425 }
Scott Michel6baba072008-03-05 23:02:02 +00001426 if (isS10Constant(Value))
Scott Michel8efdca42007-12-04 22:23:35 +00001427 return DAG.getConstant(Value, ValueType);
1428 }
1429
Dan Gohman8181bd12008-07-27 21:46:04 +00001430 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001431}
1432
1433/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1434/// and the value fits into a signed 8-bit constant, and if so, return the
1435/// constant.
1436///
1437/// @note: The incoming vector is v16i8 because that's the only way we can load
1438/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1439/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001440SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001441 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001442 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001443 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001444 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001445 && Value <= 0xffff /* truncated from uint64_t */
1446 && ((short) Value >> 8) == ((short) Value & 0xff))
Scott Michel8efdca42007-12-04 22:23:35 +00001447 return DAG.getConstant(Value & 0xff, ValueType);
1448 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001449 && (Value & 0xff) == Value)
Scott Michel8efdca42007-12-04 22:23:35 +00001450 return DAG.getConstant(Value, ValueType);
1451 }
1452
Dan Gohman8181bd12008-07-27 21:46:04 +00001453 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001454}
1455
1456/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1457/// and the value fits into a signed 16-bit constant, and if so, return the
1458/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001459SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001460 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001461 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001462 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001463 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001464 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1465 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Scott Michel8efdca42007-12-04 22:23:35 +00001466 return DAG.getConstant(Value >> 16, ValueType);
1467 }
1468
Dan Gohman8181bd12008-07-27 21:46:04 +00001469 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001470}
1471
1472/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001473SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001474 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001475 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001476 }
1477
Dan Gohman8181bd12008-07-27 21:46:04 +00001478 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001479}
1480
1481/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001482SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001483 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001484 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001485 }
1486
Dan Gohman8181bd12008-07-27 21:46:04 +00001487 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001488}
1489
1490// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001491// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001492// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1493// zero. Return true if this is not an array of constants, false if it is.
1494//
1495static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1496 uint64_t UndefBits[2]) {
1497 // Start with zero'd results.
1498 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001499
Duncan Sands92c43912008-06-06 12:08:01 +00001500 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001501 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001502 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001503
Scott Michel8efdca42007-12-04 22:23:35 +00001504 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1505 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1506
1507 uint64_t EltBits = 0;
1508 if (OpVal.getOpcode() == ISD::UNDEF) {
1509 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1510 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1511 continue;
1512 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001513 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel8efdca42007-12-04 22:23:35 +00001514 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
1515 const APFloat &apf = CN->getValueAPF();
1516 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001517 ? FloatToBits(apf.convertToFloat())
1518 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001519 } else {
1520 // Nonconstant element.
1521 return true;
1522 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001523
Scott Michel8efdca42007-12-04 22:23:35 +00001524 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1525 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001526
1527 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001528 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1529 return false;
1530}
1531
1532/// If this is a splat (repetition) of a value across the whole vector, return
1533/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001534/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001535/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001536static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001537 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001538 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001539 uint64_t &SplatBits, uint64_t &SplatUndef,
1540 int &SplatSize) {
1541 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1542 // the same as the lower 64-bits, ignoring undefs.
1543 uint64_t Bits64 = Bits128[0] | Bits128[1];
1544 uint64_t Undef64 = Undef128[0] & Undef128[1];
1545 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1546 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1547 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1548 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1549
1550 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1551 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001552
Scott Michel8efdca42007-12-04 22:23:35 +00001553 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1554 // undefs.
1555 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001556 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001557
Scott Michel5a6f17b2008-01-30 02:55:46 +00001558 // If the top 16-bits are different than the lower 16-bits, ignoring
1559 // undefs, we have an i32 splat.
1560 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1561 if (MinSplatBits < 16) {
1562 // If the top 8-bits are different than the lower 8-bits, ignoring
1563 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001564 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1565 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001566 // Otherwise, we have an 8-bit splat.
1567 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1568 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1569 SplatSize = 1;
1570 return true;
1571 }
1572 } else {
1573 SplatBits = Bits16;
1574 SplatUndef = Undef16;
1575 SplatSize = 2;
1576 return true;
1577 }
1578 }
1579 } else {
1580 SplatBits = Bits32;
1581 SplatUndef = Undef32;
1582 SplatSize = 4;
1583 return true;
1584 }
Scott Michel8efdca42007-12-04 22:23:35 +00001585 }
1586 } else {
1587 SplatBits = Bits128[0];
1588 SplatUndef = Undef128[0];
1589 SplatSize = 8;
1590 return true;
1591 }
1592 }
1593
1594 return false; // Can't be a splat if two pieces don't match.
1595}
1596
1597// If this is a case we can't handle, return null and let the default
1598// expansion code take care of it. If we CAN select this case, and if it
1599// selects to a single instruction, return Op. Otherwise, if we can codegen
1600// this case more efficiently than a constant pool load, lower it to the
1601// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001602static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001603 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001604 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001605 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001606 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001607 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001608 uint64_t VectorBits[2];
1609 uint64_t UndefBits[2];
1610 uint64_t SplatBits, SplatUndef;
1611 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001612 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001613 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001614 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001615 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001616 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001617
Duncan Sands92c43912008-06-06 12:08:01 +00001618 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001619 default:
1620 case MVT::v4f32: {
1621 uint32_t Value32 = SplatBits;
1622 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001623 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001624 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001625 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001626 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001627 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001628 break;
1629 }
1630 case MVT::v2f64: {
1631 uint64_t f64val = SplatBits;
1632 assert(SplatSize == 8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001633 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel8efdca42007-12-04 22:23:35 +00001634 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001635 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001636 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001637 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001638 break;
1639 }
1640 case MVT::v16i8: {
1641 // 8-bit constants have to be expanded to 16-bits
1642 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001643 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001644 for (int i = 0; i < 8; ++i)
1645 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1646 return DAG.getNode(ISD::BIT_CONVERT, VT,
1647 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1648 }
1649 case MVT::v8i16: {
1650 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001651 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001652 Value16 = (unsigned short) (SplatBits & 0xffff);
1653 else
1654 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001655 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1656 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001657 for (int i = 0; i < 8; ++i) Ops[i] = T;
1658 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1659 }
1660 case MVT::v4i32: {
1661 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001662 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001663 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1664 }
1665 case MVT::v2i64: {
1666 uint64_t val = SplatBits;
1667 uint32_t upper = uint32_t(val >> 32);
1668 uint32_t lower = uint32_t(val);
1669
Scott Michelbcc7b672008-03-06 04:02:54 +00001670 if (upper == lower) {
1671 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001672 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001673 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001674 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001675 SDValue LO32;
1676 SDValue HI32;
1677 SmallVector<SDValue, 16> ShufBytes;
1678 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001679 bool upper_special, lower_special;
1680
1681 // NOTE: This code creates common-case shuffle masks that can be easily
1682 // detected as common expressions. It is not attempting to create highly
1683 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1684
1685 // Detect if the upper or lower half is a special shuffle mask pattern:
1686 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1687 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1688
1689 // Create lower vector if not a special pattern
1690 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001691 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001692 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1693 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1694 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001695 }
1696
1697 // Create upper vector if not a special pattern
1698 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001699 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001700 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1701 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1702 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001703 }
1704
1705 // If either upper or lower are special, then the two input operands are
1706 // the same (basically, one of them is a "don't care")
1707 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001708 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001709 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001710 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001711 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001712 // Unhappy situation... both upper and lower are special, so punt with
1713 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001714 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001715 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001716 Zero, Zero);
1717 }
1718
1719 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001720 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001721 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001722 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001723 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001724 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001725 process_upper = (upper_special && (i & 1) == 0);
1726 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001727
Scott Michel5a6f17b2008-01-30 02:55:46 +00001728 if (process_upper || process_lower) {
1729 if ((process_upper && upper == 0)
1730 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001731 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001732 else if ((process_upper && upper == 0xffffffff)
1733 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001734 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001735 else if ((process_upper && upper == 0x80000000)
1736 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001737 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001738 } else
Scott Michel67224b22008-06-02 22:18:03 +00001739 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001740 }
Scott Michel67224b22008-06-02 22:18:03 +00001741
1742 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001743 }
1744
1745 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001746 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001747 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001748 }
1749 }
1750 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001751
Dan Gohman8181bd12008-07-27 21:46:04 +00001752 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001753}
1754
1755/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1756/// which the Cell can operate. The code inspects V3 to ascertain whether the
1757/// permutation vector, V3, is monotonically increasing with one "exception"
1758/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1759/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1760/// In either case, the net result is going to eventually invoke SHUFB to
1761/// permute/shuffle the bytes from V1 and V2.
1762/// \note
1763/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1764/// control word for byte/halfword/word insertion. This takes care of a single
1765/// element move from V2 into V1.
1766/// \note
1767/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001768static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1769 SDValue V1 = Op.getOperand(0);
1770 SDValue V2 = Op.getOperand(1);
1771 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001772
Scott Michel8efdca42007-12-04 22:23:35 +00001773 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001774
Scott Michel8efdca42007-12-04 22:23:35 +00001775 // If we have a single element being moved from V1 to V2, this can be handled
1776 // using the C*[DX] compute mask instructions, but the vector elements have
1777 // to be monotonically increasing with one exception element.
Duncan Sands92c43912008-06-06 12:08:01 +00001778 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001779 unsigned EltsFromV2 = 0;
1780 unsigned V2Elt = 0;
1781 unsigned V2EltIdx0 = 0;
1782 unsigned CurrElt = 0;
1783 bool monotonic = true;
1784 if (EltVT == MVT::i8)
1785 V2EltIdx0 = 16;
1786 else if (EltVT == MVT::i16)
1787 V2EltIdx0 = 8;
1788 else if (EltVT == MVT::i32)
1789 V2EltIdx0 = 4;
1790 else
1791 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1792
1793 for (unsigned i = 0, e = PermMask.getNumOperands();
1794 EltsFromV2 <= 1 && monotonic && i != e;
1795 ++i) {
1796 unsigned SrcElt;
1797 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1798 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001799 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001800 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001801
1802 if (SrcElt >= V2EltIdx0) {
1803 ++EltsFromV2;
1804 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1805 } else if (CurrElt != SrcElt) {
1806 monotonic = false;
1807 }
1808
1809 ++CurrElt;
1810 }
1811
1812 if (EltsFromV2 == 1 && monotonic) {
1813 // Compute mask and shuffle
1814 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001815 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1816 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001817 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001818 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001819 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001820 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1821 // Copy register's contents as index in INSERT_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001822 SDValue ShufMaskOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001823 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001824 DAG.getTargetConstant(V2Elt, MVT::i32),
1825 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001826 // Use shuffle mask in SHUFB synthetic instruction:
1827 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1828 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001829 // Convert the SHUFFLE_VECTOR mask's input element units to the
1830 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001831 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001832
Dan Gohman8181bd12008-07-27 21:46:04 +00001833 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001834 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1835 unsigned SrcElt;
1836 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001837 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001838 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001839 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001840
Scott Michel97872d32008-02-23 18:41:37 +00001841 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001842 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1843 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001844 }
1845 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001846
Dan Gohman8181bd12008-07-27 21:46:04 +00001847 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001848 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001849 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1850 }
1851}
1852
Dan Gohman8181bd12008-07-27 21:46:04 +00001853static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1854 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001855
Gabor Greif1c80d112008-08-28 21:40:38 +00001856 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001857 // For a constant, build the appropriate constant vector, which will
1858 // eventually simplify to a vector register load.
1859
Gabor Greif1c80d112008-08-28 21:40:38 +00001860 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001861 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001862 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001863 size_t n_copies;
1864
1865 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001866 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001867 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001868 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001869 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1870 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1871 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1872 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1873 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1874 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1875 }
1876
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001877 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001878 for (size_t j = 0; j < n_copies; ++j)
1879 ConstVecValues.push_back(CValue);
1880
1881 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001882 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001883 } else {
1884 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001885 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001886 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1887 case MVT::i8:
1888 case MVT::i16:
1889 case MVT::i32:
1890 case MVT::i64:
1891 case MVT::f32:
1892 case MVT::f64:
1893 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1894 }
1895 }
1896
Dan Gohman8181bd12008-07-27 21:46:04 +00001897 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001898}
1899
Dan Gohman8181bd12008-07-27 21:46:04 +00001900static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001901 switch (Op.getValueType().getSimpleVT()) {
1902 default:
1903 cerr << "CellSPU: Unknown vector multiplication, got "
1904 << Op.getValueType().getMVTString()
1905 << "\n";
1906 abort();
1907 /*NOTREACHED*/
1908
Scott Michel8efdca42007-12-04 22:23:35 +00001909 case MVT::v4i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001910 SDValue rA = Op.getOperand(0);
1911 SDValue rB = Op.getOperand(1);
1912 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1913 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1914 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1915 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel8efdca42007-12-04 22:23:35 +00001916
1917 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1918 break;
1919 }
1920
1921 // Multiply two v8i16 vectors (pipeline friendly version):
1922 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1923 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1924 // c) Use SELB to select upper and lower halves from the intermediate results
1925 //
Scott Michel67224b22008-06-02 22:18:03 +00001926 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel8efdca42007-12-04 22:23:35 +00001927 // dual-issue. This code does manage to do this, even if it's a little on
1928 // the wacky side
1929 case MVT::v8i16: {
1930 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001931 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman8181bd12008-07-27 21:46:04 +00001932 SDValue Chain = Op.getOperand(0);
1933 SDValue rA = Op.getOperand(0);
1934 SDValue rB = Op.getOperand(1);
Chris Lattner1b989192007-12-31 04:13:23 +00001935 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1936 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00001937
Dan Gohman8181bd12008-07-27 21:46:04 +00001938 SDValue FSMBOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001939 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel67224b22008-06-02 22:18:03 +00001940 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001941 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel8efdca42007-12-04 22:23:35 +00001942
Dan Gohman8181bd12008-07-27 21:46:04 +00001943 SDValue HHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001944 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001945 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001946
Dan Gohman8181bd12008-07-27 21:46:04 +00001947 SDValue HHProd_v4i32 =
Scott Michel8efdca42007-12-04 22:23:35 +00001948 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001949 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001950
1951 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001952 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1953 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1954 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1955 HHProd_v4i32,
1956 DAG.getConstant(16, MVT::i16))),
1957 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001958 }
1959
1960 // This M00sE is N@stI! (apologies to Monty Python)
1961 //
1962 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1963 // is to break it all apart, sign extend, and reassemble the various
1964 // intermediate products.
1965 case MVT::v16i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001966 SDValue rA = Op.getOperand(0);
1967 SDValue rB = Op.getOperand(1);
1968 SDValue c8 = DAG.getConstant(8, MVT::i32);
1969 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001970
Dan Gohman8181bd12008-07-27 21:46:04 +00001971 SDValue LLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001972 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001973 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1974 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001975
Dan Gohman8181bd12008-07-27 21:46:04 +00001976 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001977
Dan Gohman8181bd12008-07-27 21:46:04 +00001978 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001979
Dan Gohman8181bd12008-07-27 21:46:04 +00001980 SDValue LHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001981 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001982 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001983
Dan Gohman8181bd12008-07-27 21:46:04 +00001984 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001985 DAG.getConstant(0x2222, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001986
Dan Gohman8181bd12008-07-27 21:46:04 +00001987 SDValue LoProdParts =
Scott Michel97872d32008-02-23 18:41:37 +00001988 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1989 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1990 LLProd, LHProd, FSMBmask));
Scott Michel8efdca42007-12-04 22:23:35 +00001991
Dan Gohman8181bd12008-07-27 21:46:04 +00001992 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001993
Dan Gohman8181bd12008-07-27 21:46:04 +00001994 SDValue LoProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001995 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michel97872d32008-02-23 18:41:37 +00001996 LoProdParts,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001997 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1998 LoProdMask, LoProdMask,
1999 LoProdMask, LoProdMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002000
Dan Gohman8181bd12008-07-27 21:46:04 +00002001 SDValue rAH =
Scott Michel8efdca42007-12-04 22:23:35 +00002002 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002003 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002004
Dan Gohman8181bd12008-07-27 21:46:04 +00002005 SDValue rBH =
Scott Michel8efdca42007-12-04 22:23:35 +00002006 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002007 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002008
Dan Gohman8181bd12008-07-27 21:46:04 +00002009 SDValue HLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00002010 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002011 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2012 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel8efdca42007-12-04 22:23:35 +00002013
Dan Gohman8181bd12008-07-27 21:46:04 +00002014 SDValue HHProd_1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002015 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002016 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00002017 DAG.getNode(SPUISD::VEC_SRA,
2018 MVT::v4i32, rAH, c8)),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002019 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00002020 DAG.getNode(SPUISD::VEC_SRA,
2021 MVT::v4i32, rBH, c8)));
Scott Michel8efdca42007-12-04 22:23:35 +00002022
Dan Gohman8181bd12008-07-27 21:46:04 +00002023 SDValue HHProd =
Scott Michel97872d32008-02-23 18:41:37 +00002024 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2025 HLProd,
2026 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2027 FSMBmask);
Scott Michel8efdca42007-12-04 22:23:35 +00002028
Dan Gohman8181bd12008-07-27 21:46:04 +00002029 SDValue HiProd =
Scott Michel97872d32008-02-23 18:41:37 +00002030 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002031
2032 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002033 DAG.getNode(ISD::OR, MVT::v4i32,
2034 LoProd, HiProd));
Scott Michel8efdca42007-12-04 22:23:35 +00002035 }
Scott Michel8efdca42007-12-04 22:23:35 +00002036 }
2037
Dan Gohman8181bd12008-07-27 21:46:04 +00002038 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002039}
2040
Dan Gohman8181bd12008-07-27 21:46:04 +00002041static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00002042 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002043 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002044
Dan Gohman8181bd12008-07-27 21:46:04 +00002045 SDValue A = Op.getOperand(0);
2046 SDValue B = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002047 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002048
2049 unsigned VRegBR, VRegC;
2050
2051 if (VT == MVT::f32) {
Chris Lattner1b989192007-12-31 04:13:23 +00002052 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2053 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002054 } else {
Chris Lattner1b989192007-12-31 04:13:23 +00002055 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2056 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002057 }
2058 // TODO: make sure we're feeding FPInterp the right arguments
2059 // Right now: fi B, frest(B)
2060
2061 // Computes BRcpl =
2062 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman8181bd12008-07-27 21:46:04 +00002063 SDValue BRcpl =
Scott Michel4ec722e2008-07-16 17:17:29 +00002064 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2065 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002066 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002067
Scott Michel8efdca42007-12-04 22:23:35 +00002068 // Computes A * BRcpl and stores in a temporary register
Dan Gohman8181bd12008-07-27 21:46:04 +00002069 SDValue AxBRcpl =
Scott Michel8efdca42007-12-04 22:23:35 +00002070 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel4ec722e2008-07-16 17:17:29 +00002071 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002072 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel8efdca42007-12-04 22:23:35 +00002073 // What's the Chain variable do? It's magic!
2074 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel4ec722e2008-07-16 17:17:29 +00002075
2076 return DAG.getNode(ISD::FADD, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002077 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel4ec722e2008-07-16 17:17:29 +00002078 DAG.getNode(ISD::FMUL, VT,
2079 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002080 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel4ec722e2008-07-16 17:17:29 +00002081 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002082 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel8efdca42007-12-04 22:23:35 +00002083}
2084
Dan Gohman8181bd12008-07-27 21:46:04 +00002085static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002086 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002087 SDValue N = Op.getOperand(0);
2088 SDValue Elt = Op.getOperand(1);
2089 SDValue ShufMask[16];
Scott Michel8efdca42007-12-04 22:23:35 +00002090 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
2091
2092 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2093
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002094 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002095
2096 // sanity checks:
2097 if (VT == MVT::i8 && EltNo >= 16)
2098 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2099 else if (VT == MVT::i16 && EltNo >= 8)
2100 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2101 else if (VT == MVT::i32 && EltNo >= 4)
2102 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2103 else if (VT == MVT::i64 && EltNo >= 2)
2104 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2105
2106 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2107 // i32 and i64: Element 0 is the preferred slot
2108 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2109 }
2110
2111 // Need to generate shuffle mask and extract:
Scott Michel4c07cbd2007-12-19 21:17:42 +00002112 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands92c43912008-06-06 12:08:01 +00002113 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel8efdca42007-12-04 22:23:35 +00002114
Duncan Sands92c43912008-06-06 12:08:01 +00002115 switch (VT.getSimpleVT()) {
2116 default:
2117 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002118 case MVT::i8: {
2119 prefslot_begin = prefslot_end = 3;
2120 break;
2121 }
2122 case MVT::i16: {
2123 prefslot_begin = 2; prefslot_end = 3;
2124 break;
2125 }
2126 case MVT::i32: {
2127 prefslot_begin = 0; prefslot_end = 3;
2128 break;
2129 }
2130 case MVT::i64: {
2131 prefslot_begin = 0; prefslot_end = 7;
2132 break;
2133 }
2134 }
2135
Scott Michel4c07cbd2007-12-19 21:17:42 +00002136 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel5a6f17b2008-01-30 02:55:46 +00002137 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel4c07cbd2007-12-19 21:17:42 +00002138
Scott Michel8efdca42007-12-04 22:23:35 +00002139 for (int i = 0; i < 16; ++i) {
2140 // zero fill uppper part of preferred slot, don't care about the
2141 // other slots:
2142 unsigned int mask_val;
2143
2144 if (i <= prefslot_end) {
2145 mask_val =
Scott Michel5a6f17b2008-01-30 02:55:46 +00002146 ((i < prefslot_begin)
2147 ? 0x80
2148 : elt_byte + (i - prefslot_begin));
Scott Michel8efdca42007-12-04 22:23:35 +00002149
Scott Michel4c07cbd2007-12-19 21:17:42 +00002150 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel4ec722e2008-07-16 17:17:29 +00002151 } else
Scott Michel8efdca42007-12-04 22:23:35 +00002152 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2153 }
2154
Dan Gohman8181bd12008-07-27 21:46:04 +00002155 SDValue ShufMaskVec =
Scott Michel8efdca42007-12-04 22:23:35 +00002156 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002157 &ShufMask[0],
2158 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel8efdca42007-12-04 22:23:35 +00002159
2160 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002161 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2162 N, N, ShufMaskVec));
Scott Michel4ec722e2008-07-16 17:17:29 +00002163
Scott Michel8efdca42007-12-04 22:23:35 +00002164}
2165
Dan Gohman8181bd12008-07-27 21:46:04 +00002166static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2167 SDValue VecOp = Op.getOperand(0);
2168 SDValue ValOp = Op.getOperand(1);
2169 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002170 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002171
2172 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2173 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2174
Duncan Sands92c43912008-06-06 12:08:01 +00002175 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00002176 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman8181bd12008-07-27 21:46:04 +00002177 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +00002178
Dan Gohman8181bd12008-07-27 21:46:04 +00002179 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002180 DAG.getNode(SPUISD::SHUFB, VT,
2181 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2182 VecOp,
2183 DAG.getNode(SPUISD::INSERT_MASK, VT,
2184 DAG.getNode(ISD::ADD, PtrVT,
2185 PtrBase,
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002186 DAG.getConstant(CN->getZExtValue(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002187 PtrVT))));
Scott Michel8efdca42007-12-04 22:23:35 +00002188
2189 return result;
2190}
2191
Dan Gohman8181bd12008-07-27 21:46:04 +00002192static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002193{
Dan Gohman8181bd12008-07-27 21:46:04 +00002194 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel8efdca42007-12-04 22:23:35 +00002195
2196 assert(Op.getValueType() == MVT::i8);
2197 switch (Opc) {
2198 default:
2199 assert(0 && "Unhandled i8 math operator");
2200 /*NOTREACHED*/
2201 break;
2202 case ISD::SUB: {
2203 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2204 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002205 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002206 N0 = (N0.getOpcode() != ISD::Constant
2207 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002208 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2209 MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00002210 N1 = (N1.getOpcode() != ISD::Constant
2211 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002212 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2213 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002214 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002215 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002216 }
Scott Michel8efdca42007-12-04 22:23:35 +00002217 case ISD::ROTR:
2218 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002219 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002220 unsigned N1Opc;
2221 N0 = (N0.getOpcode() != ISD::Constant
2222 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002223 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2224 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002225 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2226 ? ISD::ZERO_EXTEND
2227 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002228 N1 = (N1.getOpcode() != ISD::Constant
2229 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002230 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2231 MVT::i16));
Dan Gohman8181bd12008-07-27 21:46:04 +00002232 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002233 DAG.getNode(ISD::OR, MVT::i16, N0,
2234 DAG.getNode(ISD::SHL, MVT::i16,
2235 N0, DAG.getConstant(8, MVT::i16)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002236 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002237 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2238 }
2239 case ISD::SRL:
2240 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002241 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002242 unsigned N1Opc;
2243 N0 = (N0.getOpcode() != ISD::Constant
2244 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002245 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2246 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002247 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2248 ? ISD::ZERO_EXTEND
2249 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002250 N1 = (N1.getOpcode() != ISD::Constant
2251 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002252 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2253 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002254 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002255 DAG.getNode(Opc, MVT::i16, N0, N1));
2256 }
2257 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002258 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002259 unsigned N1Opc;
2260 N0 = (N0.getOpcode() != ISD::Constant
2261 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002262 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2263 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002264 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2265 ? ISD::SIGN_EXTEND
2266 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002267 N1 = (N1.getOpcode() != ISD::Constant
2268 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002269 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2270 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002271 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002272 DAG.getNode(Opc, MVT::i16, N0, N1));
2273 }
2274 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002275 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002276 unsigned N1Opc;
2277 N0 = (N0.getOpcode() != ISD::Constant
2278 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002279 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2280 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002281 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002282 N1 = (N1.getOpcode() != ISD::Constant
2283 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002284 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2285 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002286 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002287 DAG.getNode(Opc, MVT::i16, N0, N1));
2288 break;
2289 }
2290 }
2291
Dan Gohman8181bd12008-07-27 21:46:04 +00002292 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002293}
2294
Dan Gohman8181bd12008-07-27 21:46:04 +00002295static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002296{
Duncan Sands92c43912008-06-06 12:08:01 +00002297 MVT VT = Op.getValueType();
2298 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002299
Dan Gohman8181bd12008-07-27 21:46:04 +00002300 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002301
2302 switch (Opc) {
2303 case ISD::ZERO_EXTEND:
2304 case ISD::SIGN_EXTEND:
2305 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002306 MVT Op0VT = Op0.getValueType();
2307 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002308
2309 assert(Op0VT == MVT::i32
2310 && "CellSPU: Zero/sign extending something other than i32");
Scott Michelbc5fbc12008-04-30 00:30:08 +00002311 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michel97872d32008-02-23 18:41:37 +00002312
2313 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2314 ? SPUISD::ROTBYTES_RIGHT_S
2315 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman8181bd12008-07-27 21:46:04 +00002316 SDValue PromoteScalar =
Scott Michel97872d32008-02-23 18:41:37 +00002317 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2318
2319 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2320 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2321 DAG.getNode(NewOpc, Op0VecVT,
2322 PromoteScalar,
2323 DAG.getConstant(4, MVT::i32))));
2324 }
2325
Scott Michel67224b22008-06-02 22:18:03 +00002326 case ISD::ADD: {
2327 // Turn operands into vectors to satisfy type checking (shufb works on
2328 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002329 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002330 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002331 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002332 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002333 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002334
2335 // Create the shuffle mask for "rotating" the borrow up one register slot
2336 // once the borrow is generated.
2337 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2338 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2339 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2340 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2341
Dan Gohman8181bd12008-07-27 21:46:04 +00002342 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002343 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002344 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002345 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2346 CarryGen, CarryGen,
2347 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2348 &ShufBytes[0], ShufBytes.size()));
2349
2350 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2351 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2352 Op0, Op1, ShiftedCarry));
2353 }
2354
2355 case ISD::SUB: {
2356 // Turn operands into vectors to satisfy type checking (shufb works on
2357 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002358 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002359 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002360 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002361 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002362 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002363
2364 // Create the shuffle mask for "rotating" the borrow up one register slot
2365 // once the borrow is generated.
2366 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2367 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2368 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2369 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2370
Dan Gohman8181bd12008-07-27 21:46:04 +00002371 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002372 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002373 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002374 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2375 BorrowGen, BorrowGen,
2376 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2377 &ShufBytes[0], ShufBytes.size()));
2378
2379 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2380 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2381 Op0, Op1, ShiftedBorrow));
2382 }
2383
Scott Michel97872d32008-02-23 18:41:37 +00002384 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002385 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002386 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002387 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2388 SDValue MaskLower =
Scott Michel97872d32008-02-23 18:41:37 +00002389 DAG.getNode(SPUISD::SELB, VecVT,
2390 Op0Vec,
2391 DAG.getConstant(0, VecVT),
Scott Michel67224b22008-06-02 22:18:03 +00002392 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michel97872d32008-02-23 18:41:37 +00002393 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman8181bd12008-07-27 21:46:04 +00002394 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002395 DAG.getNode(ISD::SRL, ShiftAmtVT,
2396 ShiftAmt,
2397 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002398 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002399 DAG.getNode(ISD::AND, ShiftAmtVT,
2400 ShiftAmt,
2401 DAG.getConstant(7, ShiftAmtVT));
2402
2403 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2404 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2405 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2406 MaskLower, ShiftAmtBytes),
2407 ShiftAmtBits));
2408 }
2409
2410 case ISD::SRL: {
Duncan Sands92c43912008-06-06 12:08:01 +00002411 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002412 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002413 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002414 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002415 DAG.getNode(ISD::SRL, ShiftAmtVT,
2416 ShiftAmt,
2417 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002418 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002419 DAG.getNode(ISD::AND, ShiftAmtVT,
2420 ShiftAmt,
2421 DAG.getConstant(7, ShiftAmtVT));
2422
2423 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2424 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2425 Op0, ShiftAmtBytes),
2426 ShiftAmtBits);
2427 }
Scott Michel67224b22008-06-02 22:18:03 +00002428
2429 case ISD::SRA: {
2430 // Promote Op0 to vector
Dan Gohman8181bd12008-07-27 21:46:04 +00002431 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002432 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002433 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002434 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel67224b22008-06-02 22:18:03 +00002435
2436 // Negate variable shift amounts
2437 if (!isa<ConstantSDNode>(ShiftAmt)) {
2438 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2439 DAG.getConstant(0, ShiftVT), ShiftAmt);
2440 }
2441
Dan Gohman8181bd12008-07-27 21:46:04 +00002442 SDValue UpperHalfSign =
Scott Michel67224b22008-06-02 22:18:03 +00002443 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2444 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2445 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2446 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman8181bd12008-07-27 21:46:04 +00002447 SDValue UpperHalfSignMask =
Scott Michel67224b22008-06-02 22:18:03 +00002448 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman8181bd12008-07-27 21:46:04 +00002449 SDValue UpperLowerMask =
Scott Michel67224b22008-06-02 22:18:03 +00002450 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2451 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman8181bd12008-07-27 21:46:04 +00002452 SDValue UpperLowerSelect =
Scott Michel67224b22008-06-02 22:18:03 +00002453 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2454 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman8181bd12008-07-27 21:46:04 +00002455 SDValue RotateLeftBytes =
Scott Michel67224b22008-06-02 22:18:03 +00002456 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2457 UpperLowerSelect, ShiftAmt);
Dan Gohman8181bd12008-07-27 21:46:04 +00002458 SDValue RotateLeftBits =
Scott Michel67224b22008-06-02 22:18:03 +00002459 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2460 RotateLeftBytes, ShiftAmt);
2461
2462 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2463 RotateLeftBits);
2464 }
Scott Michel97872d32008-02-23 18:41:37 +00002465 }
2466
Dan Gohman8181bd12008-07-27 21:46:04 +00002467 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002468}
2469
Scott Michel8efdca42007-12-04 22:23:35 +00002470//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002471static SDValue
2472LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2473 SDValue ConstVec;
2474 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002475 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002476
2477 ConstVec = Op.getOperand(0);
2478 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002479 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2480 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002481 ConstVec = ConstVec.getOperand(0);
2482 } else {
2483 ConstVec = Op.getOperand(1);
2484 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002485 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002486 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002487 }
2488 }
2489 }
2490
Gabor Greif1c80d112008-08-28 21:40:38 +00002491 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002492 uint64_t VectorBits[2];
2493 uint64_t UndefBits[2];
2494 uint64_t SplatBits, SplatUndef;
2495 int SplatSize;
2496
Gabor Greif1c80d112008-08-28 21:40:38 +00002497 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002498 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002499 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002500 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002501 SDValue tcVec[16];
2502 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002503 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2504
2505 // Turn the BUILD_VECTOR into a set of target constants:
2506 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002507 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002508
Gabor Greif1c80d112008-08-28 21:40:38 +00002509 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002510 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002511 }
2512 }
Nate Begeman7569e762008-07-29 19:07:27 +00002513 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2514 // lowered. Return the operation, rather than a null SDValue.
2515 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002516}
2517
2518//! Lower i32 multiplication
Dan Gohman8181bd12008-07-27 21:46:04 +00002519static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel8efdca42007-12-04 22:23:35 +00002520 unsigned Opc) {
Duncan Sands92c43912008-06-06 12:08:01 +00002521 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00002522 default:
2523 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands92c43912008-06-06 12:08:01 +00002524 << Op.getValueType().getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +00002525 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +00002526 abort();
2527 /*NOTREACHED*/
2528
2529 case MVT::i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002530 SDValue rA = Op.getOperand(0);
2531 SDValue rB = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002532
2533 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002534 DAG.getNode(ISD::ADD, MVT::i32,
2535 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2536 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2537 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00002538 }
2539 }
2540
Dan Gohman8181bd12008-07-27 21:46:04 +00002541 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002542}
2543
2544//! Custom lowering for CTPOP (count population)
2545/*!
2546 Custom lowering code that counts the number ones in the input
2547 operand. SPU has such an instruction, but it counts the number of
2548 ones per byte, which then have to be accumulated.
2549*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002550static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002551 MVT VT = Op.getValueType();
2552 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002553
Duncan Sands92c43912008-06-06 12:08:01 +00002554 switch (VT.getSimpleVT()) {
2555 default:
2556 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002557 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002558 SDValue N = Op.getOperand(0);
2559 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002560
Dan Gohman8181bd12008-07-27 21:46:04 +00002561 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2562 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002563
2564 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2565 }
2566
2567 case MVT::i16: {
2568 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002569 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002570
Chris Lattner1b989192007-12-31 04:13:23 +00002571 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002572
Dan Gohman8181bd12008-07-27 21:46:04 +00002573 SDValue N = Op.getOperand(0);
2574 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2575 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
2576 SDValue Shift1 = DAG.getConstant(8, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002577
Dan Gohman8181bd12008-07-27 21:46:04 +00002578 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2579 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002580
2581 // CNTB_result becomes the chain to which all of the virtual registers
2582 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002583 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002584 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002585
Dan Gohman8181bd12008-07-27 21:46:04 +00002586 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002587 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2588
Dan Gohman8181bd12008-07-27 21:46:04 +00002589 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002590
2591 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002592 DAG.getNode(ISD::ADD, MVT::i16,
2593 DAG.getNode(ISD::SRL, MVT::i16,
2594 Tmp1, Shift1),
2595 Tmp1),
2596 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002597 }
2598
2599 case MVT::i32: {
2600 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002601 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002602
Chris Lattner1b989192007-12-31 04:13:23 +00002603 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2604 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002605
Dan Gohman8181bd12008-07-27 21:46:04 +00002606 SDValue N = Op.getOperand(0);
2607 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2608 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2609 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2610 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002611
Dan Gohman8181bd12008-07-27 21:46:04 +00002612 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2613 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002614
2615 // CNTB_result becomes the chain to which all of the virtual registers
2616 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002617 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002618 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002619
Dan Gohman8181bd12008-07-27 21:46:04 +00002620 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002621 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2622
Dan Gohman8181bd12008-07-27 21:46:04 +00002623 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002624 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002625 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002626
Dan Gohman8181bd12008-07-27 21:46:04 +00002627 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002628 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002629 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002630
Dan Gohman8181bd12008-07-27 21:46:04 +00002631 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002632 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2633
Dan Gohman8181bd12008-07-27 21:46:04 +00002634 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002635 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002636 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2637 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002638 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002639 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002640 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002641
2642 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2643 }
2644
2645 case MVT::i64:
2646 break;
2647 }
2648
Dan Gohman8181bd12008-07-27 21:46:04 +00002649 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002650}
2651
2652/// LowerOperation - Provide custom lowering hooks for some operations.
2653///
Dan Gohman8181bd12008-07-27 21:46:04 +00002654SDValue
2655SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel8efdca42007-12-04 22:23:35 +00002656{
Scott Michel97872d32008-02-23 18:41:37 +00002657 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands92c43912008-06-06 12:08:01 +00002658 MVT VT = Op.getValueType();
Scott Michel97872d32008-02-23 18:41:37 +00002659
2660 switch (Opc) {
Scott Michel8efdca42007-12-04 22:23:35 +00002661 default: {
2662 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michel97872d32008-02-23 18:41:37 +00002663 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greif1c80d112008-08-28 21:40:38 +00002664 cerr << "*Op.getNode():\n";
2665 Op.getNode()->dump();
Scott Michel8efdca42007-12-04 22:23:35 +00002666 abort();
2667 }
2668 case ISD::LOAD:
2669 case ISD::SEXTLOAD:
2670 case ISD::ZEXTLOAD:
2671 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2672 case ISD::STORE:
2673 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2674 case ISD::ConstantPool:
2675 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2676 case ISD::GlobalAddress:
2677 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2678 case ISD::JumpTable:
2679 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2680 case ISD::Constant:
2681 return LowerConstant(Op, DAG);
2682 case ISD::ConstantFP:
2683 return LowerConstantFP(Op, DAG);
Scott Michel394e26d2008-01-17 20:38:41 +00002684 case ISD::BRCOND:
2685 return LowerBRCOND(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002686 case ISD::FORMAL_ARGUMENTS:
Scott Michel394e26d2008-01-17 20:38:41 +00002687 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel8efdca42007-12-04 22:23:35 +00002688 case ISD::CALL:
Scott Micheldbac4cf2008-01-11 02:53:15 +00002689 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel8efdca42007-12-04 22:23:35 +00002690 case ISD::RET:
2691 return LowerRET(Op, DAG, getTargetMachine());
2692
Scott Michel97872d32008-02-23 18:41:37 +00002693
2694 // i8, i64 math ops:
2695 case ISD::ZERO_EXTEND:
2696 case ISD::SIGN_EXTEND:
2697 case ISD::ANY_EXTEND:
Scott Michel67224b22008-06-02 22:18:03 +00002698 case ISD::ADD:
Scott Michel8efdca42007-12-04 22:23:35 +00002699 case ISD::SUB:
2700 case ISD::ROTR:
2701 case ISD::ROTL:
2702 case ISD::SRL:
2703 case ISD::SHL:
Scott Michel67224b22008-06-02 22:18:03 +00002704 case ISD::SRA: {
Scott Michel97872d32008-02-23 18:41:37 +00002705 if (VT == MVT::i8)
2706 return LowerI8Math(Op, DAG, Opc);
2707 else if (VT == MVT::i64)
2708 return LowerI64Math(Op, DAG, Opc);
2709 break;
Scott Michel67224b22008-06-02 22:18:03 +00002710 }
Scott Michel8efdca42007-12-04 22:23:35 +00002711
2712 // Vector-related lowering.
2713 case ISD::BUILD_VECTOR:
2714 return LowerBUILD_VECTOR(Op, DAG);
2715 case ISD::SCALAR_TO_VECTOR:
2716 return LowerSCALAR_TO_VECTOR(Op, DAG);
2717 case ISD::VECTOR_SHUFFLE:
2718 return LowerVECTOR_SHUFFLE(Op, DAG);
2719 case ISD::EXTRACT_VECTOR_ELT:
2720 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2721 case ISD::INSERT_VECTOR_ELT:
2722 return LowerINSERT_VECTOR_ELT(Op, DAG);
2723
2724 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2725 case ISD::AND:
2726 case ISD::OR:
2727 case ISD::XOR:
2728 return LowerByteImmed(Op, DAG);
2729
2730 // Vector and i8 multiply:
2731 case ISD::MUL:
Duncan Sands92c43912008-06-06 12:08:01 +00002732 if (VT.isVector())
Scott Michel8efdca42007-12-04 22:23:35 +00002733 return LowerVectorMUL(Op, DAG);
Scott Michel97872d32008-02-23 18:41:37 +00002734 else if (VT == MVT::i8)
2735 return LowerI8Math(Op, DAG, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002736 else
Scott Michel97872d32008-02-23 18:41:37 +00002737 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002738
2739 case ISD::FDIV:
Scott Michel97872d32008-02-23 18:41:37 +00002740 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel8efdca42007-12-04 22:23:35 +00002741 return LowerFDIVf32(Op, DAG);
2742// else if (Op.getValueType() == MVT::f64)
2743// return LowerFDIVf64(Op, DAG);
2744 else
2745 assert(0 && "Calling FDIV on unsupported MVT");
2746
2747 case ISD::CTPOP:
2748 return LowerCTPOP(Op, DAG);
2749 }
2750
Dan Gohman8181bd12008-07-27 21:46:04 +00002751 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002752}
2753
2754//===----------------------------------------------------------------------===//
Scott Michel8efdca42007-12-04 22:23:35 +00002755// Target Optimization Hooks
2756//===----------------------------------------------------------------------===//
2757
Dan Gohman8181bd12008-07-27 21:46:04 +00002758SDValue
Scott Michel8efdca42007-12-04 22:23:35 +00002759SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2760{
2761#if 0
2762 TargetMachine &TM = getTargetMachine();
Scott Michelf9f42e62008-01-29 02:16:57 +00002763#endif
2764 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel8efdca42007-12-04 22:23:35 +00002765 SelectionDAG &DAG = DCI.DAG;
Dan Gohman8181bd12008-07-27 21:46:04 +00002766 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2767 SDValue Result; // Initially, NULL result
Scott Michel8efdca42007-12-04 22:23:35 +00002768
2769 switch (N->getOpcode()) {
2770 default: break;
Scott Michelf9f42e62008-01-29 02:16:57 +00002771 case ISD::ADD: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002772 SDValue Op1 = N->getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002773
Scott Michel67224b22008-06-02 22:18:03 +00002774 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002775 SDValue Op01 = Op0.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002776 if (Op01.getOpcode() == ISD::Constant
2777 || Op01.getOpcode() == ISD::TargetConstant) {
2778 // (add <const>, (SPUindirect <arg>, <const>)) ->
2779 // (SPUindirect <arg>, <const + const>)
2780 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2781 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman8181bd12008-07-27 21:46:04 +00002782 SDValue combinedConst =
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002783 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michelf9f42e62008-01-29 02:16:57 +00002784 Op0.getValueType());
2785
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002786 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2787 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002788 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002789 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002790 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2791 Op0.getOperand(0), combinedConst);
2792 }
Scott Michel67224b22008-06-02 22:18:03 +00002793 } else if (isa<ConstantSDNode>(Op0)
Scott Michelf9f42e62008-01-29 02:16:57 +00002794 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002795 SDValue Op11 = Op1.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002796 if (Op11.getOpcode() == ISD::Constant
2797 || Op11.getOpcode() == ISD::TargetConstant) {
2798 // (add (SPUindirect <arg>, <const>), <const>) ->
2799 // (SPUindirect <arg>, <const + const>)
2800 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2801 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman8181bd12008-07-27 21:46:04 +00002802 SDValue combinedConst =
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002803 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michelf9f42e62008-01-29 02:16:57 +00002804 Op0.getValueType());
2805
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002806 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2807 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002808 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002809 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002810
2811 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2812 Op1.getOperand(0), combinedConst);
2813 }
2814 }
Scott Michel97872d32008-02-23 18:41:37 +00002815 break;
2816 }
2817 case ISD::SIGN_EXTEND:
2818 case ISD::ZERO_EXTEND:
2819 case ISD::ANY_EXTEND: {
2820 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2821 N->getValueType(0) == Op0.getValueType()) {
2822 // (any_extend (SPUextract_elt0 <arg>)) ->
2823 // (SPUextract_elt0 <arg>)
2824 // Types must match, however...
2825 DEBUG(cerr << "Replace: ");
2826 DEBUG(N->dump(&DAG));
2827 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002828 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002829 DEBUG(cerr << "\n");
2830
2831 return Op0;
2832 }
2833 break;
2834 }
2835 case SPUISD::IndirectAddr: {
2836 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2837 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002838 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00002839 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2840 // (SPUaform <addr>, 0)
2841
2842 DEBUG(cerr << "Replace: ");
2843 DEBUG(N->dump(&DAG));
2844 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002845 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002846 DEBUG(cerr << "\n");
2847
2848 return Op0;
2849 }
2850 }
2851 break;
2852 }
2853 case SPUISD::SHLQUAD_L_BITS:
2854 case SPUISD::SHLQUAD_L_BYTES:
2855 case SPUISD::VEC_SHL:
2856 case SPUISD::VEC_SRL:
2857 case SPUISD::VEC_SRA:
2858 case SPUISD::ROTQUAD_RZ_BYTES:
2859 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002860 SDValue Op1 = N->getOperand(1);
Scott Michel97872d32008-02-23 18:41:37 +00002861
2862 if (isa<ConstantSDNode>(Op1)) {
2863 // Kill degenerate vector shifts:
2864 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2865
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002866 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00002867 Result = Op0;
2868 }
2869 }
2870 break;
2871 }
2872 case SPUISD::PROMOTE_SCALAR: {
2873 switch (Op0.getOpcode()) {
2874 default:
2875 break;
2876 case ISD::ANY_EXTEND:
2877 case ISD::ZERO_EXTEND:
2878 case ISD::SIGN_EXTEND: {
2879 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2880 // <arg>
2881 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman8181bd12008-07-27 21:46:04 +00002882 SDValue Op00 = Op0.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002883 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002884 SDValue Op000 = Op00.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002885 if (Op000.getValueType() == N->getValueType(0)) {
2886 Result = Op000;
2887 }
2888 }
2889 break;
2890 }
2891 case SPUISD::EXTRACT_ELT0: {
2892 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2893 // <arg>
2894 Result = Op0.getOperand(0);
2895 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00002896 }
Scott Michel97872d32008-02-23 18:41:37 +00002897 }
2898 break;
Scott Michelf9f42e62008-01-29 02:16:57 +00002899 }
2900 }
Scott Michel394e26d2008-01-17 20:38:41 +00002901 // Otherwise, return unchanged.
Scott Michelbc5fbc12008-04-30 00:30:08 +00002902#if 1
Gabor Greif1c80d112008-08-28 21:40:38 +00002903 if (Result.getNode()) {
Scott Michel97872d32008-02-23 18:41:37 +00002904 DEBUG(cerr << "\nReplace.SPU: ");
2905 DEBUG(N->dump(&DAG));
2906 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002907 DEBUG(Result.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002908 DEBUG(cerr << "\n");
2909 }
2910#endif
2911
2912 return Result;
Scott Michel8efdca42007-12-04 22:23:35 +00002913}
2914
2915//===----------------------------------------------------------------------===//
2916// Inline Assembly Support
2917//===----------------------------------------------------------------------===//
2918
2919/// getConstraintType - Given a constraint letter, return the type of
2920/// constraint it is for this target.
Scott Michel4ec722e2008-07-16 17:17:29 +00002921SPUTargetLowering::ConstraintType
Scott Michel8efdca42007-12-04 22:23:35 +00002922SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2923 if (ConstraintLetter.size() == 1) {
2924 switch (ConstraintLetter[0]) {
2925 default: break;
2926 case 'b':
2927 case 'r':
2928 case 'f':
2929 case 'v':
2930 case 'y':
2931 return C_RegisterClass;
Scott Michel4ec722e2008-07-16 17:17:29 +00002932 }
Scott Michel8efdca42007-12-04 22:23:35 +00002933 }
2934 return TargetLowering::getConstraintType(ConstraintLetter);
2935}
2936
Scott Michel4ec722e2008-07-16 17:17:29 +00002937std::pair<unsigned, const TargetRegisterClass*>
Scott Michel8efdca42007-12-04 22:23:35 +00002938SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands92c43912008-06-06 12:08:01 +00002939 MVT VT) const
Scott Michel8efdca42007-12-04 22:23:35 +00002940{
2941 if (Constraint.size() == 1) {
2942 // GCC RS6000 Constraint Letters
2943 switch (Constraint[0]) {
2944 case 'b': // R1-R31
2945 case 'r': // R0-R31
2946 if (VT == MVT::i64)
2947 return std::make_pair(0U, SPU::R64CRegisterClass);
2948 return std::make_pair(0U, SPU::R32CRegisterClass);
2949 case 'f':
2950 if (VT == MVT::f32)
2951 return std::make_pair(0U, SPU::R32FPRegisterClass);
2952 else if (VT == MVT::f64)
2953 return std::make_pair(0U, SPU::R64FPRegisterClass);
2954 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00002955 case 'v':
Scott Michel8efdca42007-12-04 22:23:35 +00002956 return std::make_pair(0U, SPU::GPRCRegisterClass);
2957 }
2958 }
Scott Michel4ec722e2008-07-16 17:17:29 +00002959
Scott Michel8efdca42007-12-04 22:23:35 +00002960 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2961}
2962
Scott Michel97872d32008-02-23 18:41:37 +00002963//! Compute used/known bits for a SPU operand
Scott Michel8efdca42007-12-04 22:23:35 +00002964void
Dan Gohman8181bd12008-07-27 21:46:04 +00002965SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohmand0dfc772008-02-13 22:28:48 +00002966 const APInt &Mask,
Scott Michel4ec722e2008-07-16 17:17:29 +00002967 APInt &KnownZero,
Dan Gohman229fa052008-02-13 00:35:47 +00002968 APInt &KnownOne,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002969 const SelectionDAG &DAG,
2970 unsigned Depth ) const {
Scott Michelbc5fbc12008-04-30 00:30:08 +00002971#if 0
Scott Michel97872d32008-02-23 18:41:37 +00002972 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michelbc5fbc12008-04-30 00:30:08 +00002973#endif
Scott Michel97872d32008-02-23 18:41:37 +00002974
2975 switch (Op.getOpcode()) {
2976 default:
2977 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2978 break;
2979
2980#if 0
2981 case CALL:
2982 case SHUFB:
2983 case INSERT_MASK:
2984 case CNTB:
2985#endif
2986
2987 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002988 SDValue Op0 = Op.getOperand(0);
Duncan Sands92c43912008-06-06 12:08:01 +00002989 MVT Op0VT = Op0.getValueType();
2990 unsigned Op0VTBits = Op0VT.getSizeInBits();
2991 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00002992 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2993 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00002994 break;
2995 }
Scott Michel4ec722e2008-07-16 17:17:29 +00002996
Scott Michel97872d32008-02-23 18:41:37 +00002997 case SPUISD::LDRESULT:
2998 case SPUISD::EXTRACT_ELT0:
2999 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands92c43912008-06-06 12:08:01 +00003000 MVT OpVT = Op.getValueType();
3001 unsigned OpVTBits = OpVT.getSizeInBits();
3002 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003003 KnownZero |= APInt(OpVTBits, ~InMask, false);
3004 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003005 break;
3006 }
3007
3008#if 0
3009 case EXTRACT_I1_ZEXT:
3010 case EXTRACT_I1_SEXT:
3011 case EXTRACT_I8_ZEXT:
3012 case EXTRACT_I8_SEXT:
3013 case MPY:
3014 case MPYU:
3015 case MPYH:
3016 case MPYHH:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003017 case SPUISD::SHLQUAD_L_BITS:
3018 case SPUISD::SHLQUAD_L_BYTES:
3019 case SPUISD::VEC_SHL:
3020 case SPUISD::VEC_SRL:
3021 case SPUISD::VEC_SRA:
3022 case SPUISD::VEC_ROTL:
3023 case SPUISD::VEC_ROTR:
3024 case SPUISD::ROTQUAD_RZ_BYTES:
3025 case SPUISD::ROTQUAD_RZ_BITS:
3026 case SPUISD::ROTBYTES_RIGHT_S:
3027 case SPUISD::ROTBYTES_LEFT:
3028 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel67224b22008-06-02 22:18:03 +00003029 case SPUISD::SELECT_MASK:
3030 case SPUISD::SELB:
3031 case SPUISD::FPInterp:
3032 case SPUISD::FPRecipEst:
3033 case SPUISD::SEXT32TO64:
Scott Michel97872d32008-02-23 18:41:37 +00003034#endif
3035 }
Scott Michel8efdca42007-12-04 22:23:35 +00003036}
3037
Scott Michelbc5fbc12008-04-30 00:30:08 +00003038// LowerAsmOperandForConstraint
3039void
Dan Gohman8181bd12008-07-27 21:46:04 +00003040SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003041 char ConstraintLetter,
Evan Cheng7f250d62008-09-24 00:05:32 +00003042 bool hasMemory,
Dan Gohman8181bd12008-07-27 21:46:04 +00003043 std::vector<SDValue> &Ops,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003044 SelectionDAG &DAG) const {
3045 // Default, for the time being, to the base class handler
Evan Cheng7f250d62008-09-24 00:05:32 +00003046 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3047 Ops, DAG);
Scott Michelbc5fbc12008-04-30 00:30:08 +00003048}
3049
Scott Michel8efdca42007-12-04 22:23:35 +00003050/// isLegalAddressImmediate - Return true if the integer value can be used
3051/// as the offset of the target addressing mode.
Gabor Greife9f7f582008-08-31 15:37:04 +00003052bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3053 const Type *Ty) const {
Scott Michel8efdca42007-12-04 22:23:35 +00003054 // SPU's addresses are 256K:
3055 return (V > -(1 << 18) && V < (1 << 18) - 1);
3056}
3057
3058bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel4ec722e2008-07-16 17:17:29 +00003059 return false;
Scott Michel8efdca42007-12-04 22:23:35 +00003060}