blob: 9f828b410b6a792116749db437837cd4287c96e7 [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 Michelabb8ca12008-11-20 16:36:33 +0000133 // Initialize libcalls:
134 setLibcallName(RTLIB::MUL_I64, "__muldi3");
135
Scott Michel8efdca42007-12-04 22:23:35 +0000136 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng08c171a2008-10-14 21:26:46 +0000137 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
138 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
139 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +0000140
Evan Cheng08c171a2008-10-14 21:26:46 +0000141 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
142 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
143 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Scott Michel55252632008-11-20 04:26:21 +0000144 setTruncStoreAction(MVT::i8, MVT::i8, Custom);
145 setTruncStoreAction(MVT::i16, MVT::i8, Custom);
146 setTruncStoreAction(MVT::i32, MVT::i8, Custom);
147 setTruncStoreAction(MVT::i64, MVT::i8, Custom);
148 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000149
Evan Cheng08c171a2008-10-14 21:26:46 +0000150 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
151 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
152 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000153
154 // SPU constant load actions are custom lowered:
155 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begeman78125042008-02-14 18:43:04 +0000156 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000157 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
158
159 // SPU's loads and stores have to be custom lowered:
Scott Michele1006032008-11-19 17:45:08 +0000160 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel8efdca42007-12-04 22:23:35 +0000161 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000162 MVT VT = (MVT::SimpleValueType)sctype;
163
164 setOperationAction(ISD::LOAD, VT, Custom);
165 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000166 }
167
Scott Michel33d73eb2008-11-21 02:56:16 +0000168 // Custom lower BRCOND for i8 to "promote" the result to i16
Scott Michel394e26d2008-01-17 20:38:41 +0000169 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000170
171 // Expand the jumptable branches
172 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
173 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000174 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000175
176 // SPU has no intrinsics for these particular operations:
Andrew Lenharth0531ec52008-02-16 14:46:26 +0000177 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
178
Scott Michel8efdca42007-12-04 22:23:35 +0000179 // PowerPC has no SREM/UREM instructions
180 setOperationAction(ISD::SREM, MVT::i32, Expand);
181 setOperationAction(ISD::UREM, MVT::i32, Expand);
182 setOperationAction(ISD::SREM, MVT::i64, Expand);
183 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000184
Scott Michel8efdca42007-12-04 22:23:35 +0000185 // We don't support sin/cos/sqrt/fmod
186 setOperationAction(ISD::FSIN , MVT::f64, Expand);
187 setOperationAction(ISD::FCOS , MVT::f64, Expand);
188 setOperationAction(ISD::FREM , MVT::f64, Expand);
189 setOperationAction(ISD::FSIN , MVT::f32, Expand);
190 setOperationAction(ISD::FCOS , MVT::f32, Expand);
191 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000192
Scott Michel8efdca42007-12-04 22:23:35 +0000193 // If we're enabling GP optimizations, use hardware square root
194 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
195 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000196
Scott Michel8efdca42007-12-04 22:23:35 +0000197 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
198 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
199
200 // SPU can do rotate right and left, so legalize it... but customize for i8
201 // because instructions don't exist.
Bill Wendling965299c2008-08-31 02:59:23 +0000202
203 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
204 // .td files.
205 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
206 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
207 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
208
Scott Michel8efdca42007-12-04 22:23:35 +0000209 setOperationAction(ISD::ROTL, MVT::i32, Legal);
210 setOperationAction(ISD::ROTL, MVT::i16, Legal);
211 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Michelabb8ca12008-11-20 16:36:33 +0000212
Scott Michel8efdca42007-12-04 22:23:35 +0000213 // SPU has no native version of shift left/right for i8
214 setOperationAction(ISD::SHL, MVT::i8, Custom);
215 setOperationAction(ISD::SRL, MVT::i8, Custom);
216 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000217
218 // SPU needs custom lowering for shift left/right for i64
Scott Michel97872d32008-02-23 18:41:37 +0000219 setOperationAction(ISD::SHL, MVT::i64, Custom);
220 setOperationAction(ISD::SRL, MVT::i64, Custom);
221 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000222
Scott Michel4ec722e2008-07-16 17:17:29 +0000223 // Custom lower i8, i32 and i64 multiplications
224 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000225 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000226 setOperationAction(ISD::MUL, MVT::i64, Expand); // libcall
227
228 // SMUL_LOHI, UMUL_LOHI
229 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
230 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
231 setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom);
232 setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000233
Scott Michel67224b22008-06-02 22:18:03 +0000234 // Need to custom handle (some) common i8, i64 math ops
235 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000236 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000237 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000238
Scott Michel8efdca42007-12-04 22:23:35 +0000239 // SPU does not have BSWAP. It does have i32 support CTLZ.
240 // CTPOP has to be custom lowered.
241 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
242 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
243
244 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
245 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
246 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
247 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
248
249 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
250 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
251
252 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000253
Scott Michel67224b22008-06-02 22:18:03 +0000254 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel978b96f2008-03-10 23:49:09 +0000255 // select ought to work:
Scott Michel53ab7792008-03-10 16:58:52 +0000256 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000257 setOperationAction(ISD::SELECT, MVT::i16, Legal);
258 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000259 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000260
Scott Michel53ab7792008-03-10 16:58:52 +0000261 setOperationAction(ISD::SETCC, MVT::i8, Legal);
262 setOperationAction(ISD::SETCC, MVT::i16, Legal);
263 setOperationAction(ISD::SETCC, MVT::i32, Legal);
264 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michel6baba072008-03-05 23:02:02 +0000265
Scott Michel97872d32008-02-23 18:41:37 +0000266 // Zero extension and sign extension for i64 have to be
267 // custom legalized
268 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
269 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
270 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000271
Scott Michel8efdca42007-12-04 22:23:35 +0000272 // SPU has a legal FP -> signed INT instruction
273 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
274 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
275 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
276 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
277
278 // FDIV on SPU requires custom lowering
279 setOperationAction(ISD::FDIV, MVT::f32, Custom);
280 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
281
282 // SPU has [U|S]INT_TO_FP
283 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
284 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
285 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
286 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
287 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
288 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
289 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
290 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
291
Scott Michel754d8662007-12-20 00:44:13 +0000292 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
293 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
294 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
295 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000296
297 // We cannot sextinreg(i1). Expand to shifts.
298 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000299
Scott Michel8efdca42007-12-04 22:23:35 +0000300 // Support label based line numbers.
Dan Gohman472d12c2008-06-30 20:59:49 +0000301 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000302 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000303
304 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel8efdca42007-12-04 22:23:35 +0000305 // appropriate instructions to materialize the address.
Scott Michel33d73eb2008-11-21 02:56:16 +0000306 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michelf9f42e62008-01-29 02:16:57 +0000307 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000308 MVT VT = (MVT::SimpleValueType)sctype;
309
310 setOperationAction(ISD::GlobalAddress, VT, Custom);
311 setOperationAction(ISD::ConstantPool, VT, Custom);
312 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michelf9f42e62008-01-29 02:16:57 +0000313 }
Scott Michel8efdca42007-12-04 22:23:35 +0000314
315 // RET must be custom lowered, to meet ABI requirements
316 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000317
Scott Michel8efdca42007-12-04 22:23:35 +0000318 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
319 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000320
Scott Michel8efdca42007-12-04 22:23:35 +0000321 // Use the default implementation.
322 setOperationAction(ISD::VAARG , MVT::Other, Expand);
323 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
324 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000325 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000326 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
327 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
328 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
329
330 // Cell SPU has instructions for converting between i64 and fp.
331 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
332 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000333
Scott Michel8efdca42007-12-04 22:23:35 +0000334 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
335 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
336
337 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
338 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
339
340 // First set operation action for all vector types to expand. Then we
341 // will selectively turn on ones that can be effectively codegen'd.
342 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
343 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
344 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
345 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
346 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
347 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
348
Duncan Sands92c43912008-06-06 12:08:01 +0000349 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
350 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
351 MVT VT = (MVT::SimpleValueType)i;
Scott Michel8efdca42007-12-04 22:23:35 +0000352
Duncan Sands92c43912008-06-06 12:08:01 +0000353 // add/sub are legal for all supported vector VT's.
354 setOperationAction(ISD::ADD , VT, Legal);
355 setOperationAction(ISD::SUB , VT, Legal);
356 // mul has to be custom lowered.
357 setOperationAction(ISD::MUL , VT, Custom);
358
359 setOperationAction(ISD::AND , VT, Legal);
360 setOperationAction(ISD::OR , VT, Legal);
361 setOperationAction(ISD::XOR , VT, Legal);
362 setOperationAction(ISD::LOAD , VT, Legal);
363 setOperationAction(ISD::SELECT, VT, Legal);
364 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000365
Scott Michel8efdca42007-12-04 22:23:35 +0000366 // These operations need to be expanded:
Duncan Sands92c43912008-06-06 12:08:01 +0000367 setOperationAction(ISD::SDIV, VT, Expand);
368 setOperationAction(ISD::SREM, VT, Expand);
369 setOperationAction(ISD::UDIV, VT, Expand);
370 setOperationAction(ISD::UREM, VT, Expand);
371 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000372
373 // Custom lower build_vector, constant pool spills, insert and
374 // extract vector elements:
Duncan Sands92c43912008-06-06 12:08:01 +0000375 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
376 setOperationAction(ISD::ConstantPool, VT, Custom);
377 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
378 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
379 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
380 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000381 }
382
383 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
384 setOperationAction(ISD::AND, MVT::v16i8, Custom);
385 setOperationAction(ISD::OR, MVT::v16i8, Custom);
386 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
387 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000388
Scott Michel8efdca42007-12-04 22:23:35 +0000389 setShiftAmountType(MVT::i32);
390 setSetCCResultContents(ZeroOrOneSetCCResult);
Scott Michel4ec722e2008-07-16 17:17:29 +0000391
Scott Michel8efdca42007-12-04 22:23:35 +0000392 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel4ec722e2008-07-16 17:17:29 +0000393
Scott Michel8efdca42007-12-04 22:23:35 +0000394 // We have target-specific dag combine patterns for the following nodes:
Scott Michelf9f42e62008-01-29 02:16:57 +0000395 setTargetDAGCombine(ISD::ADD);
Scott Michel97872d32008-02-23 18:41:37 +0000396 setTargetDAGCombine(ISD::ZERO_EXTEND);
397 setTargetDAGCombine(ISD::SIGN_EXTEND);
398 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel4ec722e2008-07-16 17:17:29 +0000399
Scott Michel8efdca42007-12-04 22:23:35 +0000400 computeRegisterProperties();
401}
402
403const char *
404SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
405{
406 if (node_names.empty()) {
407 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
408 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
409 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
410 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Micheldbac4cf2008-01-11 02:53:15 +0000411 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michelf9f42e62008-01-29 02:16:57 +0000412 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel8efdca42007-12-04 22:23:35 +0000413 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
414 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
415 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
416 node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
417 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
418 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
419 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
Gabor Greife9f7f582008-08-31 15:37:04 +0000420 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED]
421 = "SPUISD::EXTRACT_ELT0_CHAINED";
Scott Michel8efdca42007-12-04 22:23:35 +0000422 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
423 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
424 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
425 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
426 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
427 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
428 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
429 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michel97872d32008-02-23 18:41:37 +0000430 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
431 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel8efdca42007-12-04 22:23:35 +0000432 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
433 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
434 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
435 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
436 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michel97872d32008-02-23 18:41:37 +0000437 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
438 "SPUISD::ROTQUAD_RZ_BYTES";
439 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
440 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel8efdca42007-12-04 22:23:35 +0000441 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
442 "SPUISD::ROTBYTES_RIGHT_S";
443 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
444 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
445 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel67224b22008-06-02 22:18:03 +0000446 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
447 "SPUISD::ROTBYTES_LEFT_BITS";
448 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000449 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel67224b22008-06-02 22:18:03 +0000450 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
451 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
452 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
453 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel8efdca42007-12-04 22:23:35 +0000454 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
455 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
456 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
457 }
458
459 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
460
461 return ((i != node_names.end()) ? i->second : 0);
462}
463
Dan Gohman8181bd12008-07-27 21:46:04 +0000464MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands92c43912008-06-06 12:08:01 +0000465 MVT VT = Op.getValueType();
Scott Michela313fb02008-10-30 01:51:48 +0000466 return (VT.isInteger() ? VT : MVT(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
Scott Michel33d73eb2008-11-21 02:56:16 +0000706 // The vector type we really want to load from the 16-byte chunk.
Scott Michele1006032008-11-19 17:45:08 +0000707 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
708 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +0000709
Dan Gohman8181bd12008-07-27 21:46:04 +0000710 SDValue alignLoadVec =
Scott Micheldbac4cf2008-01-11 02:53:15 +0000711 AlignedLoad(Op, DAG, ST, SN, alignment,
712 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000713
Gabor Greif1c80d112008-08-28 21:40:38 +0000714 if (alignLoadVec.getNode() == 0)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000715 return alignLoadVec;
Scott Michel8efdca42007-12-04 22:23:35 +0000716
Scott Micheldbac4cf2008-01-11 02:53:15 +0000717 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman8181bd12008-07-27 21:46:04 +0000718 SDValue basePtr = LN->getBasePtr();
719 SDValue the_chain = alignLoadVec.getValue(1);
720 SDValue theValue = SN->getValue();
721 SDValue result;
Scott Michel8efdca42007-12-04 22:23:35 +0000722
723 if (StVT != VT
Scott Michel5a6f17b2008-01-30 02:55:46 +0000724 && (theValue.getOpcode() == ISD::AssertZext
725 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel8efdca42007-12-04 22:23:35 +0000726 // Drill down and get the value for zero- and sign-extended
727 // quantities
Scott Michel4ec722e2008-07-16 17:17:29 +0000728 theValue = theValue.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000729 }
730
Scott Micheldbac4cf2008-01-11 02:53:15 +0000731 chunk_offset &= 0xf;
Scott Michel8efdca42007-12-04 22:23:35 +0000732
Dan Gohman8181bd12008-07-27 21:46:04 +0000733 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
734 SDValue insertEltPtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000735
736 // If the base pointer is already a D-form address, then just create
737 // a new D-form address with a slot offset and the orignal base pointer.
738 // Otherwise generate a D-form address with the slot offset relative
739 // to the stack pointer, which is always aligned.
Scott Michelabc58242008-01-11 21:01:19 +0000740 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greif1c80d112008-08-28 21:40:38 +0000741 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michelabc58242008-01-11 21:01:19 +0000742 DEBUG(cerr << "\n");
743
Scott Michelf9f42e62008-01-29 02:16:57 +0000744 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
745 (basePtr.getOpcode() == ISD::ADD
746 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michelabc58242008-01-11 21:01:19 +0000747 insertEltPtr = basePtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000748 } else {
Scott Michelf9f42e62008-01-29 02:16:57 +0000749 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000750 }
751
Scott Michelf65c8f02008-11-19 15:24:16 +0000752 SDValue insertEltOp =
753 DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michele1006032008-11-19 17:45:08 +0000754 SDValue vectorizeOp =
755 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michelf65c8f02008-11-19 15:24:16 +0000756
757 result = DAG.getNode(SPUISD::SHUFB, vecVT, vectorizeOp, alignLoadVec,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000758 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel8efdca42007-12-04 22:23:35 +0000759
Scott Micheldbac4cf2008-01-11 02:53:15 +0000760 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel8efdca42007-12-04 22:23:35 +0000761 LN->getSrcValue(), LN->getSrcValueOffset(),
762 LN->isVolatile(), LN->getAlignment());
763
Scott Michele1006032008-11-19 17:45:08 +0000764#if 0 && defined(NDEBUG)
Scott Michelf65c8f02008-11-19 15:24:16 +0000765 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
766 const SDValue &currentRoot = DAG.getRoot();
767
768 DAG.setRoot(result);
769 cerr << "------- CellSPU:LowerStore result:\n";
770 DAG.dump();
771 cerr << "-------\n";
772 DAG.setRoot(currentRoot);
773 }
774#endif
775
Scott Michel8efdca42007-12-04 22:23:35 +0000776 return result;
777 /*UNREACHED*/
778 }
779 case ISD::PRE_INC:
780 case ISD::PRE_DEC:
781 case ISD::POST_INC:
782 case ISD::POST_DEC:
783 case ISD::LAST_INDEXED_MODE:
784 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
785 "UNINDEXED\n";
786 cerr << (unsigned) SN->getAddressingMode() << "\n";
787 abort();
788 /*NOTREACHED*/
789 }
790
Dan Gohman8181bd12008-07-27 21:46:04 +0000791 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000792}
793
794/// Generate the address of a constant pool entry.
Dan Gohman8181bd12008-07-27 21:46:04 +0000795static SDValue
796LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000797 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000798 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
799 Constant *C = CP->getConstVal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000800 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
801 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000802 const TargetMachine &TM = DAG.getTarget();
Scott Michel8efdca42007-12-04 22:23:35 +0000803
804 if (TM.getRelocationModel() == Reloc::Static) {
805 if (!ST->usingLargeMem()) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000806 // Just return the SDValue with the constant pool address in it.
Scott Michel394e26d2008-01-17 20:38:41 +0000807 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +0000808 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000809 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
810 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000811 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel8efdca42007-12-04 22:23:35 +0000812 }
813 }
814
815 assert(0 &&
Gabor Greife9f7f582008-08-31 15:37:04 +0000816 "LowerConstantPool: Relocation model other than static"
817 " not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000818 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000819}
820
Dan Gohman8181bd12008-07-27 21:46:04 +0000821static SDValue
822LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000823 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000824 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000825 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
826 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000827 const TargetMachine &TM = DAG.getTarget();
828
829 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel97872d32008-02-23 18:41:37 +0000830 if (!ST->usingLargeMem()) {
831 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
832 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000833 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
834 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000835 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
836 }
Scott Michel8efdca42007-12-04 22:23:35 +0000837 }
838
839 assert(0 &&
840 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000841 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000842}
843
Dan Gohman8181bd12008-07-27 21:46:04 +0000844static SDValue
845LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000846 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000847 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
848 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000849 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel8efdca42007-12-04 22:23:35 +0000850 const TargetMachine &TM = DAG.getTarget();
Dan Gohman8181bd12008-07-27 21:46:04 +0000851 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel4ec722e2008-07-16 17:17:29 +0000852
Scott Michel8efdca42007-12-04 22:23:35 +0000853 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michelf9f42e62008-01-29 02:16:57 +0000854 if (!ST->usingLargeMem()) {
855 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
856 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000857 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
858 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michelf9f42e62008-01-29 02:16:57 +0000859 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
860 }
Scott Michel8efdca42007-12-04 22:23:35 +0000861 } else {
862 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel5a6f17b2008-01-30 02:55:46 +0000863 << "supported.\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000864 abort();
865 /*NOTREACHED*/
866 }
867
Dan Gohman8181bd12008-07-27 21:46:04 +0000868 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000869}
870
871//! Custom lower i64 integer constants
872/*!
873 This code inserts all of the necessary juggling that needs to occur to load
874 a 64-bit constant into a register.
875 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000876static SDValue
877LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000878 MVT VT = Op.getValueType();
Gabor Greif1c80d112008-08-28 21:40:38 +0000879 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel8efdca42007-12-04 22:23:35 +0000880
881 if (VT == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000882 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +0000883 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000884 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +0000885 } else {
886 cerr << "LowerConstant: unhandled constant type "
Duncan Sands92c43912008-06-06 12:08:01 +0000887 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +0000888 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000889 abort();
890 /*NOTREACHED*/
891 }
892
Dan Gohman8181bd12008-07-27 21:46:04 +0000893 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000894}
895
Nate Begeman78125042008-02-14 18:43:04 +0000896//! Custom lower double precision floating point constants
Dan Gohman8181bd12008-07-27 21:46:04 +0000897static SDValue
898LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000899 MVT VT = Op.getValueType();
Gabor Greif1c80d112008-08-28 21:40:38 +0000900 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel8efdca42007-12-04 22:23:35 +0000901
902 assert((FP != 0) &&
Scott Michel5a6f17b2008-01-30 02:55:46 +0000903 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel8efdca42007-12-04 22:23:35 +0000904
Nate Begeman78125042008-02-14 18:43:04 +0000905 if (VT == MVT::f64) {
Scott Michel11e88bb2007-12-19 20:15:47 +0000906 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel8efdca42007-12-04 22:23:35 +0000907 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000908 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel8efdca42007-12-04 22:23:35 +0000909 }
910
Dan Gohman8181bd12008-07-27 21:46:04 +0000911 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000912}
913
Scott Michel33d73eb2008-11-21 02:56:16 +0000914//! Lower MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman8181bd12008-07-27 21:46:04 +0000915static SDValue
916LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel394e26d2008-01-17 20:38:41 +0000917{
Dan Gohman8181bd12008-07-27 21:46:04 +0000918 SDValue Cond = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +0000919 MVT CondVT = Cond.getValueType();
920 MVT CondNVT;
Scott Michel394e26d2008-01-17 20:38:41 +0000921
Scott Michel33d73eb2008-11-21 02:56:16 +0000922 if (CondVT == MVT::i8) {
923 CondNVT = MVT::i16;
Scott Michel394e26d2008-01-17 20:38:41 +0000924 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
925 Op.getOperand(0),
926 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
927 Op.getOperand(2));
928 } else
Dan Gohman8181bd12008-07-27 21:46:04 +0000929 return SDValue(); // Unchanged
Scott Michel394e26d2008-01-17 20:38:41 +0000930}
931
Dan Gohman8181bd12008-07-27 21:46:04 +0000932static SDValue
933LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel8efdca42007-12-04 22:23:35 +0000934{
935 MachineFunction &MF = DAG.getMachineFunction();
936 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner1b989192007-12-31 04:13:23 +0000937 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michela313fb02008-10-30 01:51:48 +0000938 SmallVector<SDValue, 48> ArgValues;
Dan Gohman8181bd12008-07-27 21:46:04 +0000939 SDValue Root = Op.getOperand(0);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000940 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel8efdca42007-12-04 22:23:35 +0000941
942 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
943 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel4ec722e2008-07-16 17:17:29 +0000944
Scott Michel8efdca42007-12-04 22:23:35 +0000945 unsigned ArgOffset = SPUFrameInfo::minStackSize();
946 unsigned ArgRegIdx = 0;
947 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel4ec722e2008-07-16 17:17:29 +0000948
Duncan Sands92c43912008-06-06 12:08:01 +0000949 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +0000950
Scott Michel8efdca42007-12-04 22:23:35 +0000951 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greife9f7f582008-08-31 15:37:04 +0000952 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
953 ArgNo != e; ++ArgNo) {
Duncan Sands92c43912008-06-06 12:08:01 +0000954 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
955 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michela313fb02008-10-30 01:51:48 +0000956 SDValue ArgVal;
Scott Michel8efdca42007-12-04 22:23:35 +0000957
Scott Michela313fb02008-10-30 01:51:48 +0000958 if (ArgRegIdx < NumArgRegs) {
959 const TargetRegisterClass *ArgRegClass;
Scott Michel4ec722e2008-07-16 17:17:29 +0000960
Scott Michela313fb02008-10-30 01:51:48 +0000961 switch (ObjectVT.getSimpleVT()) {
962 default: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000963 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
964 << ObjectVT.getMVTString()
965 << "\n";
966 abort();
Scott Michela313fb02008-10-30 01:51:48 +0000967 }
968 case MVT::i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000969 ArgRegClass = &SPU::R8CRegClass;
970 break;
Scott Michela313fb02008-10-30 01:51:48 +0000971 case MVT::i16:
Scott Michel33d73eb2008-11-21 02:56:16 +0000972 ArgRegClass = &SPU::R16CRegClass;
973 break;
Scott Michela313fb02008-10-30 01:51:48 +0000974 case MVT::i32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000975 ArgRegClass = &SPU::R32CRegClass;
976 break;
Scott Michela313fb02008-10-30 01:51:48 +0000977 case MVT::i64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000978 ArgRegClass = &SPU::R64CRegClass;
979 break;
Scott Michela313fb02008-10-30 01:51:48 +0000980 case MVT::f32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000981 ArgRegClass = &SPU::R32FPRegClass;
982 break;
Scott Michela313fb02008-10-30 01:51:48 +0000983 case MVT::f64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000984 ArgRegClass = &SPU::R64FPRegClass;
985 break;
Scott Michela313fb02008-10-30 01:51:48 +0000986 case MVT::v2f64:
987 case MVT::v4f32:
988 case MVT::v2i64:
989 case MVT::v4i32:
990 case MVT::v8i16:
991 case MVT::v16i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000992 ArgRegClass = &SPU::VECREGRegClass;
993 break;
Scott Michela313fb02008-10-30 01:51:48 +0000994 }
995
996 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
997 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
998 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
999 ++ArgRegIdx;
1000 } else {
1001 // We need to load the argument to a virtual register if we determined
1002 // above that we ran out of physical registers of the appropriate type
1003 // or we're forced to do vararg
Chris Lattner60069452008-02-13 07:35:30 +00001004 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +00001005 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner60069452008-02-13 07:35:30 +00001006 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +00001007 ArgOffset += StackSlotSize;
1008 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001009
Scott Michel8efdca42007-12-04 22:23:35 +00001010 ArgValues.push_back(ArgVal);
Scott Michela313fb02008-10-30 01:51:48 +00001011 // Update the chain
1012 Root = ArgVal.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001013 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001014
Scott Michela313fb02008-10-30 01:51:48 +00001015 // vararg handling:
Scott Michel8efdca42007-12-04 22:23:35 +00001016 if (isVarArg) {
Scott Michela313fb02008-10-30 01:51:48 +00001017 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1018 // We will spill (79-3)+1 registers to the stack
1019 SmallVector<SDValue, 79-3+1> MemOps;
1020
1021 // Create the frame slot
1022
Scott Michel8efdca42007-12-04 22:23:35 +00001023 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Michela313fb02008-10-30 01:51:48 +00001024 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1025 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1026 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1027 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1028 Root = Store.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001029 MemOps.push_back(Store);
Scott Michela313fb02008-10-30 01:51:48 +00001030
1031 // Increment address by stack slot size for the next stored argument
1032 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001033 }
1034 if (!MemOps.empty())
Scott Michela313fb02008-10-30 01:51:48 +00001035 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001036 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001037
Scott Michel8efdca42007-12-04 22:23:35 +00001038 ArgValues.push_back(Root);
Scott Michel4ec722e2008-07-16 17:17:29 +00001039
Scott Michel8efdca42007-12-04 22:23:35 +00001040 // Return the new list of results.
Gabor Greif1c80d112008-08-28 21:40:38 +00001041 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf19591c2008-06-30 10:19:09 +00001042 ArgValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001043}
1044
1045/// isLSAAddress - Return the immediate to use if the specified
1046/// value is representable as a LSA address.
Dan Gohman8181bd12008-07-27 21:46:04 +00001047static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel5974f432008-11-11 03:06:06 +00001048 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel8efdca42007-12-04 22:23:35 +00001049 if (!C) return 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001050
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001051 int Addr = C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001052 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1053 (Addr << 14 >> 14) != Addr)
1054 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel4ec722e2008-07-16 17:17:29 +00001055
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001056 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel8efdca42007-12-04 22:23:35 +00001057}
1058
1059static
Dan Gohman8181bd12008-07-27 21:46:04 +00001060SDValue
1061LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001062 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1063 SDValue Chain = TheCall->getChain();
Dan Gohman705e3f72008-09-13 01:54:27 +00001064 SDValue Callee = TheCall->getCallee();
1065 unsigned NumOps = TheCall->getNumArgs();
Scott Michel8efdca42007-12-04 22:23:35 +00001066 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1067 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1068 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1069
1070 // Handy pointer type
Duncan Sands92c43912008-06-06 12:08:01 +00001071 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +00001072
Scott Michel8efdca42007-12-04 22:23:35 +00001073 // Accumulate how many bytes are to be pushed on the stack, including the
1074 // linkage area, and parameter passing area. According to the SPU ABI,
1075 // we minimally need space for [LR] and [SP]
1076 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel4ec722e2008-07-16 17:17:29 +00001077
Scott Michel8efdca42007-12-04 22:23:35 +00001078 // Set up a copy of the stack pointer for use loading and storing any
1079 // arguments that may not fit in the registers available for argument
1080 // passing.
Dan Gohman8181bd12008-07-27 21:46:04 +00001081 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel4ec722e2008-07-16 17:17:29 +00001082
Scott Michel8efdca42007-12-04 22:23:35 +00001083 // Figure out which arguments are going to go in registers, and which in
1084 // memory.
1085 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1086 unsigned ArgRegIdx = 0;
1087
1088 // Keep track of registers passing arguments
Dan Gohman8181bd12008-07-27 21:46:04 +00001089 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel8efdca42007-12-04 22:23:35 +00001090 // And the arguments passed on the stack
Dan Gohman8181bd12008-07-27 21:46:04 +00001091 SmallVector<SDValue, 8> MemOpChains;
Scott Michel8efdca42007-12-04 22:23:35 +00001092
1093 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001094 SDValue Arg = TheCall->getArg(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001095
Scott Michel8efdca42007-12-04 22:23:35 +00001096 // PtrOff will be used to store the current argument to the stack if a
1097 // register cannot be found for it.
Dan Gohman8181bd12008-07-27 21:46:04 +00001098 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel8efdca42007-12-04 22:23:35 +00001099 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1100
Duncan Sands92c43912008-06-06 12:08:01 +00001101 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001102 default: assert(0 && "Unexpected ValueType for argument!");
1103 case MVT::i32:
1104 case MVT::i64:
1105 case MVT::i128:
1106 if (ArgRegIdx != NumArgRegs) {
1107 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1108 } else {
1109 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001110 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001111 }
1112 break;
1113 case MVT::f32:
1114 case MVT::f64:
1115 if (ArgRegIdx != NumArgRegs) {
1116 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1117 } else {
1118 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001119 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001120 }
1121 break;
1122 case MVT::v4f32:
1123 case MVT::v4i32:
1124 case MVT::v8i16:
1125 case MVT::v16i8:
1126 if (ArgRegIdx != NumArgRegs) {
1127 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1128 } else {
1129 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001130 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001131 }
1132 break;
1133 }
1134 }
1135
1136 // Update number of stack bytes actually used, insert a call sequence start
1137 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001138 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1139 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001140
1141 if (!MemOpChains.empty()) {
1142 // Adjust the stack pointer for the stack arguments.
1143 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1144 &MemOpChains[0], MemOpChains.size());
1145 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001146
Scott Michel8efdca42007-12-04 22:23:35 +00001147 // Build a sequence of copy-to-reg nodes chained together with token chain
1148 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001149 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001150 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1151 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1152 InFlag);
1153 InFlag = Chain.getValue(1);
1154 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001155
Dan Gohman8181bd12008-07-27 21:46:04 +00001156 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001157 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001158
Bill Wendlingfef06052008-09-16 21:48:12 +00001159 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1160 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1161 // node so that legalize doesn't hack it.
Scott Michel5974f432008-11-11 03:06:06 +00001162 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001163 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001164 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001165 SDValue Zero = DAG.getConstant(0, PtrVT);
1166 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001167
Scott Micheldbac4cf2008-01-11 02:53:15 +00001168 if (!ST->usingLargeMem()) {
1169 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1170 // style calls, otherwise, external symbols are BRASL calls. This assumes
1171 // that declared/defined symbols are in the same compilation unit and can
1172 // be reached through PC-relative jumps.
1173 //
1174 // NOTE:
1175 // This may be an unsafe assumption for JIT and really large compilation
1176 // units.
1177 if (GV->isDeclaration()) {
1178 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1179 } else {
1180 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1181 }
Scott Michel8efdca42007-12-04 22:23:35 +00001182 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001183 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1184 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001185 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001186 }
Scott Michel5974f432008-11-11 03:06:06 +00001187 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendlingfef06052008-09-16 21:48:12 +00001188 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Micheldbac4cf2008-01-11 02:53:15 +00001189 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001190 // If this is an absolute destination address that appears to be a legal
1191 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001192 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001193 }
Scott Michel8efdca42007-12-04 22:23:35 +00001194
1195 Ops.push_back(Chain);
1196 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001197
Scott Michel8efdca42007-12-04 22:23:35 +00001198 // Add argument registers to the end of the list so that they are known live
1199 // into the call.
1200 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001201 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001202 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001203
Gabor Greif1c80d112008-08-28 21:40:38 +00001204 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001205 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001206 // Returns a chain and a flag for retval copy to use.
1207 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1208 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001209 InFlag = Chain.getValue(1);
1210
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001211 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1212 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001213 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001214 InFlag = Chain.getValue(1);
1215
Dan Gohman8181bd12008-07-27 21:46:04 +00001216 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001217 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001218
Scott Michel8efdca42007-12-04 22:23:35 +00001219 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001220 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001221 default: assert(0 && "Unexpected ret value!");
1222 case MVT::Other: break;
1223 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001224 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001225 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1226 ResultVals[0] = Chain.getValue(0);
1227 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1228 Chain.getValue(2)).getValue(1);
1229 ResultVals[1] = Chain.getValue(0);
1230 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001231 } else {
1232 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1233 ResultVals[0] = Chain.getValue(0);
1234 NumResults = 1;
1235 }
Scott Michel8efdca42007-12-04 22:23:35 +00001236 break;
1237 case MVT::i64:
1238 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1239 ResultVals[0] = Chain.getValue(0);
1240 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001241 break;
1242 case MVT::f32:
1243 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001244 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001245 InFlag).getValue(1);
1246 ResultVals[0] = Chain.getValue(0);
1247 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001248 break;
1249 case MVT::v2f64:
1250 case MVT::v4f32:
1251 case MVT::v4i32:
1252 case MVT::v8i16:
1253 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001254 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001255 InFlag).getValue(1);
1256 ResultVals[0] = Chain.getValue(0);
1257 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001258 break;
1259 }
Duncan Sands698842f2008-07-02 17:40:58 +00001260
Scott Michel8efdca42007-12-04 22:23:35 +00001261 // If the function returns void, just return the chain.
1262 if (NumResults == 0)
1263 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001264
Scott Michel8efdca42007-12-04 22:23:35 +00001265 // Otherwise, merge everything together with a MERGE_VALUES node.
1266 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001267 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001268 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001269}
1270
Dan Gohman8181bd12008-07-27 21:46:04 +00001271static SDValue
1272LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001273 SmallVector<CCValAssign, 16> RVLocs;
1274 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1275 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1276 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001277 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001278
Scott Michel8efdca42007-12-04 22:23:35 +00001279 // If this is the first return lowered for this function, add the regs to the
1280 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001281 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001282 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001283 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001284 }
1285
Dan Gohman8181bd12008-07-27 21:46:04 +00001286 SDValue Chain = Op.getOperand(0);
1287 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001288
Scott Michel8efdca42007-12-04 22:23:35 +00001289 // Copy the result values into the output registers.
1290 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1291 CCValAssign &VA = RVLocs[i];
1292 assert(VA.isRegLoc() && "Can only return in registers!");
1293 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1294 Flag = Chain.getValue(1);
1295 }
1296
Gabor Greif1c80d112008-08-28 21:40:38 +00001297 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001298 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1299 else
1300 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1301}
1302
1303
1304//===----------------------------------------------------------------------===//
1305// Vector related lowering:
1306//===----------------------------------------------------------------------===//
1307
1308static ConstantSDNode *
1309getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001310 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001311
Scott Michel8efdca42007-12-04 22:23:35 +00001312 // Check to see if this buildvec has a single non-undef value in its elements.
1313 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1314 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001315 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001316 OpVal = N->getOperand(i);
1317 else if (OpVal != N->getOperand(i))
1318 return 0;
1319 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001320
Gabor Greif1c80d112008-08-28 21:40:38 +00001321 if (OpVal.getNode() != 0) {
Scott Michel5974f432008-11-11 03:06:06 +00001322 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001323 return CN;
1324 }
1325 }
1326
1327 return 0; // All UNDEF: use implicit def.; not Constant node
1328}
1329
1330/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1331/// and the value fits into an unsigned 18-bit constant, and if so, return the
1332/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001333SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001334 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001335 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001336 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001337 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001338 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001339 uint32_t upper = uint32_t(UValue >> 32);
1340 uint32_t lower = uint32_t(UValue);
1341 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001342 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001343 Value = Value >> 32;
1344 }
Scott Michel8efdca42007-12-04 22:23:35 +00001345 if (Value <= 0x3ffff)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001346 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001347 }
1348
Dan Gohman8181bd12008-07-27 21:46:04 +00001349 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001350}
1351
1352/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1353/// and the value fits into a signed 16-bit constant, and if so, return the
1354/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001355SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001356 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001357 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001358 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001359 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001360 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001361 uint32_t upper = uint32_t(UValue >> 32);
1362 uint32_t lower = uint32_t(UValue);
1363 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001364 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001365 Value = Value >> 32;
1366 }
Scott Michel6baba072008-03-05 23:02:02 +00001367 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001368 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001369 }
1370 }
1371
Dan Gohman8181bd12008-07-27 21:46:04 +00001372 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001373}
1374
1375/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1376/// and the value fits into a signed 10-bit constant, and if so, return the
1377/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001378SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001379 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001380 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001381 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001382 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001383 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001384 uint32_t upper = uint32_t(UValue >> 32);
1385 uint32_t lower = uint32_t(UValue);
1386 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001387 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001388 Value = Value >> 32;
1389 }
Scott Michel6baba072008-03-05 23:02:02 +00001390 if (isS10Constant(Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001391 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001392 }
1393
Dan Gohman8181bd12008-07-27 21:46:04 +00001394 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001395}
1396
1397/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1398/// and the value fits into a signed 8-bit constant, and if so, return the
1399/// constant.
1400///
1401/// @note: The incoming vector is v16i8 because that's the only way we can load
1402/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1403/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001404SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001405 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001406 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001407 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001408 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001409 && Value <= 0xffff /* truncated from uint64_t */
1410 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001411 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001412 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001413 && (Value & 0xff) == Value)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001414 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001415 }
1416
Dan Gohman8181bd12008-07-27 21:46:04 +00001417 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001418}
1419
1420/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1421/// and the value fits into a signed 16-bit constant, and if so, return the
1422/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001423SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001424 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001425 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001426 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001427 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001428 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1429 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001430 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001431 }
1432
Dan Gohman8181bd12008-07-27 21:46:04 +00001433 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001434}
1435
1436/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001437SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001438 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001439 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001440 }
1441
Dan Gohman8181bd12008-07-27 21:46:04 +00001442 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001443}
1444
1445/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001446SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001447 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001448 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001449 }
1450
Dan Gohman8181bd12008-07-27 21:46:04 +00001451 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001452}
1453
1454// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001455// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001456// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1457// zero. Return true if this is not an array of constants, false if it is.
1458//
1459static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1460 uint64_t UndefBits[2]) {
1461 // Start with zero'd results.
1462 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001463
Duncan Sands92c43912008-06-06 12:08:01 +00001464 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001465 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001466 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001467
Scott Michel8efdca42007-12-04 22:23:35 +00001468 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1469 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1470
1471 uint64_t EltBits = 0;
1472 if (OpVal.getOpcode() == ISD::UNDEF) {
1473 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1474 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1475 continue;
Scott Michel5974f432008-11-11 03:06:06 +00001476 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001477 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel5974f432008-11-11 03:06:06 +00001478 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001479 const APFloat &apf = CN->getValueAPF();
1480 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001481 ? FloatToBits(apf.convertToFloat())
1482 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001483 } else {
1484 // Nonconstant element.
1485 return true;
1486 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001487
Scott Michel8efdca42007-12-04 22:23:35 +00001488 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1489 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001490
1491 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001492 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1493 return false;
1494}
1495
1496/// If this is a splat (repetition) of a value across the whole vector, return
1497/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001498/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001499/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001500static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001501 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001502 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001503 uint64_t &SplatBits, uint64_t &SplatUndef,
1504 int &SplatSize) {
1505 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1506 // the same as the lower 64-bits, ignoring undefs.
1507 uint64_t Bits64 = Bits128[0] | Bits128[1];
1508 uint64_t Undef64 = Undef128[0] & Undef128[1];
1509 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1510 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1511 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1512 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1513
1514 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1515 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001516
Scott Michel8efdca42007-12-04 22:23:35 +00001517 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1518 // undefs.
1519 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001520 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001521
Scott Michel5a6f17b2008-01-30 02:55:46 +00001522 // If the top 16-bits are different than the lower 16-bits, ignoring
1523 // undefs, we have an i32 splat.
1524 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1525 if (MinSplatBits < 16) {
1526 // If the top 8-bits are different than the lower 8-bits, ignoring
1527 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001528 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1529 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001530 // Otherwise, we have an 8-bit splat.
1531 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1532 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1533 SplatSize = 1;
1534 return true;
1535 }
1536 } else {
1537 SplatBits = Bits16;
1538 SplatUndef = Undef16;
1539 SplatSize = 2;
1540 return true;
1541 }
1542 }
1543 } else {
1544 SplatBits = Bits32;
1545 SplatUndef = Undef32;
1546 SplatSize = 4;
1547 return true;
1548 }
Scott Michel8efdca42007-12-04 22:23:35 +00001549 }
1550 } else {
1551 SplatBits = Bits128[0];
1552 SplatUndef = Undef128[0];
1553 SplatSize = 8;
1554 return true;
1555 }
1556 }
1557
1558 return false; // Can't be a splat if two pieces don't match.
1559}
1560
1561// If this is a case we can't handle, return null and let the default
1562// expansion code take care of it. If we CAN select this case, and if it
1563// selects to a single instruction, return Op. Otherwise, if we can codegen
1564// this case more efficiently than a constant pool load, lower it to the
1565// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001566static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001567 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001568 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001569 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001570 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001571 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001572 uint64_t VectorBits[2];
1573 uint64_t UndefBits[2];
1574 uint64_t SplatBits, SplatUndef;
1575 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001576 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001577 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001578 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001579 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001580 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001581
Duncan Sands92c43912008-06-06 12:08:01 +00001582 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001583 default:
1584 case MVT::v4f32: {
1585 uint32_t Value32 = SplatBits;
1586 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001587 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001588 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001589 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001590 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001591 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001592 break;
1593 }
1594 case MVT::v2f64: {
1595 uint64_t f64val = SplatBits;
1596 assert(SplatSize == 8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001597 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel8efdca42007-12-04 22:23:35 +00001598 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001599 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001600 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001601 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001602 break;
1603 }
1604 case MVT::v16i8: {
1605 // 8-bit constants have to be expanded to 16-bits
1606 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001607 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001608 for (int i = 0; i < 8; ++i)
1609 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1610 return DAG.getNode(ISD::BIT_CONVERT, VT,
1611 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1612 }
1613 case MVT::v8i16: {
1614 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001615 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001616 Value16 = (unsigned short) (SplatBits & 0xffff);
1617 else
1618 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001619 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1620 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001621 for (int i = 0; i < 8; ++i) Ops[i] = T;
1622 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1623 }
1624 case MVT::v4i32: {
1625 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001626 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001627 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1628 }
1629 case MVT::v2i64: {
1630 uint64_t val = SplatBits;
1631 uint32_t upper = uint32_t(val >> 32);
1632 uint32_t lower = uint32_t(val);
1633
Scott Michelbcc7b672008-03-06 04:02:54 +00001634 if (upper == lower) {
1635 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001636 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001637 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001638 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001639 SDValue LO32;
1640 SDValue HI32;
1641 SmallVector<SDValue, 16> ShufBytes;
1642 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001643 bool upper_special, lower_special;
1644
1645 // NOTE: This code creates common-case shuffle masks that can be easily
1646 // detected as common expressions. It is not attempting to create highly
1647 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1648
1649 // Detect if the upper or lower half is a special shuffle mask pattern:
1650 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1651 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1652
1653 // Create lower vector if not a special pattern
1654 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001655 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001656 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1657 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1658 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001659 }
1660
1661 // Create upper vector if not a special pattern
1662 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001663 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001664 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1665 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1666 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001667 }
1668
1669 // If either upper or lower are special, then the two input operands are
1670 // the same (basically, one of them is a "don't care")
1671 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001672 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001673 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001674 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001675 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001676 // Unhappy situation... both upper and lower are special, so punt with
1677 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001678 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001679 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001680 Zero, Zero);
1681 }
1682
1683 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001684 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001685 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001686 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001687 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001688 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001689 process_upper = (upper_special && (i & 1) == 0);
1690 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001691
Scott Michel5a6f17b2008-01-30 02:55:46 +00001692 if (process_upper || process_lower) {
1693 if ((process_upper && upper == 0)
1694 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001695 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001696 else if ((process_upper && upper == 0xffffffff)
1697 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001698 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001699 else if ((process_upper && upper == 0x80000000)
1700 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001701 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001702 } else
Scott Michel67224b22008-06-02 22:18:03 +00001703 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001704 }
Scott Michel67224b22008-06-02 22:18:03 +00001705
1706 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001707 }
1708
1709 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001710 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001711 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001712 }
1713 }
1714 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001715
Dan Gohman8181bd12008-07-27 21:46:04 +00001716 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001717}
1718
1719/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1720/// which the Cell can operate. The code inspects V3 to ascertain whether the
1721/// permutation vector, V3, is monotonically increasing with one "exception"
1722/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1723/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1724/// In either case, the net result is going to eventually invoke SHUFB to
1725/// permute/shuffle the bytes from V1 and V2.
1726/// \note
1727/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1728/// control word for byte/halfword/word insertion. This takes care of a single
1729/// element move from V2 into V1.
1730/// \note
1731/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001732static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1733 SDValue V1 = Op.getOperand(0);
1734 SDValue V2 = Op.getOperand(1);
1735 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001736
Scott Michel8efdca42007-12-04 22:23:35 +00001737 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001738
Scott Michel8efdca42007-12-04 22:23:35 +00001739 // If we have a single element being moved from V1 to V2, this can be handled
1740 // using the C*[DX] compute mask instructions, but the vector elements have
1741 // to be monotonically increasing with one exception element.
Duncan Sands92c43912008-06-06 12:08:01 +00001742 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001743 unsigned EltsFromV2 = 0;
1744 unsigned V2Elt = 0;
1745 unsigned V2EltIdx0 = 0;
1746 unsigned CurrElt = 0;
1747 bool monotonic = true;
1748 if (EltVT == MVT::i8)
1749 V2EltIdx0 = 16;
1750 else if (EltVT == MVT::i16)
1751 V2EltIdx0 = 8;
1752 else if (EltVT == MVT::i32)
1753 V2EltIdx0 = 4;
1754 else
1755 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1756
1757 for (unsigned i = 0, e = PermMask.getNumOperands();
1758 EltsFromV2 <= 1 && monotonic && i != e;
1759 ++i) {
1760 unsigned SrcElt;
1761 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1762 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001763 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001764 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001765
1766 if (SrcElt >= V2EltIdx0) {
1767 ++EltsFromV2;
1768 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1769 } else if (CurrElt != SrcElt) {
1770 monotonic = false;
1771 }
1772
1773 ++CurrElt;
1774 }
1775
1776 if (EltsFromV2 == 1 && monotonic) {
1777 // Compute mask and shuffle
1778 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001779 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1780 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001781 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001782 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001783 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001784 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1785 // Copy register's contents as index in INSERT_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001786 SDValue ShufMaskOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001787 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001788 DAG.getTargetConstant(V2Elt, MVT::i32),
1789 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001790 // Use shuffle mask in SHUFB synthetic instruction:
1791 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1792 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001793 // Convert the SHUFFLE_VECTOR mask's input element units to the
1794 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001795 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001796
Dan Gohman8181bd12008-07-27 21:46:04 +00001797 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001798 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1799 unsigned SrcElt;
1800 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001801 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001802 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001803 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001804
Scott Michel97872d32008-02-23 18:41:37 +00001805 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001806 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1807 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001808 }
1809 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001810
Dan Gohman8181bd12008-07-27 21:46:04 +00001811 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001812 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001813 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1814 }
1815}
1816
Dan Gohman8181bd12008-07-27 21:46:04 +00001817static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1818 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001819
Gabor Greif1c80d112008-08-28 21:40:38 +00001820 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001821 // For a constant, build the appropriate constant vector, which will
1822 // eventually simplify to a vector register load.
1823
Gabor Greif1c80d112008-08-28 21:40:38 +00001824 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001825 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001826 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001827 size_t n_copies;
1828
1829 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001830 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001831 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001832 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001833 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1834 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1835 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1836 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1837 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1838 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1839 }
1840
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001841 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001842 for (size_t j = 0; j < n_copies; ++j)
1843 ConstVecValues.push_back(CValue);
1844
1845 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001846 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001847 } else {
1848 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001849 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001850 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1851 case MVT::i8:
1852 case MVT::i16:
1853 case MVT::i32:
1854 case MVT::i64:
1855 case MVT::f32:
1856 case MVT::f64:
1857 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1858 }
1859 }
1860
Dan Gohman8181bd12008-07-27 21:46:04 +00001861 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001862}
1863
Dan Gohman8181bd12008-07-27 21:46:04 +00001864static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001865 switch (Op.getValueType().getSimpleVT()) {
1866 default:
1867 cerr << "CellSPU: Unknown vector multiplication, got "
1868 << Op.getValueType().getMVTString()
1869 << "\n";
1870 abort();
1871 /*NOTREACHED*/
1872
Scott Michel8efdca42007-12-04 22:23:35 +00001873 case MVT::v4i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001874 SDValue rA = Op.getOperand(0);
1875 SDValue rB = Op.getOperand(1);
1876 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1877 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1878 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1879 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel8efdca42007-12-04 22:23:35 +00001880
1881 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1882 break;
1883 }
1884
1885 // Multiply two v8i16 vectors (pipeline friendly version):
1886 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1887 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1888 // c) Use SELB to select upper and lower halves from the intermediate results
1889 //
Scott Michel67224b22008-06-02 22:18:03 +00001890 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel8efdca42007-12-04 22:23:35 +00001891 // dual-issue. This code does manage to do this, even if it's a little on
1892 // the wacky side
1893 case MVT::v8i16: {
1894 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001895 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman8181bd12008-07-27 21:46:04 +00001896 SDValue Chain = Op.getOperand(0);
1897 SDValue rA = Op.getOperand(0);
1898 SDValue rB = Op.getOperand(1);
Chris Lattner1b989192007-12-31 04:13:23 +00001899 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1900 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00001901
Dan Gohman8181bd12008-07-27 21:46:04 +00001902 SDValue FSMBOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001903 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel67224b22008-06-02 22:18:03 +00001904 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001905 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel8efdca42007-12-04 22:23:35 +00001906
Dan Gohman8181bd12008-07-27 21:46:04 +00001907 SDValue HHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001908 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001909 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001910
Dan Gohman8181bd12008-07-27 21:46:04 +00001911 SDValue HHProd_v4i32 =
Scott Michel8efdca42007-12-04 22:23:35 +00001912 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001913 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001914
1915 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001916 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1917 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1918 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1919 HHProd_v4i32,
1920 DAG.getConstant(16, MVT::i16))),
1921 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001922 }
1923
1924 // This M00sE is N@stI! (apologies to Monty Python)
1925 //
1926 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1927 // is to break it all apart, sign extend, and reassemble the various
1928 // intermediate products.
1929 case MVT::v16i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001930 SDValue rA = Op.getOperand(0);
1931 SDValue rB = Op.getOperand(1);
1932 SDValue c8 = DAG.getConstant(8, MVT::i32);
1933 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001934
Dan Gohman8181bd12008-07-27 21:46:04 +00001935 SDValue LLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001936 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001937 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1938 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001939
Dan Gohman8181bd12008-07-27 21:46:04 +00001940 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001941
Dan Gohman8181bd12008-07-27 21:46:04 +00001942 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001943
Dan Gohman8181bd12008-07-27 21:46:04 +00001944 SDValue LHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001945 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001946 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001947
Dan Gohman8181bd12008-07-27 21:46:04 +00001948 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001949 DAG.getConstant(0x2222, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001950
Dan Gohman8181bd12008-07-27 21:46:04 +00001951 SDValue LoProdParts =
Scott Michel97872d32008-02-23 18:41:37 +00001952 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1953 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1954 LLProd, LHProd, FSMBmask));
Scott Michel8efdca42007-12-04 22:23:35 +00001955
Dan Gohman8181bd12008-07-27 21:46:04 +00001956 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001957
Dan Gohman8181bd12008-07-27 21:46:04 +00001958 SDValue LoProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001959 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michel97872d32008-02-23 18:41:37 +00001960 LoProdParts,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001961 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1962 LoProdMask, LoProdMask,
1963 LoProdMask, LoProdMask));
Scott Michel8efdca42007-12-04 22:23:35 +00001964
Dan Gohman8181bd12008-07-27 21:46:04 +00001965 SDValue rAH =
Scott Michel8efdca42007-12-04 22:23:35 +00001966 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001967 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001968
Dan Gohman8181bd12008-07-27 21:46:04 +00001969 SDValue rBH =
Scott Michel8efdca42007-12-04 22:23:35 +00001970 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001971 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001972
Dan Gohman8181bd12008-07-27 21:46:04 +00001973 SDValue HLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001974 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001975 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1976 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel8efdca42007-12-04 22:23:35 +00001977
Dan Gohman8181bd12008-07-27 21:46:04 +00001978 SDValue HHProd_1 =
Scott Michel8efdca42007-12-04 22:23:35 +00001979 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001980 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00001981 DAG.getNode(SPUISD::VEC_SRA,
1982 MVT::v4i32, rAH, c8)),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001983 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00001984 DAG.getNode(SPUISD::VEC_SRA,
1985 MVT::v4i32, rBH, c8)));
Scott Michel8efdca42007-12-04 22:23:35 +00001986
Dan Gohman8181bd12008-07-27 21:46:04 +00001987 SDValue HHProd =
Scott Michel97872d32008-02-23 18:41:37 +00001988 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1989 HLProd,
1990 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
1991 FSMBmask);
Scott Michel8efdca42007-12-04 22:23:35 +00001992
Dan Gohman8181bd12008-07-27 21:46:04 +00001993 SDValue HiProd =
Scott Michel97872d32008-02-23 18:41:37 +00001994 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001995
1996 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001997 DAG.getNode(ISD::OR, MVT::v4i32,
1998 LoProd, HiProd));
Scott Michel8efdca42007-12-04 22:23:35 +00001999 }
Scott Michel8efdca42007-12-04 22:23:35 +00002000 }
2001
Dan Gohman8181bd12008-07-27 21:46:04 +00002002 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002003}
2004
Dan Gohman8181bd12008-07-27 21:46:04 +00002005static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00002006 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002007 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002008
Dan Gohman8181bd12008-07-27 21:46:04 +00002009 SDValue A = Op.getOperand(0);
2010 SDValue B = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002011 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002012
2013 unsigned VRegBR, VRegC;
2014
2015 if (VT == MVT::f32) {
Chris Lattner1b989192007-12-31 04:13:23 +00002016 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2017 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002018 } else {
Chris Lattner1b989192007-12-31 04:13:23 +00002019 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2020 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002021 }
2022 // TODO: make sure we're feeding FPInterp the right arguments
2023 // Right now: fi B, frest(B)
2024
2025 // Computes BRcpl =
2026 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman8181bd12008-07-27 21:46:04 +00002027 SDValue BRcpl =
Scott Michel4ec722e2008-07-16 17:17:29 +00002028 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2029 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002030 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002031
Scott Michel8efdca42007-12-04 22:23:35 +00002032 // Computes A * BRcpl and stores in a temporary register
Dan Gohman8181bd12008-07-27 21:46:04 +00002033 SDValue AxBRcpl =
Scott Michel8efdca42007-12-04 22:23:35 +00002034 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel4ec722e2008-07-16 17:17:29 +00002035 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002036 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel8efdca42007-12-04 22:23:35 +00002037 // What's the Chain variable do? It's magic!
2038 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel4ec722e2008-07-16 17:17:29 +00002039
2040 return DAG.getNode(ISD::FADD, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002041 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel4ec722e2008-07-16 17:17:29 +00002042 DAG.getNode(ISD::FMUL, VT,
2043 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002044 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel4ec722e2008-07-16 17:17:29 +00002045 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002046 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel8efdca42007-12-04 22:23:35 +00002047}
2048
Dan Gohman8181bd12008-07-27 21:46:04 +00002049static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002050 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002051 SDValue N = Op.getOperand(0);
2052 SDValue Elt = Op.getOperand(1);
2053 SDValue ShufMask[16];
Scott Michel5974f432008-11-11 03:06:06 +00002054 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
Scott Michel8efdca42007-12-04 22:23:35 +00002055
2056 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2057
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002058 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002059
2060 // sanity checks:
2061 if (VT == MVT::i8 && EltNo >= 16)
2062 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2063 else if (VT == MVT::i16 && EltNo >= 8)
2064 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2065 else if (VT == MVT::i32 && EltNo >= 4)
2066 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2067 else if (VT == MVT::i64 && EltNo >= 2)
2068 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2069
2070 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2071 // i32 and i64: Element 0 is the preferred slot
2072 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2073 }
2074
2075 // Need to generate shuffle mask and extract:
Scott Michel4c07cbd2007-12-19 21:17:42 +00002076 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands92c43912008-06-06 12:08:01 +00002077 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel8efdca42007-12-04 22:23:35 +00002078
Duncan Sands92c43912008-06-06 12:08:01 +00002079 switch (VT.getSimpleVT()) {
2080 default:
2081 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002082 case MVT::i8: {
2083 prefslot_begin = prefslot_end = 3;
2084 break;
2085 }
2086 case MVT::i16: {
2087 prefslot_begin = 2; prefslot_end = 3;
2088 break;
2089 }
Scott Michel6e2d68b2008-11-10 23:43:06 +00002090 case MVT::i32:
2091 case MVT::f32: {
Scott Michel8efdca42007-12-04 22:23:35 +00002092 prefslot_begin = 0; prefslot_end = 3;
2093 break;
2094 }
Scott Michel6e2d68b2008-11-10 23:43:06 +00002095 case MVT::i64:
2096 case MVT::f64: {
Scott Michel8efdca42007-12-04 22:23:35 +00002097 prefslot_begin = 0; prefslot_end = 7;
2098 break;
2099 }
2100 }
2101
Scott Michel4c07cbd2007-12-19 21:17:42 +00002102 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel5a6f17b2008-01-30 02:55:46 +00002103 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel4c07cbd2007-12-19 21:17:42 +00002104
Scott Michel8efdca42007-12-04 22:23:35 +00002105 for (int i = 0; i < 16; ++i) {
2106 // zero fill uppper part of preferred slot, don't care about the
2107 // other slots:
2108 unsigned int mask_val;
Scott Michel8efdca42007-12-04 22:23:35 +00002109 if (i <= prefslot_end) {
2110 mask_val =
Scott Michel5a6f17b2008-01-30 02:55:46 +00002111 ((i < prefslot_begin)
2112 ? 0x80
2113 : elt_byte + (i - prefslot_begin));
Scott Michel8efdca42007-12-04 22:23:35 +00002114
Scott Michel4c07cbd2007-12-19 21:17:42 +00002115 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel4ec722e2008-07-16 17:17:29 +00002116 } else
Scott Michel8efdca42007-12-04 22:23:35 +00002117 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2118 }
2119
Dan Gohman8181bd12008-07-27 21:46:04 +00002120 SDValue ShufMaskVec =
Scott Michel8efdca42007-12-04 22:23:35 +00002121 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002122 &ShufMask[0],
2123 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel8efdca42007-12-04 22:23:35 +00002124
2125 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002126 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2127 N, N, ShufMaskVec));
Scott Michel4ec722e2008-07-16 17:17:29 +00002128
Scott Michel8efdca42007-12-04 22:23:35 +00002129}
2130
Dan Gohman8181bd12008-07-27 21:46:04 +00002131static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2132 SDValue VecOp = Op.getOperand(0);
2133 SDValue ValOp = Op.getOperand(1);
2134 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002135 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002136
2137 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2138 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2139
Duncan Sands92c43912008-06-06 12:08:01 +00002140 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00002141 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman8181bd12008-07-27 21:46:04 +00002142 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +00002143
Dan Gohman8181bd12008-07-27 21:46:04 +00002144 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002145 DAG.getNode(SPUISD::SHUFB, VT,
2146 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2147 VecOp,
2148 DAG.getNode(SPUISD::INSERT_MASK, VT,
2149 DAG.getNode(ISD::ADD, PtrVT,
2150 PtrBase,
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002151 DAG.getConstant(CN->getZExtValue(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002152 PtrVT))));
Scott Michel8efdca42007-12-04 22:23:35 +00002153
2154 return result;
2155}
2156
Dan Gohman8181bd12008-07-27 21:46:04 +00002157static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002158{
Dan Gohman8181bd12008-07-27 21:46:04 +00002159 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel8efdca42007-12-04 22:23:35 +00002160
2161 assert(Op.getValueType() == MVT::i8);
2162 switch (Opc) {
2163 default:
2164 assert(0 && "Unhandled i8 math operator");
2165 /*NOTREACHED*/
2166 break;
2167 case ISD::SUB: {
2168 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2169 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002170 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002171 N0 = (N0.getOpcode() != ISD::Constant
2172 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002173 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2174 MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00002175 N1 = (N1.getOpcode() != ISD::Constant
2176 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002177 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2178 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002179 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002180 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002181 }
Scott Michel8efdca42007-12-04 22:23:35 +00002182 case ISD::ROTR:
2183 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002184 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002185 unsigned N1Opc;
2186 N0 = (N0.getOpcode() != ISD::Constant
2187 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002188 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2189 MVT::i16));
Duncan Sands7aef60d2008-10-30 19:24:28 +00002190 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greife9f7f582008-08-31 15:37:04 +00002191 ? ISD::ZERO_EXTEND
2192 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002193 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sands7aef60d2008-10-30 19:24:28 +00002194 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002195 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sands7aef60d2008-10-30 19:24:28 +00002196 MVT::i32));
Dan Gohman8181bd12008-07-27 21:46:04 +00002197 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002198 DAG.getNode(ISD::OR, MVT::i16, N0,
2199 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sands7aef60d2008-10-30 19:24:28 +00002200 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002201 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002202 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2203 }
2204 case ISD::SRL:
2205 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002206 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002207 unsigned N1Opc;
2208 N0 = (N0.getOpcode() != ISD::Constant
2209 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002210 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2211 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002212 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2213 ? ISD::ZERO_EXTEND
2214 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002215 N1 = (N1.getOpcode() != ISD::Constant
2216 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002217 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2218 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002219 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002220 DAG.getNode(Opc, MVT::i16, N0, N1));
2221 }
2222 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002223 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002224 unsigned N1Opc;
2225 N0 = (N0.getOpcode() != ISD::Constant
2226 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002227 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2228 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002229 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2230 ? ISD::SIGN_EXTEND
2231 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002232 N1 = (N1.getOpcode() != ISD::Constant
2233 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002234 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2235 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, N0, N1));
2238 }
2239 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002240 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002241 unsigned N1Opc;
2242 N0 = (N0.getOpcode() != ISD::Constant
2243 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002244 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2245 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002246 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002247 N1 = (N1.getOpcode() != ISD::Constant
2248 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002249 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2250 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002251 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002252 DAG.getNode(Opc, MVT::i16, N0, N1));
2253 break;
2254 }
2255 }
2256
Dan Gohman8181bd12008-07-27 21:46:04 +00002257 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002258}
2259
Dan Gohman8181bd12008-07-27 21:46:04 +00002260static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002261{
Duncan Sands92c43912008-06-06 12:08:01 +00002262 MVT VT = Op.getValueType();
2263 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002264
Dan Gohman8181bd12008-07-27 21:46:04 +00002265 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002266
2267 switch (Opc) {
2268 case ISD::ZERO_EXTEND:
2269 case ISD::SIGN_EXTEND:
2270 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002271 MVT Op0VT = Op0.getValueType();
2272 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002273
2274 assert(Op0VT == MVT::i32
2275 && "CellSPU: Zero/sign extending something other than i32");
Scott Michelbc5fbc12008-04-30 00:30:08 +00002276 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michel97872d32008-02-23 18:41:37 +00002277
2278 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2279 ? SPUISD::ROTBYTES_RIGHT_S
2280 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman8181bd12008-07-27 21:46:04 +00002281 SDValue PromoteScalar =
Scott Michel97872d32008-02-23 18:41:37 +00002282 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2283
2284 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2285 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2286 DAG.getNode(NewOpc, Op0VecVT,
2287 PromoteScalar,
2288 DAG.getConstant(4, MVT::i32))));
2289 }
2290
Scott Michel67224b22008-06-02 22:18:03 +00002291 case ISD::ADD: {
2292 // Turn operands into vectors to satisfy type checking (shufb works on
2293 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002294 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002295 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002296 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002297 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002298 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002299
2300 // Create the shuffle mask for "rotating" the borrow up one register slot
2301 // once the borrow is generated.
2302 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2303 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2304 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2305 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2306
Dan Gohman8181bd12008-07-27 21:46:04 +00002307 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002308 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002309 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002310 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2311 CarryGen, CarryGen,
2312 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2313 &ShufBytes[0], ShufBytes.size()));
2314
2315 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2316 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2317 Op0, Op1, ShiftedCarry));
2318 }
2319
2320 case ISD::SUB: {
2321 // Turn operands into vectors to satisfy type checking (shufb works on
2322 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002323 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002324 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002325 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002326 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002327 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002328
2329 // Create the shuffle mask for "rotating" the borrow up one register slot
2330 // once the borrow is generated.
2331 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2332 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2333 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2334 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2335
Dan Gohman8181bd12008-07-27 21:46:04 +00002336 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002337 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002338 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002339 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2340 BorrowGen, BorrowGen,
2341 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2342 &ShufBytes[0], ShufBytes.size()));
2343
2344 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2345 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2346 Op0, Op1, ShiftedBorrow));
2347 }
2348
Scott Michel97872d32008-02-23 18:41:37 +00002349 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002350 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002351 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002352 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2353 SDValue MaskLower =
Scott Michel97872d32008-02-23 18:41:37 +00002354 DAG.getNode(SPUISD::SELB, VecVT,
2355 Op0Vec,
2356 DAG.getConstant(0, VecVT),
Scott Michel67224b22008-06-02 22:18:03 +00002357 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michel97872d32008-02-23 18:41:37 +00002358 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman8181bd12008-07-27 21:46:04 +00002359 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002360 DAG.getNode(ISD::SRL, ShiftAmtVT,
2361 ShiftAmt,
2362 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002363 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002364 DAG.getNode(ISD::AND, ShiftAmtVT,
2365 ShiftAmt,
2366 DAG.getConstant(7, ShiftAmtVT));
2367
2368 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2369 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2370 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2371 MaskLower, ShiftAmtBytes),
2372 ShiftAmtBits));
2373 }
2374
2375 case ISD::SRL: {
Duncan Sands92c43912008-06-06 12:08:01 +00002376 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002377 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002378 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002379 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002380 DAG.getNode(ISD::SRL, ShiftAmtVT,
2381 ShiftAmt,
2382 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002383 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002384 DAG.getNode(ISD::AND, ShiftAmtVT,
2385 ShiftAmt,
2386 DAG.getConstant(7, ShiftAmtVT));
2387
2388 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2389 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2390 Op0, ShiftAmtBytes),
2391 ShiftAmtBits);
2392 }
Scott Michel67224b22008-06-02 22:18:03 +00002393
2394 case ISD::SRA: {
2395 // Promote Op0 to vector
Dan Gohman8181bd12008-07-27 21:46:04 +00002396 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002397 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002398 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002399 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel67224b22008-06-02 22:18:03 +00002400
2401 // Negate variable shift amounts
2402 if (!isa<ConstantSDNode>(ShiftAmt)) {
2403 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2404 DAG.getConstant(0, ShiftVT), ShiftAmt);
2405 }
2406
Dan Gohman8181bd12008-07-27 21:46:04 +00002407 SDValue UpperHalfSign =
Scott Michel67224b22008-06-02 22:18:03 +00002408 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2409 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2410 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2411 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman8181bd12008-07-27 21:46:04 +00002412 SDValue UpperHalfSignMask =
Scott Michel67224b22008-06-02 22:18:03 +00002413 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman8181bd12008-07-27 21:46:04 +00002414 SDValue UpperLowerMask =
Scott Michel67224b22008-06-02 22:18:03 +00002415 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2416 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman8181bd12008-07-27 21:46:04 +00002417 SDValue UpperLowerSelect =
Scott Michel67224b22008-06-02 22:18:03 +00002418 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2419 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman8181bd12008-07-27 21:46:04 +00002420 SDValue RotateLeftBytes =
Scott Michel67224b22008-06-02 22:18:03 +00002421 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2422 UpperLowerSelect, ShiftAmt);
Dan Gohman8181bd12008-07-27 21:46:04 +00002423 SDValue RotateLeftBits =
Scott Michel67224b22008-06-02 22:18:03 +00002424 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2425 RotateLeftBytes, ShiftAmt);
2426
2427 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2428 RotateLeftBits);
2429 }
Scott Michel97872d32008-02-23 18:41:37 +00002430 }
2431
Dan Gohman8181bd12008-07-27 21:46:04 +00002432 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002433}
2434
Scott Michel8efdca42007-12-04 22:23:35 +00002435//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002436static SDValue
2437LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2438 SDValue ConstVec;
2439 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002440 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002441
2442 ConstVec = Op.getOperand(0);
2443 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002444 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2445 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002446 ConstVec = ConstVec.getOperand(0);
2447 } else {
2448 ConstVec = Op.getOperand(1);
2449 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002450 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002451 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002452 }
2453 }
2454 }
2455
Gabor Greif1c80d112008-08-28 21:40:38 +00002456 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002457 uint64_t VectorBits[2];
2458 uint64_t UndefBits[2];
2459 uint64_t SplatBits, SplatUndef;
2460 int SplatSize;
2461
Gabor Greif1c80d112008-08-28 21:40:38 +00002462 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002463 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002464 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002465 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002466 SDValue tcVec[16];
2467 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002468 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2469
2470 // Turn the BUILD_VECTOR into a set of target constants:
2471 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002472 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002473
Gabor Greif1c80d112008-08-28 21:40:38 +00002474 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002475 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002476 }
2477 }
Nate Begeman7569e762008-07-29 19:07:27 +00002478 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2479 // lowered. Return the operation, rather than a null SDValue.
2480 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002481}
2482
2483//! Lower i32 multiplication
Dan Gohman8181bd12008-07-27 21:46:04 +00002484static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel8efdca42007-12-04 22:23:35 +00002485 unsigned Opc) {
Duncan Sands92c43912008-06-06 12:08:01 +00002486 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00002487 default:
2488 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands92c43912008-06-06 12:08:01 +00002489 << Op.getValueType().getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +00002490 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +00002491 abort();
2492 /*NOTREACHED*/
2493
2494 case MVT::i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002495 SDValue rA = Op.getOperand(0);
2496 SDValue rB = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002497
2498 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002499 DAG.getNode(ISD::ADD, MVT::i32,
2500 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2501 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2502 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00002503 }
2504 }
2505
Dan Gohman8181bd12008-07-27 21:46:04 +00002506 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002507}
2508
2509//! Custom lowering for CTPOP (count population)
2510/*!
2511 Custom lowering code that counts the number ones in the input
2512 operand. SPU has such an instruction, but it counts the number of
2513 ones per byte, which then have to be accumulated.
2514*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002515static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002516 MVT VT = Op.getValueType();
2517 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002518
Duncan Sands92c43912008-06-06 12:08:01 +00002519 switch (VT.getSimpleVT()) {
2520 default:
2521 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002522 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002523 SDValue N = Op.getOperand(0);
2524 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002525
Dan Gohman8181bd12008-07-27 21:46:04 +00002526 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2527 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002528
2529 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2530 }
2531
2532 case MVT::i16: {
2533 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002534 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002535
Chris Lattner1b989192007-12-31 04:13:23 +00002536 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002537
Dan Gohman8181bd12008-07-27 21:46:04 +00002538 SDValue N = Op.getOperand(0);
2539 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2540 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sands7aef60d2008-10-30 19:24:28 +00002541 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002542
Dan Gohman8181bd12008-07-27 21:46:04 +00002543 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2544 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002545
2546 // CNTB_result becomes the chain to which all of the virtual registers
2547 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002548 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002549 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002550
Dan Gohman8181bd12008-07-27 21:46:04 +00002551 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002552 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2553
Dan Gohman8181bd12008-07-27 21:46:04 +00002554 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002555
2556 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002557 DAG.getNode(ISD::ADD, MVT::i16,
2558 DAG.getNode(ISD::SRL, MVT::i16,
2559 Tmp1, Shift1),
2560 Tmp1),
2561 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002562 }
2563
2564 case MVT::i32: {
2565 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002566 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002567
Chris Lattner1b989192007-12-31 04:13:23 +00002568 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2569 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002570
Dan Gohman8181bd12008-07-27 21:46:04 +00002571 SDValue N = Op.getOperand(0);
2572 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2573 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2574 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2575 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002576
Dan Gohman8181bd12008-07-27 21:46:04 +00002577 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2578 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002579
2580 // CNTB_result becomes the chain to which all of the virtual registers
2581 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002582 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002583 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002584
Dan Gohman8181bd12008-07-27 21:46:04 +00002585 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002586 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2587
Dan Gohman8181bd12008-07-27 21:46:04 +00002588 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002589 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002590 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002591
Dan Gohman8181bd12008-07-27 21:46:04 +00002592 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002593 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002594 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002595
Dan Gohman8181bd12008-07-27 21:46:04 +00002596 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002597 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2598
Dan Gohman8181bd12008-07-27 21:46:04 +00002599 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002600 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002601 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2602 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002603 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002604 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002605 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002606
2607 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2608 }
2609
2610 case MVT::i64:
2611 break;
2612 }
2613
Dan Gohman8181bd12008-07-27 21:46:04 +00002614 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002615}
2616
2617/// LowerOperation - Provide custom lowering hooks for some operations.
2618///
Dan Gohman8181bd12008-07-27 21:46:04 +00002619SDValue
2620SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel8efdca42007-12-04 22:23:35 +00002621{
Scott Michel97872d32008-02-23 18:41:37 +00002622 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands92c43912008-06-06 12:08:01 +00002623 MVT VT = Op.getValueType();
Scott Michel97872d32008-02-23 18:41:37 +00002624
2625 switch (Opc) {
Scott Michel8efdca42007-12-04 22:23:35 +00002626 default: {
2627 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michel97872d32008-02-23 18:41:37 +00002628 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greif1c80d112008-08-28 21:40:38 +00002629 cerr << "*Op.getNode():\n";
2630 Op.getNode()->dump();
Scott Michel8efdca42007-12-04 22:23:35 +00002631 abort();
2632 }
2633 case ISD::LOAD:
2634 case ISD::SEXTLOAD:
2635 case ISD::ZEXTLOAD:
2636 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2637 case ISD::STORE:
2638 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2639 case ISD::ConstantPool:
2640 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2641 case ISD::GlobalAddress:
2642 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2643 case ISD::JumpTable:
2644 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2645 case ISD::Constant:
2646 return LowerConstant(Op, DAG);
2647 case ISD::ConstantFP:
2648 return LowerConstantFP(Op, DAG);
Scott Michel394e26d2008-01-17 20:38:41 +00002649 case ISD::BRCOND:
2650 return LowerBRCOND(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002651 case ISD::FORMAL_ARGUMENTS:
Scott Michel394e26d2008-01-17 20:38:41 +00002652 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel8efdca42007-12-04 22:23:35 +00002653 case ISD::CALL:
Scott Micheldbac4cf2008-01-11 02:53:15 +00002654 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel8efdca42007-12-04 22:23:35 +00002655 case ISD::RET:
2656 return LowerRET(Op, DAG, getTargetMachine());
2657
Scott Michel97872d32008-02-23 18:41:37 +00002658
2659 // i8, i64 math ops:
2660 case ISD::ZERO_EXTEND:
2661 case ISD::SIGN_EXTEND:
2662 case ISD::ANY_EXTEND:
Scott Michel67224b22008-06-02 22:18:03 +00002663 case ISD::ADD:
Scott Michel8efdca42007-12-04 22:23:35 +00002664 case ISD::SUB:
2665 case ISD::ROTR:
2666 case ISD::ROTL:
2667 case ISD::SRL:
2668 case ISD::SHL:
Scott Michel67224b22008-06-02 22:18:03 +00002669 case ISD::SRA: {
Scott Michel97872d32008-02-23 18:41:37 +00002670 if (VT == MVT::i8)
2671 return LowerI8Math(Op, DAG, Opc);
2672 else if (VT == MVT::i64)
2673 return LowerI64Math(Op, DAG, Opc);
2674 break;
Scott Michel67224b22008-06-02 22:18:03 +00002675 }
Scott Michel8efdca42007-12-04 22:23:35 +00002676
2677 // Vector-related lowering.
2678 case ISD::BUILD_VECTOR:
2679 return LowerBUILD_VECTOR(Op, DAG);
2680 case ISD::SCALAR_TO_VECTOR:
2681 return LowerSCALAR_TO_VECTOR(Op, DAG);
2682 case ISD::VECTOR_SHUFFLE:
2683 return LowerVECTOR_SHUFFLE(Op, DAG);
2684 case ISD::EXTRACT_VECTOR_ELT:
2685 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2686 case ISD::INSERT_VECTOR_ELT:
2687 return LowerINSERT_VECTOR_ELT(Op, DAG);
2688
2689 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2690 case ISD::AND:
2691 case ISD::OR:
2692 case ISD::XOR:
2693 return LowerByteImmed(Op, DAG);
2694
2695 // Vector and i8 multiply:
2696 case ISD::MUL:
Duncan Sands92c43912008-06-06 12:08:01 +00002697 if (VT.isVector())
Scott Michel8efdca42007-12-04 22:23:35 +00002698 return LowerVectorMUL(Op, DAG);
Scott Michel97872d32008-02-23 18:41:37 +00002699 else if (VT == MVT::i8)
2700 return LowerI8Math(Op, DAG, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002701 else
Scott Michel97872d32008-02-23 18:41:37 +00002702 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002703
2704 case ISD::FDIV:
Scott Michel97872d32008-02-23 18:41:37 +00002705 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel8efdca42007-12-04 22:23:35 +00002706 return LowerFDIVf32(Op, DAG);
2707// else if (Op.getValueType() == MVT::f64)
2708// return LowerFDIVf64(Op, DAG);
2709 else
2710 assert(0 && "Calling FDIV on unsupported MVT");
2711
2712 case ISD::CTPOP:
2713 return LowerCTPOP(Op, DAG);
2714 }
2715
Dan Gohman8181bd12008-07-27 21:46:04 +00002716 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002717}
2718
Scott Michel6e2d68b2008-11-10 23:43:06 +00002719SDNode *SPUTargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG)
2720{
2721#if 0
2722 unsigned Opc = (unsigned) N->getOpcode();
2723 MVT OpVT = N->getValueType(0);
2724
2725 switch (Opc) {
2726 default: {
2727 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2728 cerr << "Op.getOpcode() = " << Opc << "\n";
2729 cerr << "*Op.getNode():\n";
2730 N->dump();
2731 abort();
2732 /*NOTREACHED*/
2733 }
2734 }
2735#endif
2736
2737 /* Otherwise, return unchanged */
2738 return 0;
2739}
2740
Scott Michel8efdca42007-12-04 22:23:35 +00002741//===----------------------------------------------------------------------===//
Scott Michel8efdca42007-12-04 22:23:35 +00002742// Target Optimization Hooks
2743//===----------------------------------------------------------------------===//
2744
Dan Gohman8181bd12008-07-27 21:46:04 +00002745SDValue
Scott Michel8efdca42007-12-04 22:23:35 +00002746SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2747{
2748#if 0
2749 TargetMachine &TM = getTargetMachine();
Scott Michelf9f42e62008-01-29 02:16:57 +00002750#endif
2751 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel8efdca42007-12-04 22:23:35 +00002752 SelectionDAG &DAG = DCI.DAG;
Dan Gohman8181bd12008-07-27 21:46:04 +00002753 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2754 SDValue Result; // Initially, NULL result
Scott Michel8efdca42007-12-04 22:23:35 +00002755
2756 switch (N->getOpcode()) {
2757 default: break;
Scott Michelf9f42e62008-01-29 02:16:57 +00002758 case ISD::ADD: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002759 SDValue Op1 = N->getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002760
Scott Michel67224b22008-06-02 22:18:03 +00002761 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002762 SDValue Op01 = Op0.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002763 if (Op01.getOpcode() == ISD::Constant
2764 || Op01.getOpcode() == ISD::TargetConstant) {
2765 // (add <const>, (SPUindirect <arg>, <const>)) ->
2766 // (SPUindirect <arg>, <const + const>)
2767 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2768 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman8181bd12008-07-27 21:46:04 +00002769 SDValue combinedConst =
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002770 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michelf9f42e62008-01-29 02:16:57 +00002771 Op0.getValueType());
2772
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002773 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2774 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002775 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002776 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002777 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2778 Op0.getOperand(0), combinedConst);
2779 }
Scott Michel67224b22008-06-02 22:18:03 +00002780 } else if (isa<ConstantSDNode>(Op0)
Scott Michelf9f42e62008-01-29 02:16:57 +00002781 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002782 SDValue Op11 = Op1.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002783 if (Op11.getOpcode() == ISD::Constant
2784 || Op11.getOpcode() == ISD::TargetConstant) {
2785 // (add (SPUindirect <arg>, <const>), <const>) ->
2786 // (SPUindirect <arg>, <const + const>)
2787 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2788 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman8181bd12008-07-27 21:46:04 +00002789 SDValue combinedConst =
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002790 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michelf9f42e62008-01-29 02:16:57 +00002791 Op0.getValueType());
2792
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002793 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2794 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002795 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002796 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002797
2798 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2799 Op1.getOperand(0), combinedConst);
2800 }
2801 }
Scott Michel97872d32008-02-23 18:41:37 +00002802 break;
2803 }
2804 case ISD::SIGN_EXTEND:
2805 case ISD::ZERO_EXTEND:
2806 case ISD::ANY_EXTEND: {
2807 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2808 N->getValueType(0) == Op0.getValueType()) {
2809 // (any_extend (SPUextract_elt0 <arg>)) ->
2810 // (SPUextract_elt0 <arg>)
2811 // Types must match, however...
2812 DEBUG(cerr << "Replace: ");
2813 DEBUG(N->dump(&DAG));
2814 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002815 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002816 DEBUG(cerr << "\n");
2817
2818 return Op0;
2819 }
2820 break;
2821 }
2822 case SPUISD::IndirectAddr: {
2823 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2824 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002825 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00002826 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2827 // (SPUaform <addr>, 0)
2828
2829 DEBUG(cerr << "Replace: ");
2830 DEBUG(N->dump(&DAG));
2831 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002832 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002833 DEBUG(cerr << "\n");
2834
2835 return Op0;
2836 }
2837 }
2838 break;
2839 }
2840 case SPUISD::SHLQUAD_L_BITS:
2841 case SPUISD::SHLQUAD_L_BYTES:
2842 case SPUISD::VEC_SHL:
2843 case SPUISD::VEC_SRL:
2844 case SPUISD::VEC_SRA:
2845 case SPUISD::ROTQUAD_RZ_BYTES:
2846 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002847 SDValue Op1 = N->getOperand(1);
Scott Michel97872d32008-02-23 18:41:37 +00002848
2849 if (isa<ConstantSDNode>(Op1)) {
2850 // Kill degenerate vector shifts:
2851 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2852
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002853 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00002854 Result = Op0;
2855 }
2856 }
2857 break;
2858 }
2859 case SPUISD::PROMOTE_SCALAR: {
2860 switch (Op0.getOpcode()) {
2861 default:
2862 break;
2863 case ISD::ANY_EXTEND:
2864 case ISD::ZERO_EXTEND:
2865 case ISD::SIGN_EXTEND: {
2866 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2867 // <arg>
2868 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman8181bd12008-07-27 21:46:04 +00002869 SDValue Op00 = Op0.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002870 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002871 SDValue Op000 = Op00.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002872 if (Op000.getValueType() == N->getValueType(0)) {
2873 Result = Op000;
2874 }
2875 }
2876 break;
2877 }
2878 case SPUISD::EXTRACT_ELT0: {
2879 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2880 // <arg>
2881 Result = Op0.getOperand(0);
2882 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00002883 }
Scott Michel97872d32008-02-23 18:41:37 +00002884 }
2885 break;
Scott Michelf9f42e62008-01-29 02:16:57 +00002886 }
2887 }
Scott Michel394e26d2008-01-17 20:38:41 +00002888 // Otherwise, return unchanged.
Scott Michel33d73eb2008-11-21 02:56:16 +00002889#ifdef NDEBUG
Gabor Greif1c80d112008-08-28 21:40:38 +00002890 if (Result.getNode()) {
Scott Michel97872d32008-02-23 18:41:37 +00002891 DEBUG(cerr << "\nReplace.SPU: ");
2892 DEBUG(N->dump(&DAG));
2893 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002894 DEBUG(Result.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002895 DEBUG(cerr << "\n");
2896 }
2897#endif
2898
2899 return Result;
Scott Michel8efdca42007-12-04 22:23:35 +00002900}
2901
2902//===----------------------------------------------------------------------===//
2903// Inline Assembly Support
2904//===----------------------------------------------------------------------===//
2905
2906/// getConstraintType - Given a constraint letter, return the type of
2907/// constraint it is for this target.
Scott Michel4ec722e2008-07-16 17:17:29 +00002908SPUTargetLowering::ConstraintType
Scott Michel8efdca42007-12-04 22:23:35 +00002909SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2910 if (ConstraintLetter.size() == 1) {
2911 switch (ConstraintLetter[0]) {
2912 default: break;
2913 case 'b':
2914 case 'r':
2915 case 'f':
2916 case 'v':
2917 case 'y':
2918 return C_RegisterClass;
Scott Michel4ec722e2008-07-16 17:17:29 +00002919 }
Scott Michel8efdca42007-12-04 22:23:35 +00002920 }
2921 return TargetLowering::getConstraintType(ConstraintLetter);
2922}
2923
Scott Michel4ec722e2008-07-16 17:17:29 +00002924std::pair<unsigned, const TargetRegisterClass*>
Scott Michel8efdca42007-12-04 22:23:35 +00002925SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands92c43912008-06-06 12:08:01 +00002926 MVT VT) const
Scott Michel8efdca42007-12-04 22:23:35 +00002927{
2928 if (Constraint.size() == 1) {
2929 // GCC RS6000 Constraint Letters
2930 switch (Constraint[0]) {
2931 case 'b': // R1-R31
2932 case 'r': // R0-R31
2933 if (VT == MVT::i64)
2934 return std::make_pair(0U, SPU::R64CRegisterClass);
2935 return std::make_pair(0U, SPU::R32CRegisterClass);
2936 case 'f':
2937 if (VT == MVT::f32)
2938 return std::make_pair(0U, SPU::R32FPRegisterClass);
2939 else if (VT == MVT::f64)
2940 return std::make_pair(0U, SPU::R64FPRegisterClass);
2941 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00002942 case 'v':
Scott Michel8efdca42007-12-04 22:23:35 +00002943 return std::make_pair(0U, SPU::GPRCRegisterClass);
2944 }
2945 }
Scott Michel4ec722e2008-07-16 17:17:29 +00002946
Scott Michel8efdca42007-12-04 22:23:35 +00002947 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2948}
2949
Scott Michel97872d32008-02-23 18:41:37 +00002950//! Compute used/known bits for a SPU operand
Scott Michel8efdca42007-12-04 22:23:35 +00002951void
Dan Gohman8181bd12008-07-27 21:46:04 +00002952SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohmand0dfc772008-02-13 22:28:48 +00002953 const APInt &Mask,
Scott Michel4ec722e2008-07-16 17:17:29 +00002954 APInt &KnownZero,
Dan Gohman229fa052008-02-13 00:35:47 +00002955 APInt &KnownOne,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002956 const SelectionDAG &DAG,
2957 unsigned Depth ) const {
Scott Michelbc5fbc12008-04-30 00:30:08 +00002958#if 0
Scott Michel97872d32008-02-23 18:41:37 +00002959 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michelbc5fbc12008-04-30 00:30:08 +00002960#endif
Scott Michel97872d32008-02-23 18:41:37 +00002961
2962 switch (Op.getOpcode()) {
2963 default:
2964 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2965 break;
2966
2967#if 0
2968 case CALL:
2969 case SHUFB:
2970 case INSERT_MASK:
2971 case CNTB:
2972#endif
2973
2974 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002975 SDValue Op0 = Op.getOperand(0);
Duncan Sands92c43912008-06-06 12:08:01 +00002976 MVT Op0VT = Op0.getValueType();
2977 unsigned Op0VTBits = Op0VT.getSizeInBits();
2978 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00002979 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2980 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00002981 break;
2982 }
Scott Michel4ec722e2008-07-16 17:17:29 +00002983
Scott Michel97872d32008-02-23 18:41:37 +00002984 case SPUISD::LDRESULT:
2985 case SPUISD::EXTRACT_ELT0:
2986 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands92c43912008-06-06 12:08:01 +00002987 MVT OpVT = Op.getValueType();
2988 unsigned OpVTBits = OpVT.getSizeInBits();
2989 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00002990 KnownZero |= APInt(OpVTBits, ~InMask, false);
2991 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00002992 break;
2993 }
2994
2995#if 0
2996 case EXTRACT_I1_ZEXT:
2997 case EXTRACT_I1_SEXT:
2998 case EXTRACT_I8_ZEXT:
2999 case EXTRACT_I8_SEXT:
3000 case MPY:
3001 case MPYU:
3002 case MPYH:
3003 case MPYHH:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003004 case SPUISD::SHLQUAD_L_BITS:
3005 case SPUISD::SHLQUAD_L_BYTES:
3006 case SPUISD::VEC_SHL:
3007 case SPUISD::VEC_SRL:
3008 case SPUISD::VEC_SRA:
3009 case SPUISD::VEC_ROTL:
3010 case SPUISD::VEC_ROTR:
3011 case SPUISD::ROTQUAD_RZ_BYTES:
3012 case SPUISD::ROTQUAD_RZ_BITS:
3013 case SPUISD::ROTBYTES_RIGHT_S:
3014 case SPUISD::ROTBYTES_LEFT:
3015 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel67224b22008-06-02 22:18:03 +00003016 case SPUISD::SELECT_MASK:
3017 case SPUISD::SELB:
3018 case SPUISD::FPInterp:
3019 case SPUISD::FPRecipEst:
3020 case SPUISD::SEXT32TO64:
Scott Michel97872d32008-02-23 18:41:37 +00003021#endif
3022 }
Scott Michel8efdca42007-12-04 22:23:35 +00003023}
3024
Scott Michelbc5fbc12008-04-30 00:30:08 +00003025// LowerAsmOperandForConstraint
3026void
Dan Gohman8181bd12008-07-27 21:46:04 +00003027SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003028 char ConstraintLetter,
Evan Cheng7f250d62008-09-24 00:05:32 +00003029 bool hasMemory,
Dan Gohman8181bd12008-07-27 21:46:04 +00003030 std::vector<SDValue> &Ops,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003031 SelectionDAG &DAG) const {
3032 // Default, for the time being, to the base class handler
Evan Cheng7f250d62008-09-24 00:05:32 +00003033 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3034 Ops, DAG);
Scott Michelbc5fbc12008-04-30 00:30:08 +00003035}
3036
Scott Michel8efdca42007-12-04 22:23:35 +00003037/// isLegalAddressImmediate - Return true if the integer value can be used
3038/// as the offset of the target addressing mode.
Gabor Greife9f7f582008-08-31 15:37:04 +00003039bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3040 const Type *Ty) const {
Scott Michel8efdca42007-12-04 22:23:35 +00003041 // SPU's addresses are 256K:
3042 return (V > -(1 << 18) && V < (1 << 18) - 1);
3043}
3044
3045bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel4ec722e2008-07-16 17:17:29 +00003046 return false;
Scott Michel8efdca42007-12-04 22:23:35 +00003047}
Dan Gohman36322c72008-10-18 02:06:02 +00003048
3049bool
3050SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3051 // The SPU target isn't yet aware of offsets.
3052 return false;
3053}