blob: 222c0d6145a9b1c2cbd34cd423af4ac4baea7d6b [file] [log] [blame]
Scott Michel8efdca42007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner081ce942007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel8efdca42007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SPUTargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPURegisterNames.h"
15#include "SPUISelLowering.h"
16#include "SPUTargetMachine.h"
Scott Michelbc5fbc12008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michel8efdca42007-12-04 22:23:35 +000018#include "llvm/ADT/VectorExtras.h"
Scott Michel8efdca42007-12-04 22:23:35 +000019#include "llvm/CodeGen/CallingConvLower.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner1b989192007-12-31 04:13:23 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel8efdca42007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel8efdca42007-12-04 22:23:35 +000025#include "llvm/Constants.h"
26#include "llvm/Function.h"
27#include "llvm/Intrinsics.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/MathExtras.h"
30#include "llvm/Target/TargetOptions.h"
31
32#include <map>
33
34using namespace llvm;
35
36// Used in getTargetNodeName() below
37namespace {
38 std::map<unsigned, const char *> node_names;
39
Duncan Sands92c43912008-06-06 12:08:01 +000040 //! MVT mapping to useful data for Cell SPU
Scott Michel8efdca42007-12-04 22:23:35 +000041 struct valtype_map_s {
Scott Michel56a125e2008-11-22 23:50:42 +000042 const MVT valtype;
43 const int prefslot_byte;
Scott Michel8efdca42007-12-04 22:23:35 +000044 };
Scott Michel4ec722e2008-07-16 17:17:29 +000045
Scott Michel8efdca42007-12-04 22:23:35 +000046 const valtype_map_s valtype_map[] = {
47 { MVT::i1, 3 },
48 { MVT::i8, 3 },
49 { MVT::i16, 2 },
50 { MVT::i32, 0 },
51 { MVT::f32, 0 },
52 { MVT::i64, 0 },
53 { MVT::f64, 0 },
54 { MVT::i128, 0 }
55 };
56
57 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
58
Duncan Sands92c43912008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel8efdca42007-12-04 22:23:35 +000060 const valtype_map_s *retval = 0;
61
62 for (size_t i = 0; i < n_valtype_map; ++i) {
63 if (valtype_map[i].valtype == VT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel8efdca42007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands92c43912008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +000074 abort();
75 }
76#endif
77
78 return retval;
79 }
80
81 //! Predicate that returns true if operand is a memory target
82 /*!
83 \arg Op Operand to test
84 \return true if the operand is a memory target (i.e., global
Scott Micheldbac4cf2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel8efdca42007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman8181bd12008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel8efdca42007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel8efdca42007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
Bill Wendlingfef06052008-09-16 21:48:12 +000095 || Opc == ISD::ExternalSymbol
Scott Michel8efdca42007-12-04 22:23:35 +000096 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel8efdca42007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
Bill Wendlingfef06052008-09-16 21:48:12 +0000100 || Opc == ISD::TargetExternalSymbol
Scott Micheldbac4cf2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel8efdca42007-12-04 22:23:35 +0000102 }
Scott Michel394e26d2008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman8181bd12008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel394e26d2008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel5a6f17b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel394e26d2008-01-17 20:38:41 +0000110 }
Scott Michel8efdca42007-12-04 22:23:35 +0000111}
112
113SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
114 : TargetLowering(TM),
115 SPUTM(TM)
116{
117 // Fold away setcc operations if possible.
118 setPow2DivIsCheap();
119
120 // Use _setjmp/_longjmp instead of setjmp/longjmp.
121 setUseUnderscoreSetJmp(true);
122 setUseUnderscoreLongJmp(true);
Scott Michel4ec722e2008-07-16 17:17:29 +0000123
Scott Michel8efdca42007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel438be252007-12-17 22:32:34 +0000125 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
126 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
127 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
128 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
129 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
130 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel8efdca42007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel4ec722e2008-07-16 17:17:29 +0000132
Scott Michelabb8ca12008-11-20 16:36:33 +0000133 // Initialize libcalls:
134 setLibcallName(RTLIB::MUL_I64, "__muldi3");
135
Scott Michel8efdca42007-12-04 22:23:35 +0000136 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng08c171a2008-10-14 21:26:46 +0000137 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
138 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
139 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +0000140
Evan Cheng08c171a2008-10-14 21:26:46 +0000141 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
142 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
143 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Scott Michel55252632008-11-20 04:26:21 +0000144 setTruncStoreAction(MVT::i8, MVT::i8, Custom);
145 setTruncStoreAction(MVT::i16, MVT::i8, Custom);
146 setTruncStoreAction(MVT::i32, MVT::i8, Custom);
147 setTruncStoreAction(MVT::i64, MVT::i8, Custom);
148 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000149
Evan Cheng08c171a2008-10-14 21:26:46 +0000150 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
151 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
152 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000153
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 Michel56a125e2008-11-22 23:50:42 +0000174
175 // Custom lower SELECT_CC for most cases, but expand by default
Scott Michel4ec722e2008-07-16 17:17:29 +0000176 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel56a125e2008-11-22 23:50:42 +0000177 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
178 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
179 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
Scott Michelfa888632008-11-25 00:23:16 +0000180#if 0
Scott Michel56a125e2008-11-22 23:50:42 +0000181 setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
Scott Michelfa888632008-11-25 00:23:16 +0000182#endif
Scott Michel8efdca42007-12-04 22:23:35 +0000183
184 // SPU has no intrinsics for these particular operations:
Andrew Lenharth0531ec52008-02-16 14:46:26 +0000185 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
186
Scott Michel8efdca42007-12-04 22:23:35 +0000187 // PowerPC has no SREM/UREM instructions
188 setOperationAction(ISD::SREM, MVT::i32, Expand);
189 setOperationAction(ISD::UREM, MVT::i32, Expand);
190 setOperationAction(ISD::SREM, MVT::i64, Expand);
191 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000192
Scott Michel8efdca42007-12-04 22:23:35 +0000193 // We don't support sin/cos/sqrt/fmod
194 setOperationAction(ISD::FSIN , MVT::f64, Expand);
195 setOperationAction(ISD::FCOS , MVT::f64, Expand);
196 setOperationAction(ISD::FREM , MVT::f64, Expand);
197 setOperationAction(ISD::FSIN , MVT::f32, Expand);
198 setOperationAction(ISD::FCOS , MVT::f32, Expand);
199 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000200
Scott Michel8efdca42007-12-04 22:23:35 +0000201 // If we're enabling GP optimizations, use hardware square root
202 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
203 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000204
Scott Michel8efdca42007-12-04 22:23:35 +0000205 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
206 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
207
208 // SPU can do rotate right and left, so legalize it... but customize for i8
209 // because instructions don't exist.
Bill Wendling965299c2008-08-31 02:59:23 +0000210
211 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
212 // .td files.
213 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
214 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
215 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
216
Scott Michel8efdca42007-12-04 22:23:35 +0000217 setOperationAction(ISD::ROTL, MVT::i32, Legal);
218 setOperationAction(ISD::ROTL, MVT::i16, Legal);
219 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Michelabb8ca12008-11-20 16:36:33 +0000220
Scott Michel8efdca42007-12-04 22:23:35 +0000221 // SPU has no native version of shift left/right for i8
222 setOperationAction(ISD::SHL, MVT::i8, Custom);
223 setOperationAction(ISD::SRL, MVT::i8, Custom);
224 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000225
226 // SPU needs custom lowering for shift left/right for i64
Scott Michel97872d32008-02-23 18:41:37 +0000227 setOperationAction(ISD::SHL, MVT::i64, Custom);
228 setOperationAction(ISD::SRL, MVT::i64, Custom);
229 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000230
Scott Michel4ec722e2008-07-16 17:17:29 +0000231 // Custom lower i8, i32 and i64 multiplications
232 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000233 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel33d73eb2008-11-21 02:56:16 +0000234 setOperationAction(ISD::MUL, MVT::i64, Expand); // libcall
235
236 // SMUL_LOHI, UMUL_LOHI
237 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
238 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
239 setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom);
240 setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000241
Scott Michel67224b22008-06-02 22:18:03 +0000242 // Need to custom handle (some) common i8, i64 math ops
243 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000244 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel67224b22008-06-02 22:18:03 +0000245 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000246
Scott Michel8efdca42007-12-04 22:23:35 +0000247 // SPU does not have BSWAP. It does have i32 support CTLZ.
248 // CTPOP has to be custom lowered.
249 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
250 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
251
252 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
253 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
254 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
255 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
256
257 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
258 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
259
260 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000261
Scott Michel67224b22008-06-02 22:18:03 +0000262 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel978b96f2008-03-10 23:49:09 +0000263 // select ought to work:
Scott Michel53ab7792008-03-10 16:58:52 +0000264 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michel6baba072008-03-05 23:02:02 +0000265 setOperationAction(ISD::SELECT, MVT::i16, Legal);
266 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000267 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000268
Scott Michel53ab7792008-03-10 16:58:52 +0000269 setOperationAction(ISD::SETCC, MVT::i8, Legal);
270 setOperationAction(ISD::SETCC, MVT::i16, Legal);
271 setOperationAction(ISD::SETCC, MVT::i32, Legal);
272 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michel6baba072008-03-05 23:02:02 +0000273
Scott Michel97872d32008-02-23 18:41:37 +0000274 // Zero extension and sign extension for i64 have to be
275 // custom legalized
276 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
277 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
278 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000279
Scott Michel8efdca42007-12-04 22:23:35 +0000280 // SPU has a legal FP -> signed INT instruction
281 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
282 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
283 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
284 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
285
286 // FDIV on SPU requires custom lowering
287 setOperationAction(ISD::FDIV, MVT::f32, Custom);
288 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
289
290 // SPU has [U|S]INT_TO_FP
291 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
292 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
293 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
294 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
295 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
296 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
297 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
298 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
299
Scott Michel754d8662007-12-20 00:44:13 +0000300 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
301 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
302 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
303 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel8efdca42007-12-04 22:23:35 +0000304
305 // We cannot sextinreg(i1). Expand to shifts.
306 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000307
Scott Michel8efdca42007-12-04 22:23:35 +0000308 // Support label based line numbers.
Dan Gohman472d12c2008-06-30 20:59:49 +0000309 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000310 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000311
312 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel8efdca42007-12-04 22:23:35 +0000313 // appropriate instructions to materialize the address.
Scott Michel33d73eb2008-11-21 02:56:16 +0000314 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michelf9f42e62008-01-29 02:16:57 +0000315 ++sctype) {
Duncan Sands92c43912008-06-06 12:08:01 +0000316 MVT VT = (MVT::SimpleValueType)sctype;
317
318 setOperationAction(ISD::GlobalAddress, VT, Custom);
319 setOperationAction(ISD::ConstantPool, VT, Custom);
320 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michelf9f42e62008-01-29 02:16:57 +0000321 }
Scott Michel8efdca42007-12-04 22:23:35 +0000322
323 // RET must be custom lowered, to meet ABI requirements
324 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000325
Scott Michel8efdca42007-12-04 22:23:35 +0000326 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
327 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000328
Scott Michel8efdca42007-12-04 22:23:35 +0000329 // Use the default implementation.
330 setOperationAction(ISD::VAARG , MVT::Other, Expand);
331 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
332 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel4ec722e2008-07-16 17:17:29 +0000333 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel8efdca42007-12-04 22:23:35 +0000334 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
335 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
336 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
337
338 // Cell SPU has instructions for converting between i64 and fp.
339 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
340 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel4ec722e2008-07-16 17:17:29 +0000341
Scott Michel8efdca42007-12-04 22:23:35 +0000342 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
343 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
344
345 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
346 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
347
348 // First set operation action for all vector types to expand. Then we
349 // will selectively turn on ones that can be effectively codegen'd.
350 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
351 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
352 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
353 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
354 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
355 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
356
Duncan Sands92c43912008-06-06 12:08:01 +0000357 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
358 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
359 MVT VT = (MVT::SimpleValueType)i;
Scott Michel8efdca42007-12-04 22:23:35 +0000360
Duncan Sands92c43912008-06-06 12:08:01 +0000361 // add/sub are legal for all supported vector VT's.
362 setOperationAction(ISD::ADD , VT, Legal);
363 setOperationAction(ISD::SUB , VT, Legal);
364 // mul has to be custom lowered.
365 setOperationAction(ISD::MUL , VT, Custom);
366
367 setOperationAction(ISD::AND , VT, Legal);
368 setOperationAction(ISD::OR , VT, Legal);
369 setOperationAction(ISD::XOR , VT, Legal);
370 setOperationAction(ISD::LOAD , VT, Legal);
371 setOperationAction(ISD::SELECT, VT, Legal);
372 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel4ec722e2008-07-16 17:17:29 +0000373
Scott Michel8efdca42007-12-04 22:23:35 +0000374 // These operations need to be expanded:
Duncan Sands92c43912008-06-06 12:08:01 +0000375 setOperationAction(ISD::SDIV, VT, Expand);
376 setOperationAction(ISD::SREM, VT, Expand);
377 setOperationAction(ISD::UDIV, VT, Expand);
378 setOperationAction(ISD::UREM, VT, Expand);
379 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000380
381 // Custom lower build_vector, constant pool spills, insert and
382 // extract vector elements:
Duncan Sands92c43912008-06-06 12:08:01 +0000383 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
384 setOperationAction(ISD::ConstantPool, VT, Custom);
385 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
386 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
387 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
388 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel8efdca42007-12-04 22:23:35 +0000389 }
390
391 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
392 setOperationAction(ISD::AND, MVT::v16i8, Custom);
393 setOperationAction(ISD::OR, MVT::v16i8, Custom);
394 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
395 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000396
Scott Michel8efdca42007-12-04 22:23:35 +0000397 setShiftAmountType(MVT::i32);
Duncan Sands8cf4a822008-11-23 15:47:28 +0000398 setBooleanContents(ZeroOrOneBooleanContent);
Scott Michel4ec722e2008-07-16 17:17:29 +0000399
Scott Michel8efdca42007-12-04 22:23:35 +0000400 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel4ec722e2008-07-16 17:17:29 +0000401
Scott Michel8efdca42007-12-04 22:23:35 +0000402 // We have target-specific dag combine patterns for the following nodes:
Scott Michelf9f42e62008-01-29 02:16:57 +0000403 setTargetDAGCombine(ISD::ADD);
Scott Michel97872d32008-02-23 18:41:37 +0000404 setTargetDAGCombine(ISD::ZERO_EXTEND);
405 setTargetDAGCombine(ISD::SIGN_EXTEND);
406 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel4ec722e2008-07-16 17:17:29 +0000407
Scott Michel8efdca42007-12-04 22:23:35 +0000408 computeRegisterProperties();
Scott Michel56a125e2008-11-22 23:50:42 +0000409
410 // Set other properties:
411 setSchedulingPreference(SchedulingForLatency);
Scott Michel8efdca42007-12-04 22:23:35 +0000412}
413
414const char *
415SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
416{
417 if (node_names.empty()) {
418 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
419 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
420 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
421 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Micheldbac4cf2008-01-11 02:53:15 +0000422 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michelf9f42e62008-01-29 02:16:57 +0000423 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel8efdca42007-12-04 22:23:35 +0000424 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
425 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
426 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel56a125e2008-11-22 23:50:42 +0000427 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000428 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
429 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
Scott Michelc630c412008-11-24 17:11:17 +0000430 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
431 node_names[(unsigned) SPUISD::VEC2PREFSLOT_CHAINED]
432 = "SPUISD::VEC2PREFSLOT_CHAINED";
Scott Michel8efdca42007-12-04 22:23:35 +0000433 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
434 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
435 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
436 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
437 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
438 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
439 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
440 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michel97872d32008-02-23 18:41:37 +0000441 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
442 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel8efdca42007-12-04 22:23:35 +0000443 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
444 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
445 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
446 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
447 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michel97872d32008-02-23 18:41:37 +0000448 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
449 "SPUISD::ROTQUAD_RZ_BYTES";
450 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
451 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel8efdca42007-12-04 22:23:35 +0000452 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
453 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
454 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel67224b22008-06-02 22:18:03 +0000455 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
456 "SPUISD::ROTBYTES_LEFT_BITS";
457 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel8efdca42007-12-04 22:23:35 +0000458 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel67224b22008-06-02 22:18:03 +0000459 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
460 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
461 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
462 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel8efdca42007-12-04 22:23:35 +0000463 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
464 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
465 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
466 }
467
468 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
469
470 return ((i != node_names.end()) ? i->second : 0);
471}
472
Dan Gohman8181bd12008-07-27 21:46:04 +0000473MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands92c43912008-06-06 12:08:01 +0000474 MVT VT = Op.getValueType();
Scott Michela313fb02008-10-30 01:51:48 +0000475 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel53ab7792008-03-10 16:58:52 +0000476}
477
Scott Michel8efdca42007-12-04 22:23:35 +0000478//===----------------------------------------------------------------------===//
479// Calling convention code:
480//===----------------------------------------------------------------------===//
481
482#include "SPUGenCallingConv.inc"
483
484//===----------------------------------------------------------------------===//
485// LowerOperation implementation
486//===----------------------------------------------------------------------===//
487
Scott Micheldbac4cf2008-01-11 02:53:15 +0000488/// Aligned load common code for CellSPU
489/*!
490 \param[in] Op The SelectionDAG load or store operand
491 \param[in] DAG The selection DAG
492 \param[in] ST CellSPU subtarget information structure
493 \param[in,out] alignment Caller initializes this to the load or store node's
494 value from getAlignment(), may be updated while generating the aligned load
495 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
496 offset (divisible by 16, modulo 16 == 0)
497 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
498 offset of the preferred slot (modulo 16 != 0)
499 \param[in,out] VT Caller initializes this value type to the the load or store
500 node's loaded or stored value type; may be updated if an i1-extended load or
501 store.
502 \param[out] was16aligned true if the base pointer had 16-byte alignment,
503 otherwise false. Can help to determine if the chunk needs to be rotated.
504
505 Both load and store lowering load a block of data aligned on a 16-byte
506 boundary. This is the common aligned load code shared between both.
507 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000508static SDValue
509AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Micheldbac4cf2008-01-11 02:53:15 +0000510 LSBaseSDNode *LSN,
511 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands92c43912008-06-06 12:08:01 +0000512 MVT &VT, bool &was16aligned)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000513{
Duncan Sands92c43912008-06-06 12:08:01 +0000514 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000515 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman8181bd12008-07-27 21:46:04 +0000516 SDValue basePtr = LSN->getBasePtr();
517 SDValue chain = LSN->getChain();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000518
519 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greif1c80d112008-08-28 21:40:38 +0000520 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000521
Gabor Greife9f7f582008-08-31 15:37:04 +0000522 if (Op1.getOpcode() == ISD::Constant
523 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel394e26d2008-01-17 20:38:41 +0000524 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000525
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000526 alignOffs = (int) CN->getZExtValue();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000527 prefSlotOffs = (int) (alignOffs & 0xf);
528
529 // Adjust the rotation amount to ensure that the final result ends up in
530 // the preferred slot:
531 prefSlotOffs -= vtm->prefslot_byte;
532 basePtr = basePtr.getOperand(0);
533
Scott Michel394e26d2008-01-17 20:38:41 +0000534 // Loading from memory, can we adjust alignment?
535 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000536 SDValue APtr = basePtr.getOperand(0);
Scott Michel394e26d2008-01-17 20:38:41 +0000537 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
538 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
539 alignment = GSDN->getGlobal()->getAlignment();
540 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000541 }
542 } else {
543 alignOffs = 0;
544 prefSlotOffs = -vtm->prefslot_byte;
545 }
Scott Michelbc5fbc12008-04-30 00:30:08 +0000546 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
547 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
548 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
549 prefSlotOffs = (int) (alignOffs & 0xf);
550 prefSlotOffs -= vtm->prefslot_byte;
551 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000552 } else {
553 alignOffs = 0;
554 prefSlotOffs = -vtm->prefslot_byte;
555 }
556
557 if (alignment == 16) {
558 // Realign the base pointer as a D-Form address:
559 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel394e26d2008-01-17 20:38:41 +0000560 basePtr = DAG.getNode(ISD::ADD, PtrVT,
561 basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000562 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000563 }
564
565 // Emit the vector load:
566 was16aligned = true;
567 return DAG.getLoad(MVT::v16i8, chain, basePtr,
568 LSN->getSrcValue(), LSN->getSrcValueOffset(),
569 LSN->isVolatile(), 16);
570 }
571
572 // Unaligned load or we're using the "large memory" model, which means that
573 // we have to be very pessimistic:
Scott Michel394e26d2008-01-17 20:38:41 +0000574 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greife9f7f582008-08-31 15:37:04 +0000575 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
576 DAG.getConstant(0, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000577 }
578
579 // Add the offset
Scott Michelf9f42e62008-01-29 02:16:57 +0000580 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000581 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000582 was16aligned = false;
583 return DAG.getLoad(MVT::v16i8, chain, basePtr,
584 LSN->getSrcValue(), LSN->getSrcValueOffset(),
585 LSN->isVolatile(), 16);
586}
587
Scott Michel8efdca42007-12-04 22:23:35 +0000588/// Custom lower loads for CellSPU
589/*!
590 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
591 within a 16-byte block, we have to rotate to extract the requested element.
592 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000593static SDValue
594LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000595 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000596 SDValue the_chain = LN->getChain();
Duncan Sands92c43912008-06-06 12:08:01 +0000597 MVT VT = LN->getMemoryVT();
Gabor Greif1c80d112008-08-28 21:40:38 +0000598 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000599 ISD::LoadExtType ExtType = LN->getExtensionType();
600 unsigned alignment = LN->getAlignment();
Dan Gohman8181bd12008-07-27 21:46:04 +0000601 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +0000602
Scott Michel8efdca42007-12-04 22:23:35 +0000603 switch (LN->getAddressingMode()) {
604 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000605 int offset, rotamt;
606 bool was16aligned;
Dan Gohman8181bd12008-07-27 21:46:04 +0000607 SDValue result =
Scott Micheldbac4cf2008-01-11 02:53:15 +0000608 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000609
Gabor Greif1c80d112008-08-28 21:40:38 +0000610 if (result.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +0000611 return result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000612
613 the_chain = result.getValue(1);
614 // Rotate the chunk if necessary
615 if (rotamt < 0)
616 rotamt += 16;
Scott Michelabc58242008-01-11 21:01:19 +0000617 if (rotamt != 0 || !was16aligned) {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000618 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
619
Scott Michel394e26d2008-01-17 20:38:41 +0000620 Ops[0] = the_chain;
621 Ops[1] = result;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000622 if (was16aligned) {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000623 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
624 } else {
Duncan Sands92c43912008-06-06 12:08:01 +0000625 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000626 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michelabc58242008-01-11 21:01:19 +0000627 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel5a6f17b2008-01-30 02:55:46 +0000628 DAG.getConstant(rotamt, PtrVT));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000629 }
630
631 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
632 the_chain = result.getValue(1);
Scott Michel8efdca42007-12-04 22:23:35 +0000633 }
Scott Micheldbac4cf2008-01-11 02:53:15 +0000634
635 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
636 SDVTList scalarvts;
Duncan Sands92c43912008-06-06 12:08:01 +0000637 MVT vecVT = MVT::v16i8;
Scott Michel4ec722e2008-07-16 17:17:29 +0000638
Scott Micheldbac4cf2008-01-11 02:53:15 +0000639 // Convert the loaded v16i8 vector to the appropriate vector type
640 // specified by the operand:
641 if (OpVT == VT) {
642 if (VT != MVT::i1)
Duncan Sands92c43912008-06-06 12:08:01 +0000643 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000644 } else
Duncan Sands92c43912008-06-06 12:08:01 +0000645 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000646
647 Ops[0] = the_chain;
648 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
649 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
Scott Michelc630c412008-11-24 17:11:17 +0000650 result = DAG.getNode(SPUISD::VEC2PREFSLOT_CHAINED, scalarvts, Ops, 2);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000651 the_chain = result.getValue(1);
652 } else {
653 // Handle the sign and zero-extending loads for i1 and i8:
654 unsigned NewOpC;
655
656 if (ExtType == ISD::SEXTLOAD) {
657 NewOpC = (OpVT == MVT::i1
658 ? SPUISD::EXTRACT_I1_SEXT
659 : SPUISD::EXTRACT_I8_SEXT);
660 } else {
661 assert(ExtType == ISD::ZEXTLOAD);
662 NewOpC = (OpVT == MVT::i1
663 ? SPUISD::EXTRACT_I1_ZEXT
664 : SPUISD::EXTRACT_I8_ZEXT);
665 }
666
667 result = DAG.getNode(NewOpC, OpVT, result);
668 }
669
670 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman8181bd12008-07-27 21:46:04 +0000671 SDValue retops[2] = {
Scott Michel394e26d2008-01-17 20:38:41 +0000672 result,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000673 the_chain
Scott Michel394e26d2008-01-17 20:38:41 +0000674 };
Scott Micheldbac4cf2008-01-11 02:53:15 +0000675
Scott Michel394e26d2008-01-17 20:38:41 +0000676 result = DAG.getNode(SPUISD::LDRESULT, retvts,
677 retops, sizeof(retops) / sizeof(retops[0]));
Scott Micheldbac4cf2008-01-11 02:53:15 +0000678 return result;
Scott Michel8efdca42007-12-04 22:23:35 +0000679 }
680 case ISD::PRE_INC:
681 case ISD::PRE_DEC:
682 case ISD::POST_INC:
683 case ISD::POST_DEC:
684 case ISD::LAST_INDEXED_MODE:
685 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
686 "UNINDEXED\n";
687 cerr << (unsigned) LN->getAddressingMode() << "\n";
688 abort();
689 /*NOTREACHED*/
690 }
691
Dan Gohman8181bd12008-07-27 21:46:04 +0000692 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000693}
694
695/// Custom lower stores for CellSPU
696/*!
697 All CellSPU stores are aligned to 16-byte boundaries, so for elements
698 within a 16-byte block, we have to generate a shuffle to insert the
699 requested element into its place, then store the resulting block.
700 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000701static SDValue
702LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel8efdca42007-12-04 22:23:35 +0000703 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000704 SDValue Value = SN->getValue();
Duncan Sands92c43912008-06-06 12:08:01 +0000705 MVT VT = Value.getValueType();
706 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
707 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Micheldbac4cf2008-01-11 02:53:15 +0000708 unsigned alignment = SN->getAlignment();
Scott Michel8efdca42007-12-04 22:23:35 +0000709
710 switch (SN->getAddressingMode()) {
711 case ISD::UNINDEXED: {
Scott Micheldbac4cf2008-01-11 02:53:15 +0000712 int chunk_offset, slot_offset;
713 bool was16aligned;
Scott Michel8efdca42007-12-04 22:23:35 +0000714
Scott Michel33d73eb2008-11-21 02:56:16 +0000715 // The vector type we really want to load from the 16-byte chunk.
Scott Michele1006032008-11-19 17:45:08 +0000716 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
717 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +0000718
Dan Gohman8181bd12008-07-27 21:46:04 +0000719 SDValue alignLoadVec =
Scott Micheldbac4cf2008-01-11 02:53:15 +0000720 AlignedLoad(Op, DAG, ST, SN, alignment,
721 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel8efdca42007-12-04 22:23:35 +0000722
Gabor Greif1c80d112008-08-28 21:40:38 +0000723 if (alignLoadVec.getNode() == 0)
Scott Micheldbac4cf2008-01-11 02:53:15 +0000724 return alignLoadVec;
Scott Michel8efdca42007-12-04 22:23:35 +0000725
Scott Micheldbac4cf2008-01-11 02:53:15 +0000726 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman8181bd12008-07-27 21:46:04 +0000727 SDValue basePtr = LN->getBasePtr();
728 SDValue the_chain = alignLoadVec.getValue(1);
729 SDValue theValue = SN->getValue();
730 SDValue result;
Scott Michel8efdca42007-12-04 22:23:35 +0000731
732 if (StVT != VT
Scott Michel5a6f17b2008-01-30 02:55:46 +0000733 && (theValue.getOpcode() == ISD::AssertZext
734 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel8efdca42007-12-04 22:23:35 +0000735 // Drill down and get the value for zero- and sign-extended
736 // quantities
Scott Michel4ec722e2008-07-16 17:17:29 +0000737 theValue = theValue.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +0000738 }
739
Scott Micheldbac4cf2008-01-11 02:53:15 +0000740 chunk_offset &= 0xf;
Scott Michel8efdca42007-12-04 22:23:35 +0000741
Dan Gohman8181bd12008-07-27 21:46:04 +0000742 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
743 SDValue insertEltPtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000744
745 // If the base pointer is already a D-form address, then just create
746 // a new D-form address with a slot offset and the orignal base pointer.
747 // Otherwise generate a D-form address with the slot offset relative
748 // to the stack pointer, which is always aligned.
Scott Michelabc58242008-01-11 21:01:19 +0000749 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greif1c80d112008-08-28 21:40:38 +0000750 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michelabc58242008-01-11 21:01:19 +0000751 DEBUG(cerr << "\n");
752
Scott Michelf9f42e62008-01-29 02:16:57 +0000753 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
754 (basePtr.getOpcode() == ISD::ADD
755 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michelabc58242008-01-11 21:01:19 +0000756 insertEltPtr = basePtr;
Scott Micheldbac4cf2008-01-11 02:53:15 +0000757 } else {
Scott Michelf9f42e62008-01-29 02:16:57 +0000758 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000759 }
760
Scott Michelf65c8f02008-11-19 15:24:16 +0000761 SDValue insertEltOp =
Scott Michel0718cd82008-12-01 17:56:02 +0000762 DAG.getNode(SPUISD::SHUFFLE_MASK, vecVT, insertEltPtr);
Scott Michele1006032008-11-19 17:45:08 +0000763 SDValue vectorizeOp =
764 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michelf65c8f02008-11-19 15:24:16 +0000765
Scott Michel0718cd82008-12-01 17:56:02 +0000766 result = DAG.getNode(SPUISD::SHUFB, vecVT,
767 vectorizeOp, alignLoadVec,
768 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, insertEltOp));
Scott Michel8efdca42007-12-04 22:23:35 +0000769
Scott Micheldbac4cf2008-01-11 02:53:15 +0000770 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel8efdca42007-12-04 22:23:35 +0000771 LN->getSrcValue(), LN->getSrcValueOffset(),
772 LN->isVolatile(), LN->getAlignment());
773
Scott Michele1006032008-11-19 17:45:08 +0000774#if 0 && defined(NDEBUG)
Scott Michelf65c8f02008-11-19 15:24:16 +0000775 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
776 const SDValue &currentRoot = DAG.getRoot();
777
778 DAG.setRoot(result);
779 cerr << "------- CellSPU:LowerStore result:\n";
780 DAG.dump();
781 cerr << "-------\n";
782 DAG.setRoot(currentRoot);
783 }
784#endif
785
Scott Michel8efdca42007-12-04 22:23:35 +0000786 return result;
787 /*UNREACHED*/
788 }
789 case ISD::PRE_INC:
790 case ISD::PRE_DEC:
791 case ISD::POST_INC:
792 case ISD::POST_DEC:
793 case ISD::LAST_INDEXED_MODE:
794 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
795 "UNINDEXED\n";
796 cerr << (unsigned) SN->getAddressingMode() << "\n";
797 abort();
798 /*NOTREACHED*/
799 }
800
Dan Gohman8181bd12008-07-27 21:46:04 +0000801 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000802}
803
804/// Generate the address of a constant pool entry.
Dan Gohman8181bd12008-07-27 21:46:04 +0000805static SDValue
806LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000807 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000808 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
809 Constant *C = CP->getConstVal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000810 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
811 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Micheldbac4cf2008-01-11 02:53:15 +0000812 const TargetMachine &TM = DAG.getTarget();
Scott Michel8efdca42007-12-04 22:23:35 +0000813
814 if (TM.getRelocationModel() == Reloc::Static) {
815 if (!ST->usingLargeMem()) {
Dan Gohman8181bd12008-07-27 21:46:04 +0000816 // Just return the SDValue with the constant pool address in it.
Scott Michel394e26d2008-01-17 20:38:41 +0000817 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +0000818 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000819 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
820 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000821 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel8efdca42007-12-04 22:23:35 +0000822 }
823 }
824
825 assert(0 &&
Gabor Greife9f7f582008-08-31 15:37:04 +0000826 "LowerConstantPool: Relocation model other than static"
827 " not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000828 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000829}
830
Dan Gohman8181bd12008-07-27 21:46:04 +0000831static SDValue
832LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000833 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000834 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman8181bd12008-07-27 21:46:04 +0000835 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
836 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel8efdca42007-12-04 22:23:35 +0000837 const TargetMachine &TM = DAG.getTarget();
838
839 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel97872d32008-02-23 18:41:37 +0000840 if (!ST->usingLargeMem()) {
841 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
842 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000843 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
844 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michel97872d32008-02-23 18:41:37 +0000845 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
846 }
Scott Michel8efdca42007-12-04 22:23:35 +0000847 }
848
849 assert(0 &&
850 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman8181bd12008-07-27 21:46:04 +0000851 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000852}
853
Dan Gohman8181bd12008-07-27 21:46:04 +0000854static SDValue
855LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands92c43912008-06-06 12:08:01 +0000856 MVT PtrVT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000857 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
858 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman8181bd12008-07-27 21:46:04 +0000859 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel8efdca42007-12-04 22:23:35 +0000860 const TargetMachine &TM = DAG.getTarget();
Dan Gohman8181bd12008-07-27 21:46:04 +0000861 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel4ec722e2008-07-16 17:17:29 +0000862
Scott Michel8efdca42007-12-04 22:23:35 +0000863 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michelf9f42e62008-01-29 02:16:57 +0000864 if (!ST->usingLargeMem()) {
865 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
866 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +0000867 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
868 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michelf9f42e62008-01-29 02:16:57 +0000869 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
870 }
Scott Michel8efdca42007-12-04 22:23:35 +0000871 } else {
872 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel5a6f17b2008-01-30 02:55:46 +0000873 << "supported.\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000874 abort();
875 /*NOTREACHED*/
876 }
877
Dan Gohman8181bd12008-07-27 21:46:04 +0000878 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000879}
880
881//! Custom lower i64 integer constants
882/*!
883 This code inserts all of the necessary juggling that needs to occur to load
884 a 64-bit constant into a register.
885 */
Dan Gohman8181bd12008-07-27 21:46:04 +0000886static SDValue
887LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000888 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000889
890 if (VT == MVT::i64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000891 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
892 SDValue T = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michelc630c412008-11-24 17:11:17 +0000893 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +0000894 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +0000895 } else {
896 cerr << "LowerConstant: unhandled constant type "
Duncan Sands92c43912008-06-06 12:08:01 +0000897 << VT.getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +0000898 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +0000899 abort();
900 /*NOTREACHED*/
901 }
902
Dan Gohman8181bd12008-07-27 21:46:04 +0000903 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000904}
905
Nate Begeman78125042008-02-14 18:43:04 +0000906//! Custom lower double precision floating point constants
Dan Gohman8181bd12008-07-27 21:46:04 +0000907static SDValue
908LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +0000909 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +0000910
Nate Begeman78125042008-02-14 18:43:04 +0000911 if (VT == MVT::f64) {
Scott Michel0718cd82008-12-01 17:56:02 +0000912 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
913
914 assert((FP != 0) &&
915 "LowerConstantFP: Node is not ConstantFPSDNode");
916
Scott Michel11e88bb2007-12-19 20:15:47 +0000917 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel0718cd82008-12-01 17:56:02 +0000918 SDValue T = DAG.getConstant(dbits, MVT::i64);
919 SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T);
920 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
921 DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64, Tvec));
Scott Michel8efdca42007-12-04 22:23:35 +0000922 }
923
Dan Gohman8181bd12008-07-27 21:46:04 +0000924 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +0000925}
926
Scott Michel33d73eb2008-11-21 02:56:16 +0000927//! Lower MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman8181bd12008-07-27 21:46:04 +0000928static SDValue
929LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel394e26d2008-01-17 20:38:41 +0000930{
Dan Gohman8181bd12008-07-27 21:46:04 +0000931 SDValue Cond = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +0000932 MVT CondVT = Cond.getValueType();
933 MVT CondNVT;
Scott Michel394e26d2008-01-17 20:38:41 +0000934
Scott Michel33d73eb2008-11-21 02:56:16 +0000935 if (CondVT == MVT::i8) {
936 CondNVT = MVT::i16;
Scott Michel394e26d2008-01-17 20:38:41 +0000937 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
938 Op.getOperand(0),
939 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
940 Op.getOperand(2));
941 } else
Dan Gohman8181bd12008-07-27 21:46:04 +0000942 return SDValue(); // Unchanged
Scott Michel394e26d2008-01-17 20:38:41 +0000943}
944
Dan Gohman8181bd12008-07-27 21:46:04 +0000945static SDValue
946LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel8efdca42007-12-04 22:23:35 +0000947{
948 MachineFunction &MF = DAG.getMachineFunction();
949 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner1b989192007-12-31 04:13:23 +0000950 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michela313fb02008-10-30 01:51:48 +0000951 SmallVector<SDValue, 48> ArgValues;
Dan Gohman8181bd12008-07-27 21:46:04 +0000952 SDValue Root = Op.getOperand(0);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +0000953 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel8efdca42007-12-04 22:23:35 +0000954
955 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
956 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel4ec722e2008-07-16 17:17:29 +0000957
Scott Michel8efdca42007-12-04 22:23:35 +0000958 unsigned ArgOffset = SPUFrameInfo::minStackSize();
959 unsigned ArgRegIdx = 0;
960 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel4ec722e2008-07-16 17:17:29 +0000961
Duncan Sands92c43912008-06-06 12:08:01 +0000962 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +0000963
Scott Michel8efdca42007-12-04 22:23:35 +0000964 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greife9f7f582008-08-31 15:37:04 +0000965 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
966 ArgNo != e; ++ArgNo) {
Duncan Sands92c43912008-06-06 12:08:01 +0000967 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
968 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michela313fb02008-10-30 01:51:48 +0000969 SDValue ArgVal;
Scott Michel8efdca42007-12-04 22:23:35 +0000970
Scott Michela313fb02008-10-30 01:51:48 +0000971 if (ArgRegIdx < NumArgRegs) {
972 const TargetRegisterClass *ArgRegClass;
Scott Michel4ec722e2008-07-16 17:17:29 +0000973
Scott Michela313fb02008-10-30 01:51:48 +0000974 switch (ObjectVT.getSimpleVT()) {
975 default: {
Scott Michel33d73eb2008-11-21 02:56:16 +0000976 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
977 << ObjectVT.getMVTString()
978 << "\n";
979 abort();
Scott Michela313fb02008-10-30 01:51:48 +0000980 }
981 case MVT::i8:
Scott Michel33d73eb2008-11-21 02:56:16 +0000982 ArgRegClass = &SPU::R8CRegClass;
983 break;
Scott Michela313fb02008-10-30 01:51:48 +0000984 case MVT::i16:
Scott Michel33d73eb2008-11-21 02:56:16 +0000985 ArgRegClass = &SPU::R16CRegClass;
986 break;
Scott Michela313fb02008-10-30 01:51:48 +0000987 case MVT::i32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000988 ArgRegClass = &SPU::R32CRegClass;
989 break;
Scott Michela313fb02008-10-30 01:51:48 +0000990 case MVT::i64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000991 ArgRegClass = &SPU::R64CRegClass;
992 break;
Scott Michela313fb02008-10-30 01:51:48 +0000993 case MVT::f32:
Scott Michel33d73eb2008-11-21 02:56:16 +0000994 ArgRegClass = &SPU::R32FPRegClass;
995 break;
Scott Michela313fb02008-10-30 01:51:48 +0000996 case MVT::f64:
Scott Michel33d73eb2008-11-21 02:56:16 +0000997 ArgRegClass = &SPU::R64FPRegClass;
998 break;
Scott Michela313fb02008-10-30 01:51:48 +0000999 case MVT::v2f64:
1000 case MVT::v4f32:
1001 case MVT::v2i64:
1002 case MVT::v4i32:
1003 case MVT::v8i16:
1004 case MVT::v16i8:
Scott Michel33d73eb2008-11-21 02:56:16 +00001005 ArgRegClass = &SPU::VECREGRegClass;
1006 break;
Scott Michela313fb02008-10-30 01:51:48 +00001007 }
1008
1009 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
1010 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
1011 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1012 ++ArgRegIdx;
1013 } else {
1014 // We need to load the argument to a virtual register if we determined
1015 // above that we ran out of physical registers of the appropriate type
1016 // or we're forced to do vararg
Chris Lattner60069452008-02-13 07:35:30 +00001017 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman8181bd12008-07-27 21:46:04 +00001018 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner60069452008-02-13 07:35:30 +00001019 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel8efdca42007-12-04 22:23:35 +00001020 ArgOffset += StackSlotSize;
1021 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001022
Scott Michel8efdca42007-12-04 22:23:35 +00001023 ArgValues.push_back(ArgVal);
Scott Michela313fb02008-10-30 01:51:48 +00001024 // Update the chain
1025 Root = ArgVal.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001026 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001027
Scott Michela313fb02008-10-30 01:51:48 +00001028 // vararg handling:
Scott Michel8efdca42007-12-04 22:23:35 +00001029 if (isVarArg) {
Scott Michela313fb02008-10-30 01:51:48 +00001030 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1031 // We will spill (79-3)+1 registers to the stack
1032 SmallVector<SDValue, 79-3+1> MemOps;
1033
1034 // Create the frame slot
1035
Scott Michel8efdca42007-12-04 22:23:35 +00001036 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Michela313fb02008-10-30 01:51:48 +00001037 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1038 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1039 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1040 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1041 Root = Store.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00001042 MemOps.push_back(Store);
Scott Michela313fb02008-10-30 01:51:48 +00001043
1044 // Increment address by stack slot size for the next stored argument
1045 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001046 }
1047 if (!MemOps.empty())
Scott Michela313fb02008-10-30 01:51:48 +00001048 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001049 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001050
Scott Michel8efdca42007-12-04 22:23:35 +00001051 ArgValues.push_back(Root);
Scott Michel4ec722e2008-07-16 17:17:29 +00001052
Scott Michel8efdca42007-12-04 22:23:35 +00001053 // Return the new list of results.
Duncan Sands42d7bb82008-12-01 11:41:29 +00001054 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
1055 &ArgValues[0], ArgValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001056}
1057
1058/// isLSAAddress - Return the immediate to use if the specified
1059/// value is representable as a LSA address.
Dan Gohman8181bd12008-07-27 21:46:04 +00001060static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel5974f432008-11-11 03:06:06 +00001061 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel8efdca42007-12-04 22:23:35 +00001062 if (!C) return 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001063
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001064 int Addr = C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001065 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1066 (Addr << 14 >> 14) != Addr)
1067 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel4ec722e2008-07-16 17:17:29 +00001068
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001069 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel8efdca42007-12-04 22:23:35 +00001070}
1071
1072static
Dan Gohman8181bd12008-07-27 21:46:04 +00001073SDValue
1074LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001075 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1076 SDValue Chain = TheCall->getChain();
Dan Gohman705e3f72008-09-13 01:54:27 +00001077 SDValue Callee = TheCall->getCallee();
1078 unsigned NumOps = TheCall->getNumArgs();
Scott Michel8efdca42007-12-04 22:23:35 +00001079 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1080 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1081 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1082
1083 // Handy pointer type
Duncan Sands92c43912008-06-06 12:08:01 +00001084 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel4ec722e2008-07-16 17:17:29 +00001085
Scott Michel8efdca42007-12-04 22:23:35 +00001086 // Accumulate how many bytes are to be pushed on the stack, including the
1087 // linkage area, and parameter passing area. According to the SPU ABI,
1088 // we minimally need space for [LR] and [SP]
1089 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel4ec722e2008-07-16 17:17:29 +00001090
Scott Michel8efdca42007-12-04 22:23:35 +00001091 // Set up a copy of the stack pointer for use loading and storing any
1092 // arguments that may not fit in the registers available for argument
1093 // passing.
Dan Gohman8181bd12008-07-27 21:46:04 +00001094 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel4ec722e2008-07-16 17:17:29 +00001095
Scott Michel8efdca42007-12-04 22:23:35 +00001096 // Figure out which arguments are going to go in registers, and which in
1097 // memory.
1098 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1099 unsigned ArgRegIdx = 0;
1100
1101 // Keep track of registers passing arguments
Dan Gohman8181bd12008-07-27 21:46:04 +00001102 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel8efdca42007-12-04 22:23:35 +00001103 // And the arguments passed on the stack
Dan Gohman8181bd12008-07-27 21:46:04 +00001104 SmallVector<SDValue, 8> MemOpChains;
Scott Michel8efdca42007-12-04 22:23:35 +00001105
1106 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman705e3f72008-09-13 01:54:27 +00001107 SDValue Arg = TheCall->getArg(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001108
Scott Michel8efdca42007-12-04 22:23:35 +00001109 // PtrOff will be used to store the current argument to the stack if a
1110 // register cannot be found for it.
Dan Gohman8181bd12008-07-27 21:46:04 +00001111 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel8efdca42007-12-04 22:23:35 +00001112 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1113
Duncan Sands92c43912008-06-06 12:08:01 +00001114 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001115 default: assert(0 && "Unexpected ValueType for argument!");
1116 case MVT::i32:
1117 case MVT::i64:
1118 case MVT::i128:
1119 if (ArgRegIdx != NumArgRegs) {
1120 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1121 } else {
1122 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001123 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001124 }
1125 break;
1126 case MVT::f32:
1127 case MVT::f64:
1128 if (ArgRegIdx != NumArgRegs) {
1129 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1130 } else {
1131 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001132 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001133 }
1134 break;
1135 case MVT::v4f32:
1136 case MVT::v4i32:
1137 case MVT::v8i16:
1138 case MVT::v16i8:
1139 if (ArgRegIdx != NumArgRegs) {
1140 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1141 } else {
1142 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel5a6f17b2008-01-30 02:55:46 +00001143 ArgOffset += StackSlotSize;
Scott Michel8efdca42007-12-04 22:23:35 +00001144 }
1145 break;
1146 }
1147 }
1148
1149 // Update number of stack bytes actually used, insert a call sequence start
1150 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001151 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1152 true));
Scott Michel8efdca42007-12-04 22:23:35 +00001153
1154 if (!MemOpChains.empty()) {
1155 // Adjust the stack pointer for the stack arguments.
1156 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1157 &MemOpChains[0], MemOpChains.size());
1158 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001159
Scott Michel8efdca42007-12-04 22:23:35 +00001160 // Build a sequence of copy-to-reg nodes chained together with token chain
1161 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman8181bd12008-07-27 21:46:04 +00001162 SDValue InFlag;
Scott Michel8efdca42007-12-04 22:23:35 +00001163 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1164 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1165 InFlag);
1166 InFlag = Chain.getValue(1);
1167 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001168
Dan Gohman8181bd12008-07-27 21:46:04 +00001169 SmallVector<SDValue, 8> Ops;
Scott Michel8efdca42007-12-04 22:23:35 +00001170 unsigned CallOpc = SPUISD::CALL;
Scott Michel4ec722e2008-07-16 17:17:29 +00001171
Bill Wendlingfef06052008-09-16 21:48:12 +00001172 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1173 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1174 // node so that legalize doesn't hack it.
Scott Michel5974f432008-11-11 03:06:06 +00001175 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001176 GlobalValue *GV = G->getGlobal();
Duncan Sands92c43912008-06-06 12:08:01 +00001177 MVT CalleeVT = Callee.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00001178 SDValue Zero = DAG.getConstant(0, PtrVT);
1179 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel8efdca42007-12-04 22:23:35 +00001180
Scott Micheldbac4cf2008-01-11 02:53:15 +00001181 if (!ST->usingLargeMem()) {
1182 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1183 // style calls, otherwise, external symbols are BRASL calls. This assumes
1184 // that declared/defined symbols are in the same compilation unit and can
1185 // be reached through PC-relative jumps.
1186 //
1187 // NOTE:
1188 // This may be an unsafe assumption for JIT and really large compilation
1189 // units.
1190 if (GV->isDeclaration()) {
1191 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1192 } else {
1193 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1194 }
Scott Michel8efdca42007-12-04 22:23:35 +00001195 } else {
Scott Micheldbac4cf2008-01-11 02:53:15 +00001196 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1197 // address pairs:
Scott Michelf9f42e62008-01-29 02:16:57 +00001198 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel8efdca42007-12-04 22:23:35 +00001199 }
Scott Michel5974f432008-11-11 03:06:06 +00001200 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendlingfef06052008-09-16 21:48:12 +00001201 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Micheldbac4cf2008-01-11 02:53:15 +00001202 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001203 // If this is an absolute destination address that appears to be a legal
1204 // local store address, use the munged value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001205 Callee = SDValue(Dest, 0);
Scott Micheldbac4cf2008-01-11 02:53:15 +00001206 }
Scott Michel8efdca42007-12-04 22:23:35 +00001207
1208 Ops.push_back(Chain);
1209 Ops.push_back(Callee);
Scott Michel4ec722e2008-07-16 17:17:29 +00001210
Scott Michel8efdca42007-12-04 22:23:35 +00001211 // Add argument registers to the end of the list so that they are known live
1212 // into the call.
1213 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel4ec722e2008-07-16 17:17:29 +00001214 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel8efdca42007-12-04 22:23:35 +00001215 RegsToPass[i].second.getValueType()));
Scott Michel4ec722e2008-07-16 17:17:29 +00001216
Gabor Greif1c80d112008-08-28 21:40:38 +00001217 if (InFlag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001218 Ops.push_back(InFlag);
Duncan Sands698842f2008-07-02 17:40:58 +00001219 // Returns a chain and a flag for retval copy to use.
1220 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1221 &Ops[0], Ops.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001222 InFlag = Chain.getValue(1);
1223
Chris Lattnerfe5d4022008-10-11 22:08:30 +00001224 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1225 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman705e3f72008-09-13 01:54:27 +00001226 if (TheCall->getValueType(0) != MVT::Other)
Evan Cheng07322bb2008-02-05 22:44:06 +00001227 InFlag = Chain.getValue(1);
1228
Dan Gohman8181bd12008-07-27 21:46:04 +00001229 SDValue ResultVals[3];
Scott Michel8efdca42007-12-04 22:23:35 +00001230 unsigned NumResults = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001231
Scott Michel8efdca42007-12-04 22:23:35 +00001232 // If the call has results, copy the values out of the ret val registers.
Dan Gohman705e3f72008-09-13 01:54:27 +00001233 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001234 default: assert(0 && "Unexpected ret value!");
1235 case MVT::Other: break;
1236 case MVT::i32:
Dan Gohman705e3f72008-09-13 01:54:27 +00001237 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001238 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1239 ResultVals[0] = Chain.getValue(0);
1240 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1241 Chain.getValue(2)).getValue(1);
1242 ResultVals[1] = Chain.getValue(0);
1243 NumResults = 2;
Scott Michel8efdca42007-12-04 22:23:35 +00001244 } else {
1245 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1246 ResultVals[0] = Chain.getValue(0);
1247 NumResults = 1;
1248 }
Scott Michel8efdca42007-12-04 22:23:35 +00001249 break;
1250 case MVT::i64:
1251 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1252 ResultVals[0] = Chain.getValue(0);
1253 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001254 break;
1255 case MVT::f32:
1256 case MVT::f64:
Dan Gohman705e3f72008-09-13 01:54:27 +00001257 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001258 InFlag).getValue(1);
1259 ResultVals[0] = Chain.getValue(0);
1260 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001261 break;
1262 case MVT::v2f64:
1263 case MVT::v4f32:
1264 case MVT::v4i32:
1265 case MVT::v8i16:
1266 case MVT::v16i8:
Dan Gohman705e3f72008-09-13 01:54:27 +00001267 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel8efdca42007-12-04 22:23:35 +00001268 InFlag).getValue(1);
1269 ResultVals[0] = Chain.getValue(0);
1270 NumResults = 1;
Scott Michel8efdca42007-12-04 22:23:35 +00001271 break;
1272 }
Duncan Sands698842f2008-07-02 17:40:58 +00001273
Scott Michel8efdca42007-12-04 22:23:35 +00001274 // If the function returns void, just return the chain.
1275 if (NumResults == 0)
1276 return Chain;
Scott Michel4ec722e2008-07-16 17:17:29 +00001277
Scott Michel8efdca42007-12-04 22:23:35 +00001278 // Otherwise, merge everything together with a MERGE_VALUES node.
1279 ResultVals[NumResults++] = Chain;
Dan Gohman8181bd12008-07-27 21:46:04 +00001280 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif46bf5472008-08-26 22:36:50 +00001281 return Res.getValue(Op.getResNo());
Scott Michel8efdca42007-12-04 22:23:35 +00001282}
1283
Dan Gohman8181bd12008-07-27 21:46:04 +00001284static SDValue
1285LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel8efdca42007-12-04 22:23:35 +00001286 SmallVector<CCValAssign, 16> RVLocs;
1287 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1288 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1289 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greif1c80d112008-08-28 21:40:38 +00001290 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel4ec722e2008-07-16 17:17:29 +00001291
Scott Michel8efdca42007-12-04 22:23:35 +00001292 // If this is the first return lowered for this function, add the regs to the
1293 // liveout set for the function.
Chris Lattner1b989192007-12-31 04:13:23 +00001294 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001295 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner1b989192007-12-31 04:13:23 +00001296 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel8efdca42007-12-04 22:23:35 +00001297 }
1298
Dan Gohman8181bd12008-07-27 21:46:04 +00001299 SDValue Chain = Op.getOperand(0);
1300 SDValue Flag;
Scott Michel4ec722e2008-07-16 17:17:29 +00001301
Scott Michel8efdca42007-12-04 22:23:35 +00001302 // Copy the result values into the output registers.
1303 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1304 CCValAssign &VA = RVLocs[i];
1305 assert(VA.isRegLoc() && "Can only return in registers!");
1306 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1307 Flag = Chain.getValue(1);
1308 }
1309
Gabor Greif1c80d112008-08-28 21:40:38 +00001310 if (Flag.getNode())
Scott Michel8efdca42007-12-04 22:23:35 +00001311 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1312 else
1313 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1314}
1315
1316
1317//===----------------------------------------------------------------------===//
1318// Vector related lowering:
1319//===----------------------------------------------------------------------===//
1320
1321static ConstantSDNode *
1322getVecImm(SDNode *N) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001323 SDValue OpVal(0, 0);
Scott Michel4ec722e2008-07-16 17:17:29 +00001324
Scott Michel8efdca42007-12-04 22:23:35 +00001325 // Check to see if this buildvec has a single non-undef value in its elements.
1326 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1327 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greif1c80d112008-08-28 21:40:38 +00001328 if (OpVal.getNode() == 0)
Scott Michel8efdca42007-12-04 22:23:35 +00001329 OpVal = N->getOperand(i);
1330 else if (OpVal != N->getOperand(i))
1331 return 0;
1332 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001333
Gabor Greif1c80d112008-08-28 21:40:38 +00001334 if (OpVal.getNode() != 0) {
Scott Michel5974f432008-11-11 03:06:06 +00001335 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001336 return CN;
1337 }
1338 }
1339
1340 return 0; // All UNDEF: use implicit def.; not Constant node
1341}
1342
1343/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1344/// and the value fits into an unsigned 18-bit constant, and if so, return the
1345/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001346SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001347 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001348 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001349 uint64_t Value = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001350 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001351 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001352 uint32_t upper = uint32_t(UValue >> 32);
1353 uint32_t lower = uint32_t(UValue);
1354 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001355 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001356 Value = Value >> 32;
1357 }
Scott Michel8efdca42007-12-04 22:23:35 +00001358 if (Value <= 0x3ffff)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001359 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001360 }
1361
Dan Gohman8181bd12008-07-27 21:46:04 +00001362 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001363}
1364
1365/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1366/// and the value fits into a signed 16-bit constant, and if so, return the
1367/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001368SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001369 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001370 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001371 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001372 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001373 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001374 uint32_t upper = uint32_t(UValue >> 32);
1375 uint32_t lower = uint32_t(UValue);
1376 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001377 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001378 Value = Value >> 32;
1379 }
Scott Michel6baba072008-03-05 23:02:02 +00001380 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001381 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001382 }
1383 }
1384
Dan Gohman8181bd12008-07-27 21:46:04 +00001385 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001386}
1387
1388/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1389/// and the value fits into a signed 10-bit constant, and if so, return the
1390/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001391SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001392 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001393 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman40686732008-09-26 21:54:37 +00001394 int64_t Value = CN->getSExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001395 if (ValueType == MVT::i64) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001396 uint64_t UValue = CN->getZExtValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001397 uint32_t upper = uint32_t(UValue >> 32);
1398 uint32_t lower = uint32_t(UValue);
1399 if (upper != lower)
Dan Gohman8181bd12008-07-27 21:46:04 +00001400 return SDValue();
Scott Michelbcc7b672008-03-06 04:02:54 +00001401 Value = Value >> 32;
1402 }
Scott Michel6baba072008-03-05 23:02:02 +00001403 if (isS10Constant(Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001404 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001405 }
1406
Dan Gohman8181bd12008-07-27 21:46:04 +00001407 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001408}
1409
1410/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1411/// and the value fits into a signed 8-bit constant, and if so, return the
1412/// constant.
1413///
1414/// @note: The incoming vector is v16i8 because that's the only way we can load
1415/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1416/// same value.
Dan Gohman8181bd12008-07-27 21:46:04 +00001417SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001418 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001419 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001420 int Value = (int) CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001421 if (ValueType == MVT::i16
Scott Michel5a6f17b2008-01-30 02:55:46 +00001422 && Value <= 0xffff /* truncated from uint64_t */
1423 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001424 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001425 else if (ValueType == MVT::i8
Scott Michel5a6f17b2008-01-30 02:55:46 +00001426 && (Value & 0xff) == Value)
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001427 return DAG.getTargetConstant(Value, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001428 }
1429
Dan Gohman8181bd12008-07-27 21:46:04 +00001430 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001431}
1432
1433/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1434/// and the value fits into a signed 16-bit constant, and if so, return the
1435/// constant
Dan Gohman8181bd12008-07-27 21:46:04 +00001436SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands92c43912008-06-06 12:08:01 +00001437 MVT ValueType) {
Scott Michel8efdca42007-12-04 22:23:35 +00001438 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001439 uint64_t Value = CN->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001440 if ((ValueType == MVT::i32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001441 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1442 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001443 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel8efdca42007-12-04 22:23:35 +00001444 }
1445
Dan Gohman8181bd12008-07-27 21:46:04 +00001446 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001447}
1448
1449/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001450SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001451 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001452 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001453 }
1454
Dan Gohman8181bd12008-07-27 21:46:04 +00001455 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001456}
1457
1458/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman8181bd12008-07-27 21:46:04 +00001459SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00001460 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman57d5d5d2008-11-05 02:06:09 +00001461 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001462 }
1463
Dan Gohman8181bd12008-07-27 21:46:04 +00001464 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001465}
1466
1467// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001468// UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001469// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1470// zero. Return true if this is not an array of constants, false if it is.
1471//
1472static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1473 uint64_t UndefBits[2]) {
1474 // Start with zero'd results.
1475 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001476
Duncan Sands92c43912008-06-06 12:08:01 +00001477 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel8efdca42007-12-04 22:23:35 +00001478 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001479 SDValue OpVal = BV->getOperand(i);
Scott Michel4ec722e2008-07-16 17:17:29 +00001480
Scott Michel8efdca42007-12-04 22:23:35 +00001481 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1482 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1483
1484 uint64_t EltBits = 0;
1485 if (OpVal.getOpcode() == ISD::UNDEF) {
1486 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1487 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1488 continue;
Scott Michel5974f432008-11-11 03:06:06 +00001489 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001490 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel5974f432008-11-11 03:06:06 +00001491 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel8efdca42007-12-04 22:23:35 +00001492 const APFloat &apf = CN->getValueAPF();
1493 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel5a6f17b2008-01-30 02:55:46 +00001494 ? FloatToBits(apf.convertToFloat())
1495 : DoubleToBits(apf.convertToDouble()));
Scott Michel8efdca42007-12-04 22:23:35 +00001496 } else {
1497 // Nonconstant element.
1498 return true;
1499 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001500
Scott Michel8efdca42007-12-04 22:23:35 +00001501 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1502 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001503
1504 //printf("%llx %llx %llx %llx\n",
Scott Michel8efdca42007-12-04 22:23:35 +00001505 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1506 return false;
1507}
1508
1509/// If this is a splat (repetition) of a value across the whole vector, return
1510/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel4ec722e2008-07-16 17:17:29 +00001511/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel8efdca42007-12-04 22:23:35 +00001512/// SplatSize = 1 byte.
Scott Michel4ec722e2008-07-16 17:17:29 +00001513static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel8efdca42007-12-04 22:23:35 +00001514 const uint64_t Undef128[2],
Scott Michel5a6f17b2008-01-30 02:55:46 +00001515 int MinSplatBits,
Scott Michel8efdca42007-12-04 22:23:35 +00001516 uint64_t &SplatBits, uint64_t &SplatUndef,
1517 int &SplatSize) {
1518 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1519 // the same as the lower 64-bits, ignoring undefs.
1520 uint64_t Bits64 = Bits128[0] | Bits128[1];
1521 uint64_t Undef64 = Undef128[0] & Undef128[1];
1522 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1523 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1524 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1525 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1526
1527 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1528 if (MinSplatBits < 64) {
Scott Michel4ec722e2008-07-16 17:17:29 +00001529
Scott Michel8efdca42007-12-04 22:23:35 +00001530 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1531 // undefs.
1532 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001533 if (MinSplatBits < 32) {
Scott Michel8efdca42007-12-04 22:23:35 +00001534
Scott Michel5a6f17b2008-01-30 02:55:46 +00001535 // If the top 16-bits are different than the lower 16-bits, ignoring
1536 // undefs, we have an i32 splat.
1537 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1538 if (MinSplatBits < 16) {
1539 // If the top 8-bits are different than the lower 8-bits, ignoring
1540 // undefs, we have an i16 splat.
Gabor Greife9f7f582008-08-31 15:37:04 +00001541 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1542 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001543 // Otherwise, we have an 8-bit splat.
1544 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1545 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1546 SplatSize = 1;
1547 return true;
1548 }
1549 } else {
1550 SplatBits = Bits16;
1551 SplatUndef = Undef16;
1552 SplatSize = 2;
1553 return true;
1554 }
1555 }
1556 } else {
1557 SplatBits = Bits32;
1558 SplatUndef = Undef32;
1559 SplatSize = 4;
1560 return true;
1561 }
Scott Michel8efdca42007-12-04 22:23:35 +00001562 }
1563 } else {
1564 SplatBits = Bits128[0];
1565 SplatUndef = Undef128[0];
1566 SplatSize = 8;
1567 return true;
1568 }
1569 }
1570
1571 return false; // Can't be a splat if two pieces don't match.
1572}
1573
1574// If this is a case we can't handle, return null and let the default
1575// expansion code take care of it. If we CAN select this case, and if it
1576// selects to a single instruction, return Op. Otherwise, if we can codegen
1577// this case more efficiently than a constant pool load, lower it to the
1578// sequence of ops that should be used.
Dan Gohman8181bd12008-07-27 21:46:04 +00001579static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001580 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00001581 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel4ec722e2008-07-16 17:17:29 +00001582 // UndefBits is set if the corresponding element of the vector is an
Scott Michel8efdca42007-12-04 22:23:35 +00001583 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel4ec722e2008-07-16 17:17:29 +00001584 // zero.
Scott Michel8efdca42007-12-04 22:23:35 +00001585 uint64_t VectorBits[2];
1586 uint64_t UndefBits[2];
1587 uint64_t SplatBits, SplatUndef;
1588 int SplatSize;
Gabor Greif1c80d112008-08-28 21:40:38 +00001589 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel8efdca42007-12-04 22:23:35 +00001590 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00001591 VT.getVectorElementType().getSizeInBits(),
Scott Michel8efdca42007-12-04 22:23:35 +00001592 SplatBits, SplatUndef, SplatSize))
Dan Gohman8181bd12008-07-27 21:46:04 +00001593 return SDValue(); // Not a constant vector, not a splat.
Scott Michel4ec722e2008-07-16 17:17:29 +00001594
Duncan Sands92c43912008-06-06 12:08:01 +00001595 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001596 default:
1597 case MVT::v4f32: {
1598 uint32_t Value32 = SplatBits;
1599 assert(SplatSize == 4
Scott Michel5a6f17b2008-01-30 02:55:46 +00001600 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel8efdca42007-12-04 22:23:35 +00001601 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001602 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001603 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001604 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001605 break;
1606 }
1607 case MVT::v2f64: {
1608 uint64_t f64val = SplatBits;
1609 assert(SplatSize == 8
Scott Michelc630c412008-11-24 17:11:17 +00001610 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel8efdca42007-12-04 22:23:35 +00001611 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman8181bd12008-07-27 21:46:04 +00001612 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel8efdca42007-12-04 22:23:35 +00001613 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001614 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel8efdca42007-12-04 22:23:35 +00001615 break;
1616 }
1617 case MVT::v16i8: {
1618 // 8-bit constants have to be expanded to 16-bits
1619 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman8181bd12008-07-27 21:46:04 +00001620 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001621 for (int i = 0; i < 8; ++i)
1622 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1623 return DAG.getNode(ISD::BIT_CONVERT, VT,
1624 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1625 }
1626 case MVT::v8i16: {
1627 unsigned short Value16;
Scott Michel4ec722e2008-07-16 17:17:29 +00001628 if (SplatSize == 2)
Scott Michel8efdca42007-12-04 22:23:35 +00001629 Value16 = (unsigned short) (SplatBits & 0xffff);
1630 else
1631 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman8181bd12008-07-27 21:46:04 +00001632 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1633 SDValue Ops[8];
Scott Michel8efdca42007-12-04 22:23:35 +00001634 for (int i = 0; i < 8; ++i) Ops[i] = T;
1635 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1636 }
1637 case MVT::v4i32: {
1638 unsigned int Value = SplatBits;
Dan Gohman8181bd12008-07-27 21:46:04 +00001639 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel8efdca42007-12-04 22:23:35 +00001640 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1641 }
1642 case MVT::v2i64: {
1643 uint64_t val = SplatBits;
1644 uint32_t upper = uint32_t(val >> 32);
1645 uint32_t lower = uint32_t(val);
1646
Scott Michelbcc7b672008-03-06 04:02:54 +00001647 if (upper == lower) {
1648 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman8181bd12008-07-27 21:46:04 +00001649 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michelbcc7b672008-03-06 04:02:54 +00001650 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michel6baba072008-03-05 23:02:02 +00001651 } else {
Dan Gohman8181bd12008-07-27 21:46:04 +00001652 SDValue LO32;
1653 SDValue HI32;
1654 SmallVector<SDValue, 16> ShufBytes;
1655 SDValue Result;
Scott Michel8efdca42007-12-04 22:23:35 +00001656 bool upper_special, lower_special;
1657
1658 // NOTE: This code creates common-case shuffle masks that can be easily
1659 // detected as common expressions. It is not attempting to create highly
1660 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1661
1662 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michelc630c412008-11-24 17:11:17 +00001663 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1664 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel8efdca42007-12-04 22:23:35 +00001665
1666 // Create lower vector if not a special pattern
1667 if (!lower_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001668 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001669 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1670 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1671 LO32C, LO32C, LO32C, LO32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001672 }
1673
1674 // Create upper vector if not a special pattern
1675 if (!upper_special) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001676 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001677 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1678 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1679 HI32C, HI32C, HI32C, HI32C));
Scott Michel8efdca42007-12-04 22:23:35 +00001680 }
1681
1682 // If either upper or lower are special, then the two input operands are
1683 // the same (basically, one of them is a "don't care")
1684 if (lower_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001685 LO32 = HI32;
Scott Michel8efdca42007-12-04 22:23:35 +00001686 if (upper_special)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001687 HI32 = LO32;
Scott Michel8efdca42007-12-04 22:23:35 +00001688 if (lower_special && upper_special) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001689 // Unhappy situation... both upper and lower are special, so punt with
1690 // a target constant:
Dan Gohman8181bd12008-07-27 21:46:04 +00001691 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001692 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel8efdca42007-12-04 22:23:35 +00001693 Zero, Zero);
1694 }
1695
1696 for (int i = 0; i < 4; ++i) {
Scott Michel67224b22008-06-02 22:18:03 +00001697 uint64_t val = 0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001698 for (int j = 0; j < 4; ++j) {
Dan Gohman8181bd12008-07-27 21:46:04 +00001699 SDValue V;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001700 bool process_upper, process_lower;
Scott Michel67224b22008-06-02 22:18:03 +00001701 val <<= 8;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001702 process_upper = (upper_special && (i & 1) == 0);
1703 process_lower = (lower_special && (i & 1) == 1);
Scott Michel8efdca42007-12-04 22:23:35 +00001704
Scott Michel5a6f17b2008-01-30 02:55:46 +00001705 if (process_upper || process_lower) {
1706 if ((process_upper && upper == 0)
1707 || (process_lower && lower == 0))
Scott Michel67224b22008-06-02 22:18:03 +00001708 val |= 0x80;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001709 else if ((process_upper && upper == 0xffffffff)
1710 || (process_lower && lower == 0xffffffff))
Scott Michel67224b22008-06-02 22:18:03 +00001711 val |= 0xc0;
Scott Michel5a6f17b2008-01-30 02:55:46 +00001712 else if ((process_upper && upper == 0x80000000)
1713 || (process_lower && lower == 0x80000000))
Scott Michel67224b22008-06-02 22:18:03 +00001714 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001715 } else
Scott Michel67224b22008-06-02 22:18:03 +00001716 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel5a6f17b2008-01-30 02:55:46 +00001717 }
Scott Michel67224b22008-06-02 22:18:03 +00001718
1719 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001720 }
1721
1722 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel67224b22008-06-02 22:18:03 +00001723 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001724 &ShufBytes[0], ShufBytes.size()));
Scott Michel8efdca42007-12-04 22:23:35 +00001725 }
1726 }
1727 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001728
Dan Gohman8181bd12008-07-27 21:46:04 +00001729 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001730}
1731
1732/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1733/// which the Cell can operate. The code inspects V3 to ascertain whether the
1734/// permutation vector, V3, is monotonically increasing with one "exception"
1735/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel56a125e2008-11-22 23:50:42 +00001736/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel8efdca42007-12-04 22:23:35 +00001737/// In either case, the net result is going to eventually invoke SHUFB to
1738/// permute/shuffle the bytes from V1 and V2.
1739/// \note
Scott Michel56a125e2008-11-22 23:50:42 +00001740/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel8efdca42007-12-04 22:23:35 +00001741/// control word for byte/halfword/word insertion. This takes care of a single
1742/// element move from V2 into V1.
1743/// \note
1744/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman8181bd12008-07-27 21:46:04 +00001745static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1746 SDValue V1 = Op.getOperand(0);
1747 SDValue V2 = Op.getOperand(1);
1748 SDValue PermMask = Op.getOperand(2);
Scott Michel4ec722e2008-07-16 17:17:29 +00001749
Scott Michel8efdca42007-12-04 22:23:35 +00001750 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel4ec722e2008-07-16 17:17:29 +00001751
Scott Michel8efdca42007-12-04 22:23:35 +00001752 // If we have a single element being moved from V1 to V2, this can be handled
1753 // using the C*[DX] compute mask instructions, but the vector elements have
1754 // to be monotonically increasing with one exception element.
Duncan Sands92c43912008-06-06 12:08:01 +00001755 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel8efdca42007-12-04 22:23:35 +00001756 unsigned EltsFromV2 = 0;
1757 unsigned V2Elt = 0;
1758 unsigned V2EltIdx0 = 0;
1759 unsigned CurrElt = 0;
1760 bool monotonic = true;
1761 if (EltVT == MVT::i8)
1762 V2EltIdx0 = 16;
1763 else if (EltVT == MVT::i16)
1764 V2EltIdx0 = 8;
1765 else if (EltVT == MVT::i32)
1766 V2EltIdx0 = 4;
1767 else
1768 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1769
1770 for (unsigned i = 0, e = PermMask.getNumOperands();
1771 EltsFromV2 <= 1 && monotonic && i != e;
1772 ++i) {
1773 unsigned SrcElt;
1774 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1775 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001776 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001777 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001778
1779 if (SrcElt >= V2EltIdx0) {
1780 ++EltsFromV2;
1781 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1782 } else if (CurrElt != SrcElt) {
1783 monotonic = false;
1784 }
1785
1786 ++CurrElt;
1787 }
1788
1789 if (EltsFromV2 == 1 && monotonic) {
1790 // Compute mask and shuffle
1791 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001792 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1793 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands92c43912008-06-06 12:08:01 +00001794 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel8efdca42007-12-04 22:23:35 +00001795 // Initialize temporary register to 0
Dan Gohman8181bd12008-07-27 21:46:04 +00001796 SDValue InitTempReg =
Scott Michel8efdca42007-12-04 22:23:35 +00001797 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel56a125e2008-11-22 23:50:42 +00001798 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman8181bd12008-07-27 21:46:04 +00001799 SDValue ShufMaskOp =
Scott Michel0718cd82008-12-01 17:56:02 +00001800 DAG.getNode(SPUISD::SHUFFLE_MASK, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001801 DAG.getTargetConstant(V2Elt, MVT::i32),
1802 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel8efdca42007-12-04 22:23:35 +00001803 // Use shuffle mask in SHUFB synthetic instruction:
1804 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1805 } else {
Gabor Greife9f7f582008-08-31 15:37:04 +00001806 // Convert the SHUFFLE_VECTOR mask's input element units to the
1807 // actual bytes.
Duncan Sands92c43912008-06-06 12:08:01 +00001808 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel4ec722e2008-07-16 17:17:29 +00001809
Dan Gohman8181bd12008-07-27 21:46:04 +00001810 SmallVector<SDValue, 16> ResultMask;
Scott Michel8efdca42007-12-04 22:23:35 +00001811 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1812 unsigned SrcElt;
1813 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel5a6f17b2008-01-30 02:55:46 +00001814 SrcElt = 0;
Scott Michel4ec722e2008-07-16 17:17:29 +00001815 else
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001816 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel4ec722e2008-07-16 17:17:29 +00001817
Scott Michel97872d32008-02-23 18:41:37 +00001818 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00001819 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1820 MVT::i8));
Scott Michel8efdca42007-12-04 22:23:35 +00001821 }
1822 }
Scott Michel4ec722e2008-07-16 17:17:29 +00001823
Dan Gohman8181bd12008-07-27 21:46:04 +00001824 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel0718cd82008-12-01 17:56:02 +00001825 &ResultMask[0], ResultMask.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001826 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1827 }
1828}
1829
Dan Gohman8181bd12008-07-27 21:46:04 +00001830static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1831 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel8efdca42007-12-04 22:23:35 +00001832
Gabor Greif1c80d112008-08-28 21:40:38 +00001833 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel8efdca42007-12-04 22:23:35 +00001834 // For a constant, build the appropriate constant vector, which will
1835 // eventually simplify to a vector register load.
1836
Gabor Greif1c80d112008-08-28 21:40:38 +00001837 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman8181bd12008-07-27 21:46:04 +00001838 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands92c43912008-06-06 12:08:01 +00001839 MVT VT;
Scott Michel8efdca42007-12-04 22:23:35 +00001840 size_t n_copies;
1841
1842 // Create a constant vector:
Duncan Sands92c43912008-06-06 12:08:01 +00001843 switch (Op.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001844 default: assert(0 && "Unexpected constant value type in "
Scott Michel5a6f17b2008-01-30 02:55:46 +00001845 "LowerSCALAR_TO_VECTOR");
Scott Michel8efdca42007-12-04 22:23:35 +00001846 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1847 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1848 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1849 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1850 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1851 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1852 }
1853
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00001854 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel8efdca42007-12-04 22:23:35 +00001855 for (size_t j = 0; j < n_copies; ++j)
1856 ConstVecValues.push_back(CValue);
1857
1858 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001859 &ConstVecValues[0], ConstVecValues.size());
Scott Michel8efdca42007-12-04 22:23:35 +00001860 } else {
1861 // Otherwise, copy the value from one register to another:
Duncan Sands92c43912008-06-06 12:08:01 +00001862 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00001863 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1864 case MVT::i8:
1865 case MVT::i16:
1866 case MVT::i32:
1867 case MVT::i64:
1868 case MVT::f32:
1869 case MVT::f64:
1870 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1871 }
1872 }
1873
Dan Gohman8181bd12008-07-27 21:46:04 +00001874 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00001875}
1876
Dan Gohman8181bd12008-07-27 21:46:04 +00001877static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00001878 switch (Op.getValueType().getSimpleVT()) {
1879 default:
1880 cerr << "CellSPU: Unknown vector multiplication, got "
1881 << Op.getValueType().getMVTString()
1882 << "\n";
1883 abort();
1884 /*NOTREACHED*/
1885
Scott Michel8efdca42007-12-04 22:23:35 +00001886 case MVT::v4i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001887 SDValue rA = Op.getOperand(0);
1888 SDValue rB = Op.getOperand(1);
1889 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1890 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1891 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1892 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel8efdca42007-12-04 22:23:35 +00001893
1894 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1895 break;
1896 }
1897
1898 // Multiply two v8i16 vectors (pipeline friendly version):
1899 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1900 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1901 // c) Use SELB to select upper and lower halves from the intermediate results
1902 //
Scott Michel67224b22008-06-02 22:18:03 +00001903 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel8efdca42007-12-04 22:23:35 +00001904 // dual-issue. This code does manage to do this, even if it's a little on
1905 // the wacky side
1906 case MVT::v8i16: {
1907 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00001908 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman8181bd12008-07-27 21:46:04 +00001909 SDValue Chain = Op.getOperand(0);
1910 SDValue rA = Op.getOperand(0);
1911 SDValue rB = Op.getOperand(1);
Chris Lattner1b989192007-12-31 04:13:23 +00001912 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1913 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00001914
Dan Gohman8181bd12008-07-27 21:46:04 +00001915 SDValue FSMBOp =
Scott Michel8efdca42007-12-04 22:23:35 +00001916 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel67224b22008-06-02 22:18:03 +00001917 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001918 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel8efdca42007-12-04 22:23:35 +00001919
Dan Gohman8181bd12008-07-27 21:46:04 +00001920 SDValue HHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001921 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001922 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001923
Dan Gohman8181bd12008-07-27 21:46:04 +00001924 SDValue HHProd_v4i32 =
Scott Michel8efdca42007-12-04 22:23:35 +00001925 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001926 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001927
1928 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001929 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1930 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1931 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1932 HHProd_v4i32,
1933 DAG.getConstant(16, MVT::i16))),
1934 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel8efdca42007-12-04 22:23:35 +00001935 }
1936
1937 // This M00sE is N@stI! (apologies to Monty Python)
1938 //
1939 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1940 // is to break it all apart, sign extend, and reassemble the various
1941 // intermediate products.
1942 case MVT::v16i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00001943 SDValue rA = Op.getOperand(0);
1944 SDValue rB = Op.getOperand(1);
1945 SDValue c8 = DAG.getConstant(8, MVT::i32);
1946 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001947
Dan Gohman8181bd12008-07-27 21:46:04 +00001948 SDValue LLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001949 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001950 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1951 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00001952
Dan Gohman8181bd12008-07-27 21:46:04 +00001953 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001954
Dan Gohman8181bd12008-07-27 21:46:04 +00001955 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001956
Dan Gohman8181bd12008-07-27 21:46:04 +00001957 SDValue LHProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001958 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001959 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel8efdca42007-12-04 22:23:35 +00001960
Dan Gohman8181bd12008-07-27 21:46:04 +00001961 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michelbc5fbc12008-04-30 00:30:08 +00001962 DAG.getConstant(0x2222, MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00001963
Dan Gohman8181bd12008-07-27 21:46:04 +00001964 SDValue LoProdParts =
Scott Michel97872d32008-02-23 18:41:37 +00001965 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1966 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1967 LLProd, LHProd, FSMBmask));
Scott Michel8efdca42007-12-04 22:23:35 +00001968
Dan Gohman8181bd12008-07-27 21:46:04 +00001969 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00001970
Dan Gohman8181bd12008-07-27 21:46:04 +00001971 SDValue LoProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001972 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michel97872d32008-02-23 18:41:37 +00001973 LoProdParts,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001974 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1975 LoProdMask, LoProdMask,
1976 LoProdMask, LoProdMask));
Scott Michel8efdca42007-12-04 22:23:35 +00001977
Dan Gohman8181bd12008-07-27 21:46:04 +00001978 SDValue rAH =
Scott Michel8efdca42007-12-04 22:23:35 +00001979 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001980 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001981
Dan Gohman8181bd12008-07-27 21:46:04 +00001982 SDValue rBH =
Scott Michel8efdca42007-12-04 22:23:35 +00001983 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001984 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel8efdca42007-12-04 22:23:35 +00001985
Dan Gohman8181bd12008-07-27 21:46:04 +00001986 SDValue HLProd =
Scott Michel8efdca42007-12-04 22:23:35 +00001987 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001988 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1989 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel8efdca42007-12-04 22:23:35 +00001990
Dan Gohman8181bd12008-07-27 21:46:04 +00001991 SDValue HHProd_1 =
Scott Michel8efdca42007-12-04 22:23:35 +00001992 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00001993 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00001994 DAG.getNode(SPUISD::VEC_SRA,
1995 MVT::v4i32, rAH, c8)),
Scott Michel5a6f17b2008-01-30 02:55:46 +00001996 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greife9f7f582008-08-31 15:37:04 +00001997 DAG.getNode(SPUISD::VEC_SRA,
1998 MVT::v4i32, rBH, c8)));
Scott Michel8efdca42007-12-04 22:23:35 +00001999
Dan Gohman8181bd12008-07-27 21:46:04 +00002000 SDValue HHProd =
Scott Michel97872d32008-02-23 18:41:37 +00002001 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2002 HLProd,
2003 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2004 FSMBmask);
Scott Michel8efdca42007-12-04 22:23:35 +00002005
Dan Gohman8181bd12008-07-27 21:46:04 +00002006 SDValue HiProd =
Scott Michel97872d32008-02-23 18:41:37 +00002007 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel8efdca42007-12-04 22:23:35 +00002008
2009 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002010 DAG.getNode(ISD::OR, MVT::v4i32,
2011 LoProd, HiProd));
Scott Michel8efdca42007-12-04 22:23:35 +00002012 }
Scott Michel8efdca42007-12-04 22:23:35 +00002013 }
2014
Dan Gohman8181bd12008-07-27 21:46:04 +00002015 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002016}
2017
Dan Gohman8181bd12008-07-27 21:46:04 +00002018static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel8efdca42007-12-04 22:23:35 +00002019 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002020 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002021
Dan Gohman8181bd12008-07-27 21:46:04 +00002022 SDValue A = Op.getOperand(0);
2023 SDValue B = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002024 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002025
2026 unsigned VRegBR, VRegC;
2027
2028 if (VT == MVT::f32) {
Chris Lattner1b989192007-12-31 04:13:23 +00002029 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2030 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002031 } else {
Chris Lattner1b989192007-12-31 04:13:23 +00002032 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2033 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002034 }
2035 // TODO: make sure we're feeding FPInterp the right arguments
2036 // Right now: fi B, frest(B)
2037
2038 // Computes BRcpl =
2039 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman8181bd12008-07-27 21:46:04 +00002040 SDValue BRcpl =
Scott Michel4ec722e2008-07-16 17:17:29 +00002041 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2042 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002043 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002044
Scott Michel8efdca42007-12-04 22:23:35 +00002045 // Computes A * BRcpl and stores in a temporary register
Dan Gohman8181bd12008-07-27 21:46:04 +00002046 SDValue AxBRcpl =
Scott Michel8efdca42007-12-04 22:23:35 +00002047 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel4ec722e2008-07-16 17:17:29 +00002048 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002049 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel8efdca42007-12-04 22:23:35 +00002050 // What's the Chain variable do? It's magic!
2051 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel4ec722e2008-07-16 17:17:29 +00002052
2053 return DAG.getNode(ISD::FADD, VT,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002054 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel4ec722e2008-07-16 17:17:29 +00002055 DAG.getNode(ISD::FMUL, VT,
2056 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002057 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel4ec722e2008-07-16 17:17:29 +00002058 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002059 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel8efdca42007-12-04 22:23:35 +00002060}
2061
Dan Gohman8181bd12008-07-27 21:46:04 +00002062static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002063 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002064 SDValue N = Op.getOperand(0);
2065 SDValue Elt = Op.getOperand(1);
Scott Michel56a125e2008-11-22 23:50:42 +00002066 SDValue retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002067
Scott Michel56a125e2008-11-22 23:50:42 +00002068 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2069 // Constant argument:
2070 int EltNo = (int) C->getZExtValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002071
Scott Michel56a125e2008-11-22 23:50:42 +00002072 // sanity checks:
2073 if (VT == MVT::i8 && EltNo >= 16)
2074 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2075 else if (VT == MVT::i16 && EltNo >= 8)
2076 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2077 else if (VT == MVT::i32 && EltNo >= 4)
2078 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2079 else if (VT == MVT::i64 && EltNo >= 2)
2080 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel8efdca42007-12-04 22:23:35 +00002081
Scott Michel56a125e2008-11-22 23:50:42 +00002082 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2083 // i32 and i64: Element 0 is the preferred slot
Scott Michelc630c412008-11-24 17:11:17 +00002084 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel56a125e2008-11-22 23:50:42 +00002085 }
Scott Michel8efdca42007-12-04 22:23:35 +00002086
Scott Michel56a125e2008-11-22 23:50:42 +00002087 // Need to generate shuffle mask and extract:
2088 int prefslot_begin = -1, prefslot_end = -1;
2089 int elt_byte = EltNo * VT.getSizeInBits() / 8;
2090
2091 switch (VT.getSimpleVT()) {
2092 default:
2093 assert(false && "Invalid value type!");
2094 case MVT::i8: {
2095 prefslot_begin = prefslot_end = 3;
2096 break;
2097 }
2098 case MVT::i16: {
2099 prefslot_begin = 2; prefslot_end = 3;
2100 break;
2101 }
2102 case MVT::i32:
2103 case MVT::f32: {
2104 prefslot_begin = 0; prefslot_end = 3;
2105 break;
2106 }
2107 case MVT::i64:
2108 case MVT::f64: {
2109 prefslot_begin = 0; prefslot_end = 7;
2110 break;
2111 }
2112 }
2113
2114 assert(prefslot_begin != -1 && prefslot_end != -1 &&
2115 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2116
2117 unsigned int ShufBytes[16];
2118 for (int i = 0; i < 16; ++i) {
2119 // zero fill uppper part of preferred slot, don't care about the
2120 // other slots:
2121 unsigned int mask_val;
2122 if (i <= prefslot_end) {
2123 mask_val =
2124 ((i < prefslot_begin)
2125 ? 0x80
2126 : elt_byte + (i - prefslot_begin));
2127
2128 ShufBytes[i] = mask_val;
2129 } else
2130 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2131 }
2132
2133 SDValue ShufMask[4];
2134 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
2135 unsigned bidx = i / 4;
2136 unsigned int bits = ((ShufBytes[bidx] << 24) |
2137 (ShufBytes[bidx+1] << 16) |
2138 (ShufBytes[bidx+2] << 8) |
2139 ShufBytes[bidx+3]);
2140 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
2141 }
2142
2143 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2144 &ShufMask[0],
2145 sizeof(ShufMask) / sizeof(ShufMask[0]));
2146
Scott Michelc630c412008-11-24 17:11:17 +00002147 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel56a125e2008-11-22 23:50:42 +00002148 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2149 N, N, ShufMaskVec));
2150 } else {
2151 // Variable index: Rotate the requested element into slot 0, then replicate
2152 // slot 0 across the vector
2153 MVT VecVT = N.getValueType();
2154 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2155 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2156 abort();
2157 }
2158
2159 // Make life easier by making sure the index is zero-extended to i32
2160 if (Elt.getValueType() != MVT::i32)
2161 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2162
2163 // Scale the index to a bit/byte shift quantity
2164 APInt scaleFactor =
Scott Michelc630c412008-11-24 17:11:17 +00002165 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2166 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel56a125e2008-11-22 23:50:42 +00002167 SDValue vecShift;
Scott Michel56a125e2008-11-22 23:50:42 +00002168
Scott Michelc630c412008-11-24 17:11:17 +00002169 if (scaleShift > 0) {
2170 // Scale the shift factor:
Scott Michel56a125e2008-11-22 23:50:42 +00002171 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel0718cd82008-12-01 17:56:02 +00002172 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel56a125e2008-11-22 23:50:42 +00002173 }
2174
Scott Michelc630c412008-11-24 17:11:17 +00002175 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2176
2177 // Replicate the bytes starting at byte 0 across the entire vector (for
2178 // consistency with the notion of a unified register set)
Scott Michel56a125e2008-11-22 23:50:42 +00002179 SDValue replicate;
2180
2181 switch (VT.getSimpleVT()) {
2182 default:
2183 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2184 abort();
2185 /*NOTREACHED*/
2186 case MVT::i8: {
Scott Michelc630c412008-11-24 17:11:17 +00002187 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002188 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2189 factor, factor);
2190 break;
2191 }
2192 case MVT::i16: {
Scott Michelc630c412008-11-24 17:11:17 +00002193 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel56a125e2008-11-22 23:50:42 +00002194 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2195 factor, factor);
2196 break;
2197 }
2198 case MVT::i32:
2199 case MVT::f32: {
2200 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2201 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2202 factor, factor);
2203 break;
2204 }
2205 case MVT::i64:
2206 case MVT::f64: {
2207 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2208 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2209 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2210 loFactor, hiFactor);
2211 break;
2212 }
2213 }
2214
Scott Michelc630c412008-11-24 17:11:17 +00002215 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel0718cd82008-12-01 17:56:02 +00002216 DAG.getNode(SPUISD::SHUFB, VecVT,
2217 vecShift, vecShift, replicate));
Scott Michel8efdca42007-12-04 22:23:35 +00002218 }
2219
Scott Michel56a125e2008-11-22 23:50:42 +00002220 return retval;
Scott Michel8efdca42007-12-04 22:23:35 +00002221}
2222
Dan Gohman8181bd12008-07-27 21:46:04 +00002223static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2224 SDValue VecOp = Op.getOperand(0);
2225 SDValue ValOp = Op.getOperand(1);
2226 SDValue IdxOp = Op.getOperand(2);
Duncan Sands92c43912008-06-06 12:08:01 +00002227 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002228
2229 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2230 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2231
Duncan Sands92c43912008-06-06 12:08:01 +00002232 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel0718cd82008-12-01 17:56:02 +00002233 // Use $sp ($1) because it's always 16-byte aligned and it's available:
2234 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
2235 DAG.getRegister(SPU::R1, PtrVT),
2236 DAG.getConstant(CN->getSExtValue(), PtrVT));
2237 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, VT, Pointer);
Scott Michel8efdca42007-12-04 22:23:35 +00002238
Dan Gohman8181bd12008-07-27 21:46:04 +00002239 SDValue result =
Scott Michel8efdca42007-12-04 22:23:35 +00002240 DAG.getNode(SPUISD::SHUFB, VT,
2241 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
Scott Michel0718cd82008-12-01 17:56:02 +00002242 VecOp,
2243 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, ShufMask));
Scott Michel8efdca42007-12-04 22:23:35 +00002244
2245 return result;
2246}
2247
Dan Gohman8181bd12008-07-27 21:46:04 +00002248static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002249{
Dan Gohman8181bd12008-07-27 21:46:04 +00002250 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel8efdca42007-12-04 22:23:35 +00002251
2252 assert(Op.getValueType() == MVT::i8);
2253 switch (Opc) {
2254 default:
2255 assert(0 && "Unhandled i8 math operator");
2256 /*NOTREACHED*/
2257 break;
2258 case ISD::SUB: {
2259 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2260 // the result:
Dan Gohman8181bd12008-07-27 21:46:04 +00002261 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002262 N0 = (N0.getOpcode() != ISD::Constant
2263 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002264 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2265 MVT::i16));
Scott Michel8efdca42007-12-04 22:23:35 +00002266 N1 = (N1.getOpcode() != ISD::Constant
2267 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002268 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2269 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002270 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002271 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel4ec722e2008-07-16 17:17:29 +00002272 }
Scott Michel8efdca42007-12-04 22:23:35 +00002273 case ISD::ROTR:
2274 case ISD::ROTL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002275 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002276 unsigned N1Opc;
2277 N0 = (N0.getOpcode() != ISD::Constant
2278 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002279 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2280 MVT::i16));
Duncan Sands7aef60d2008-10-30 19:24:28 +00002281 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greife9f7f582008-08-31 15:37:04 +00002282 ? ISD::ZERO_EXTEND
2283 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002284 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sands7aef60d2008-10-30 19:24:28 +00002285 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002286 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sands7aef60d2008-10-30 19:24:28 +00002287 MVT::i32));
Dan Gohman8181bd12008-07-27 21:46:04 +00002288 SDValue ExpandArg =
Scott Michel8efdca42007-12-04 22:23:35 +00002289 DAG.getNode(ISD::OR, MVT::i16, N0,
2290 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sands7aef60d2008-10-30 19:24:28 +00002291 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel4ec722e2008-07-16 17:17:29 +00002292 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002293 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2294 }
2295 case ISD::SRL:
2296 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002297 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002298 unsigned N1Opc;
2299 N0 = (N0.getOpcode() != ISD::Constant
2300 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002301 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2302 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002303 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2304 ? ISD::ZERO_EXTEND
2305 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002306 N1 = (N1.getOpcode() != ISD::Constant
2307 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002308 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2309 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002310 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002311 DAG.getNode(Opc, MVT::i16, N0, N1));
2312 }
2313 case ISD::SRA: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002314 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002315 unsigned N1Opc;
2316 N0 = (N0.getOpcode() != ISD::Constant
2317 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002318 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2319 MVT::i16));
Gabor Greife9f7f582008-08-31 15:37:04 +00002320 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2321 ? ISD::SIGN_EXTEND
2322 : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002323 N1 = (N1.getOpcode() != ISD::Constant
2324 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002325 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2326 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002327 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002328 DAG.getNode(Opc, MVT::i16, N0, N1));
2329 }
2330 case ISD::MUL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002331 SDValue N1 = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002332 unsigned N1Opc;
2333 N0 = (N0.getOpcode() != ISD::Constant
2334 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002335 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2336 MVT::i16));
Duncan Sandsec142ee2008-06-08 20:54:56 +00002337 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel8efdca42007-12-04 22:23:35 +00002338 N1 = (N1.getOpcode() != ISD::Constant
2339 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002340 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2341 MVT::i16));
Scott Michel4ec722e2008-07-16 17:17:29 +00002342 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel8efdca42007-12-04 22:23:35 +00002343 DAG.getNode(Opc, MVT::i16, N0, N1));
2344 break;
2345 }
2346 }
2347
Dan Gohman8181bd12008-07-27 21:46:04 +00002348 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002349}
2350
Dan Gohman8181bd12008-07-27 21:46:04 +00002351static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michel97872d32008-02-23 18:41:37 +00002352{
Duncan Sands92c43912008-06-06 12:08:01 +00002353 MVT VT = Op.getValueType();
2354 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002355
Dan Gohman8181bd12008-07-27 21:46:04 +00002356 SDValue Op0 = Op.getOperand(0);
Scott Michel97872d32008-02-23 18:41:37 +00002357
2358 switch (Opc) {
2359 case ISD::ZERO_EXTEND:
2360 case ISD::SIGN_EXTEND:
2361 case ISD::ANY_EXTEND: {
Duncan Sands92c43912008-06-06 12:08:01 +00002362 MVT Op0VT = Op0.getValueType();
2363 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michel97872d32008-02-23 18:41:37 +00002364
2365 assert(Op0VT == MVT::i32
2366 && "CellSPU: Zero/sign extending something other than i32");
2367
Scott Michelc630c412008-11-24 17:11:17 +00002368 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2369
Dan Gohman8181bd12008-07-27 21:46:04 +00002370 SDValue PromoteScalar =
Scott Michelc630c412008-11-24 17:11:17 +00002371 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
Scott Michel97872d32008-02-23 18:41:37 +00002372
Scott Michelc630c412008-11-24 17:11:17 +00002373 if (Opc != ISD::SIGN_EXTEND) {
Scott Michelf2df6cb2008-11-24 18:20:46 +00002374 // Use a shuffle to zero extend the i32 to i64 directly:
2375 SDValue shufMask =
2376 DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2377 DAG.getConstant(0x80808080, MVT::i32),
2378 DAG.getConstant(0x00010203, MVT::i32),
2379 DAG.getConstant(0x80808080, MVT::i32),
2380 DAG.getConstant(0x08090a0b, MVT::i32));
2381 SDValue zextShuffle =
2382 DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2383 PromoteScalar, PromoteScalar, shufMask);
2384
Scott Michelc630c412008-11-24 17:11:17 +00002385 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michelf2df6cb2008-11-24 18:20:46 +00002386 DAG.getNode(ISD::BIT_CONVERT, VecVT, zextShuffle));
Scott Michelc630c412008-11-24 17:11:17 +00002387 } else {
2388 // SPU has no "rotate quadword and replicate bit 0" (i.e. rotate/shift
2389 // right and propagate the sign bit) instruction.
Scott Michelf2df6cb2008-11-24 18:20:46 +00002390 SDValue RotQuad =
2391 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, Op0VecVT,
2392 PromoteScalar, DAG.getConstant(4, MVT::i32));
Scott Michelc630c412008-11-24 17:11:17 +00002393 SDValue SignQuad =
2394 DAG.getNode(SPUISD::VEC_SRA, Op0VecVT,
2395 PromoteScalar, DAG.getConstant(32, MVT::i32));
2396 SDValue SelMask =
2397 DAG.getNode(SPUISD::SELECT_MASK, Op0VecVT,
2398 DAG.getConstant(0xf0f0, MVT::i16));
2399 SDValue CombineQuad =
2400 DAG.getNode(SPUISD::SELB, Op0VecVT,
2401 SignQuad, RotQuad, SelMask);
2402
2403 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2404 DAG.getNode(ISD::BIT_CONVERT, VecVT, CombineQuad));
2405 }
Scott Michel97872d32008-02-23 18:41:37 +00002406 }
2407
Scott Michel67224b22008-06-02 22:18:03 +00002408 case ISD::ADD: {
2409 // Turn operands into vectors to satisfy type checking (shufb works on
2410 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002411 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002412 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002413 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002414 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002415 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002416
2417 // Create the shuffle mask for "rotating" the borrow up one register slot
2418 // once the borrow is generated.
2419 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2420 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2421 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2422 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2423
Dan Gohman8181bd12008-07-27 21:46:04 +00002424 SDValue CarryGen =
Scott Michel67224b22008-06-02 22:18:03 +00002425 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002426 SDValue ShiftedCarry =
Scott Michel67224b22008-06-02 22:18:03 +00002427 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2428 CarryGen, CarryGen,
2429 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2430 &ShufBytes[0], ShufBytes.size()));
2431
Scott Michelc630c412008-11-24 17:11:17 +00002432 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002433 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2434 Op0, Op1, ShiftedCarry));
2435 }
2436
2437 case ISD::SUB: {
2438 // Turn operands into vectors to satisfy type checking (shufb works on
2439 // vectors)
Dan Gohman8181bd12008-07-27 21:46:04 +00002440 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002441 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002442 SDValue Op1 =
Scott Michel67224b22008-06-02 22:18:03 +00002443 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman8181bd12008-07-27 21:46:04 +00002444 SmallVector<SDValue, 16> ShufBytes;
Scott Michel67224b22008-06-02 22:18:03 +00002445
2446 // Create the shuffle mask for "rotating" the borrow up one register slot
2447 // once the borrow is generated.
2448 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2449 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2450 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2451 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2452
Dan Gohman8181bd12008-07-27 21:46:04 +00002453 SDValue BorrowGen =
Scott Michel67224b22008-06-02 22:18:03 +00002454 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman8181bd12008-07-27 21:46:04 +00002455 SDValue ShiftedBorrow =
Scott Michel67224b22008-06-02 22:18:03 +00002456 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2457 BorrowGen, BorrowGen,
2458 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2459 &ShufBytes[0], ShufBytes.size()));
2460
Scott Michelc630c412008-11-24 17:11:17 +00002461 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002462 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2463 Op0, Op1, ShiftedBorrow));
2464 }
2465
Scott Michel97872d32008-02-23 18:41:37 +00002466 case ISD::SHL: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002467 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002468 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002469 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2470 SDValue MaskLower =
Scott Michel97872d32008-02-23 18:41:37 +00002471 DAG.getNode(SPUISD::SELB, VecVT,
2472 Op0Vec,
2473 DAG.getConstant(0, VecVT),
Scott Michel67224b22008-06-02 22:18:03 +00002474 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michel97872d32008-02-23 18:41:37 +00002475 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman8181bd12008-07-27 21:46:04 +00002476 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002477 DAG.getNode(ISD::SRL, ShiftAmtVT,
2478 ShiftAmt,
2479 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002480 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002481 DAG.getNode(ISD::AND, ShiftAmtVT,
2482 ShiftAmt,
2483 DAG.getConstant(7, ShiftAmtVT));
2484
Scott Michelc630c412008-11-24 17:11:17 +00002485 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel97872d32008-02-23 18:41:37 +00002486 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2487 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2488 MaskLower, ShiftAmtBytes),
2489 ShiftAmtBits));
2490 }
2491
2492 case ISD::SRL: {
Duncan Sands92c43912008-06-06 12:08:01 +00002493 MVT VT = Op.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002494 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002495 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman8181bd12008-07-27 21:46:04 +00002496 SDValue ShiftAmtBytes =
Scott Michel97872d32008-02-23 18:41:37 +00002497 DAG.getNode(ISD::SRL, ShiftAmtVT,
2498 ShiftAmt,
2499 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman8181bd12008-07-27 21:46:04 +00002500 SDValue ShiftAmtBits =
Scott Michel97872d32008-02-23 18:41:37 +00002501 DAG.getNode(ISD::AND, ShiftAmtVT,
2502 ShiftAmt,
2503 DAG.getConstant(7, ShiftAmtVT));
2504
2505 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2506 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2507 Op0, ShiftAmtBytes),
2508 ShiftAmtBits);
2509 }
Scott Michel67224b22008-06-02 22:18:03 +00002510
2511 case ISD::SRA: {
2512 // Promote Op0 to vector
Dan Gohman8181bd12008-07-27 21:46:04 +00002513 SDValue Op0 =
Scott Michel67224b22008-06-02 22:18:03 +00002514 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman8181bd12008-07-27 21:46:04 +00002515 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands92c43912008-06-06 12:08:01 +00002516 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel67224b22008-06-02 22:18:03 +00002517
2518 // Negate variable shift amounts
2519 if (!isa<ConstantSDNode>(ShiftAmt)) {
2520 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2521 DAG.getConstant(0, ShiftVT), ShiftAmt);
2522 }
2523
Dan Gohman8181bd12008-07-27 21:46:04 +00002524 SDValue UpperHalfSign =
Scott Michelc630c412008-11-24 17:11:17 +00002525 DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i32,
Scott Michel67224b22008-06-02 22:18:03 +00002526 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2527 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2528 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman8181bd12008-07-27 21:46:04 +00002529 SDValue UpperHalfSignMask =
Scott Michel67224b22008-06-02 22:18:03 +00002530 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman8181bd12008-07-27 21:46:04 +00002531 SDValue UpperLowerMask =
Scott Michel67224b22008-06-02 22:18:03 +00002532 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2533 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman8181bd12008-07-27 21:46:04 +00002534 SDValue UpperLowerSelect =
Scott Michel67224b22008-06-02 22:18:03 +00002535 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2536 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman8181bd12008-07-27 21:46:04 +00002537 SDValue RotateLeftBytes =
Scott Michel67224b22008-06-02 22:18:03 +00002538 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2539 UpperLowerSelect, ShiftAmt);
Dan Gohman8181bd12008-07-27 21:46:04 +00002540 SDValue RotateLeftBits =
Scott Michel67224b22008-06-02 22:18:03 +00002541 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2542 RotateLeftBytes, ShiftAmt);
2543
Scott Michelc630c412008-11-24 17:11:17 +00002544 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel67224b22008-06-02 22:18:03 +00002545 RotateLeftBits);
2546 }
Scott Michel97872d32008-02-23 18:41:37 +00002547 }
2548
Dan Gohman8181bd12008-07-27 21:46:04 +00002549 return SDValue();
Scott Michel97872d32008-02-23 18:41:37 +00002550}
2551
Scott Michel8efdca42007-12-04 22:23:35 +00002552//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman8181bd12008-07-27 21:46:04 +00002553static SDValue
2554LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2555 SDValue ConstVec;
2556 SDValue Arg;
Duncan Sands92c43912008-06-06 12:08:01 +00002557 MVT VT = Op.getValueType();
Scott Michel8efdca42007-12-04 22:23:35 +00002558
2559 ConstVec = Op.getOperand(0);
2560 Arg = Op.getOperand(1);
Gabor Greif1c80d112008-08-28 21:40:38 +00002561 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2562 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel8efdca42007-12-04 22:23:35 +00002563 ConstVec = ConstVec.getOperand(0);
2564 } else {
2565 ConstVec = Op.getOperand(1);
2566 Arg = Op.getOperand(0);
Gabor Greif1c80d112008-08-28 21:40:38 +00002567 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel5a6f17b2008-01-30 02:55:46 +00002568 ConstVec = ConstVec.getOperand(0);
Scott Michel8efdca42007-12-04 22:23:35 +00002569 }
2570 }
2571 }
2572
Gabor Greif1c80d112008-08-28 21:40:38 +00002573 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel8efdca42007-12-04 22:23:35 +00002574 uint64_t VectorBits[2];
2575 uint64_t UndefBits[2];
2576 uint64_t SplatBits, SplatUndef;
2577 int SplatSize;
2578
Gabor Greif1c80d112008-08-28 21:40:38 +00002579 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002580 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands92c43912008-06-06 12:08:01 +00002581 VT.getVectorElementType().getSizeInBits(),
Scott Michel5a6f17b2008-01-30 02:55:46 +00002582 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002583 SDValue tcVec[16];
2584 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel8efdca42007-12-04 22:23:35 +00002585 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2586
2587 // Turn the BUILD_VECTOR into a set of target constants:
2588 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel5a6f17b2008-01-30 02:55:46 +00002589 tcVec[i] = tc;
Scott Michel8efdca42007-12-04 22:23:35 +00002590
Gabor Greif1c80d112008-08-28 21:40:38 +00002591 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002592 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel8efdca42007-12-04 22:23:35 +00002593 }
2594 }
Nate Begeman7569e762008-07-29 19:07:27 +00002595 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2596 // lowered. Return the operation, rather than a null SDValue.
2597 return Op;
Scott Michel8efdca42007-12-04 22:23:35 +00002598}
2599
2600//! Lower i32 multiplication
Dan Gohman8181bd12008-07-27 21:46:04 +00002601static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel8efdca42007-12-04 22:23:35 +00002602 unsigned Opc) {
Duncan Sands92c43912008-06-06 12:08:01 +00002603 switch (VT.getSimpleVT()) {
Scott Michel8efdca42007-12-04 22:23:35 +00002604 default:
2605 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands92c43912008-06-06 12:08:01 +00002606 << Op.getValueType().getMVTString()
Scott Michel5a6f17b2008-01-30 02:55:46 +00002607 << "\n";
Scott Michel8efdca42007-12-04 22:23:35 +00002608 abort();
2609 /*NOTREACHED*/
2610
2611 case MVT::i32: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002612 SDValue rA = Op.getOperand(0);
2613 SDValue rB = Op.getOperand(1);
Scott Michel8efdca42007-12-04 22:23:35 +00002614
2615 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002616 DAG.getNode(ISD::ADD, MVT::i32,
2617 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2618 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2619 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel8efdca42007-12-04 22:23:35 +00002620 }
2621 }
2622
Dan Gohman8181bd12008-07-27 21:46:04 +00002623 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002624}
2625
2626//! Custom lowering for CTPOP (count population)
2627/*!
2628 Custom lowering code that counts the number ones in the input
2629 operand. SPU has such an instruction, but it counts the number of
2630 ones per byte, which then have to be accumulated.
2631*/
Dan Gohman8181bd12008-07-27 21:46:04 +00002632static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands92c43912008-06-06 12:08:01 +00002633 MVT VT = Op.getValueType();
2634 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel8efdca42007-12-04 22:23:35 +00002635
Duncan Sands92c43912008-06-06 12:08:01 +00002636 switch (VT.getSimpleVT()) {
2637 default:
2638 assert(false && "Invalid value type!");
Scott Michel8efdca42007-12-04 22:23:35 +00002639 case MVT::i8: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002640 SDValue N = Op.getOperand(0);
2641 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002642
Dan Gohman8181bd12008-07-27 21:46:04 +00002643 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2644 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002645
2646 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2647 }
2648
2649 case MVT::i16: {
2650 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002651 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002652
Chris Lattner1b989192007-12-31 04:13:23 +00002653 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002654
Dan Gohman8181bd12008-07-27 21:46:04 +00002655 SDValue N = Op.getOperand(0);
2656 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2657 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sands7aef60d2008-10-30 19:24:28 +00002658 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002659
Dan Gohman8181bd12008-07-27 21:46:04 +00002660 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2661 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002662
2663 // CNTB_result becomes the chain to which all of the virtual registers
2664 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002665 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002666 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002667
Dan Gohman8181bd12008-07-27 21:46:04 +00002668 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002669 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2670
Dan Gohman8181bd12008-07-27 21:46:04 +00002671 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel8efdca42007-12-04 22:23:35 +00002672
2673 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002674 DAG.getNode(ISD::ADD, MVT::i16,
2675 DAG.getNode(ISD::SRL, MVT::i16,
2676 Tmp1, Shift1),
2677 Tmp1),
2678 Mask0);
Scott Michel8efdca42007-12-04 22:23:35 +00002679 }
2680
2681 case MVT::i32: {
2682 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner1b989192007-12-31 04:13:23 +00002683 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel8efdca42007-12-04 22:23:35 +00002684
Chris Lattner1b989192007-12-31 04:13:23 +00002685 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2686 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel8efdca42007-12-04 22:23:35 +00002687
Dan Gohman8181bd12008-07-27 21:46:04 +00002688 SDValue N = Op.getOperand(0);
2689 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2690 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2691 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2692 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel8efdca42007-12-04 22:23:35 +00002693
Dan Gohman8181bd12008-07-27 21:46:04 +00002694 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2695 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel8efdca42007-12-04 22:23:35 +00002696
2697 // CNTB_result becomes the chain to which all of the virtual registers
2698 // CNTB_reg, SUM1_reg become associated:
Dan Gohman8181bd12008-07-27 21:46:04 +00002699 SDValue CNTB_result =
Scott Michel8efdca42007-12-04 22:23:35 +00002700 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel4ec722e2008-07-16 17:17:29 +00002701
Dan Gohman8181bd12008-07-27 21:46:04 +00002702 SDValue CNTB_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002703 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2704
Dan Gohman8181bd12008-07-27 21:46:04 +00002705 SDValue Comp1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002706 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002707 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel8efdca42007-12-04 22:23:35 +00002708
Dan Gohman8181bd12008-07-27 21:46:04 +00002709 SDValue Sum1 =
Scott Michel8efdca42007-12-04 22:23:35 +00002710 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002711 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002712
Dan Gohman8181bd12008-07-27 21:46:04 +00002713 SDValue Sum1_rescopy =
Scott Michel8efdca42007-12-04 22:23:35 +00002714 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2715
Dan Gohman8181bd12008-07-27 21:46:04 +00002716 SDValue Comp2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002717 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002718 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2719 Shift2);
Dan Gohman8181bd12008-07-27 21:46:04 +00002720 SDValue Sum2 =
Scott Michel8efdca42007-12-04 22:23:35 +00002721 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel5a6f17b2008-01-30 02:55:46 +00002722 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel8efdca42007-12-04 22:23:35 +00002723
2724 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2725 }
2726
2727 case MVT::i64:
2728 break;
2729 }
2730
Dan Gohman8181bd12008-07-27 21:46:04 +00002731 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002732}
2733
Scott Michel56a125e2008-11-22 23:50:42 +00002734//! Lower ISD::SELECT_CC
2735/*!
2736 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2737 SELB instruction.
2738
2739 \note Need to revisit this in the future: if the code path through the true
2740 and false value computations is longer than the latency of a branch (6
2741 cycles), then it would be more advantageous to branch and insert a new basic
2742 block and branch on the condition. However, this code does not make that
2743 assumption, given the simplisitc uses so far.
2744 */
2745
2746static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
2747 MVT VT = Op.getValueType();
2748 SDValue lhs = Op.getOperand(0);
2749 SDValue rhs = Op.getOperand(1);
2750 SDValue trueval = Op.getOperand(2);
2751 SDValue falseval = Op.getOperand(3);
2752 SDValue condition = Op.getOperand(4);
2753
2754 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2755 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2756 // with another "cannot select select_cc" assert:
2757
2758 SDValue compare = DAG.getNode(ISD::SETCC, VT, lhs, rhs, condition);
2759 return DAG.getNode(SPUISD::SELB, VT, trueval, falseval, compare);
2760}
2761
2762//! Custom (target-specific) lowering entry point
2763/*!
2764 This is where LLVM's DAG selection process calls to do target-specific
2765 lowering of nodes.
2766 */
Dan Gohman8181bd12008-07-27 21:46:04 +00002767SDValue
2768SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel8efdca42007-12-04 22:23:35 +00002769{
Scott Michel97872d32008-02-23 18:41:37 +00002770 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands92c43912008-06-06 12:08:01 +00002771 MVT VT = Op.getValueType();
Scott Michel97872d32008-02-23 18:41:37 +00002772
2773 switch (Opc) {
Scott Michel8efdca42007-12-04 22:23:35 +00002774 default: {
2775 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michel97872d32008-02-23 18:41:37 +00002776 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greif1c80d112008-08-28 21:40:38 +00002777 cerr << "*Op.getNode():\n";
2778 Op.getNode()->dump();
Scott Michel8efdca42007-12-04 22:23:35 +00002779 abort();
2780 }
2781 case ISD::LOAD:
2782 case ISD::SEXTLOAD:
2783 case ISD::ZEXTLOAD:
2784 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2785 case ISD::STORE:
2786 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2787 case ISD::ConstantPool:
2788 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2789 case ISD::GlobalAddress:
2790 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2791 case ISD::JumpTable:
2792 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2793 case ISD::Constant:
2794 return LowerConstant(Op, DAG);
2795 case ISD::ConstantFP:
2796 return LowerConstantFP(Op, DAG);
Scott Michel394e26d2008-01-17 20:38:41 +00002797 case ISD::BRCOND:
2798 return LowerBRCOND(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002799 case ISD::FORMAL_ARGUMENTS:
Scott Michel394e26d2008-01-17 20:38:41 +00002800 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel8efdca42007-12-04 22:23:35 +00002801 case ISD::CALL:
Scott Micheldbac4cf2008-01-11 02:53:15 +00002802 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel8efdca42007-12-04 22:23:35 +00002803 case ISD::RET:
2804 return LowerRET(Op, DAG, getTargetMachine());
2805
Scott Michel97872d32008-02-23 18:41:37 +00002806
2807 // i8, i64 math ops:
2808 case ISD::ZERO_EXTEND:
2809 case ISD::SIGN_EXTEND:
2810 case ISD::ANY_EXTEND:
Scott Michel67224b22008-06-02 22:18:03 +00002811 case ISD::ADD:
Scott Michel8efdca42007-12-04 22:23:35 +00002812 case ISD::SUB:
2813 case ISD::ROTR:
2814 case ISD::ROTL:
2815 case ISD::SRL:
2816 case ISD::SHL:
Scott Michel67224b22008-06-02 22:18:03 +00002817 case ISD::SRA: {
Scott Michel97872d32008-02-23 18:41:37 +00002818 if (VT == MVT::i8)
2819 return LowerI8Math(Op, DAG, Opc);
2820 else if (VT == MVT::i64)
2821 return LowerI64Math(Op, DAG, Opc);
2822 break;
Scott Michel67224b22008-06-02 22:18:03 +00002823 }
Scott Michel8efdca42007-12-04 22:23:35 +00002824
2825 // Vector-related lowering.
2826 case ISD::BUILD_VECTOR:
2827 return LowerBUILD_VECTOR(Op, DAG);
2828 case ISD::SCALAR_TO_VECTOR:
2829 return LowerSCALAR_TO_VECTOR(Op, DAG);
2830 case ISD::VECTOR_SHUFFLE:
2831 return LowerVECTOR_SHUFFLE(Op, DAG);
2832 case ISD::EXTRACT_VECTOR_ELT:
2833 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2834 case ISD::INSERT_VECTOR_ELT:
2835 return LowerINSERT_VECTOR_ELT(Op, DAG);
2836
2837 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2838 case ISD::AND:
2839 case ISD::OR:
2840 case ISD::XOR:
2841 return LowerByteImmed(Op, DAG);
2842
2843 // Vector and i8 multiply:
2844 case ISD::MUL:
Duncan Sands92c43912008-06-06 12:08:01 +00002845 if (VT.isVector())
Scott Michel8efdca42007-12-04 22:23:35 +00002846 return LowerVectorMUL(Op, DAG);
Scott Michel97872d32008-02-23 18:41:37 +00002847 else if (VT == MVT::i8)
2848 return LowerI8Math(Op, DAG, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002849 else
Scott Michel97872d32008-02-23 18:41:37 +00002850 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel8efdca42007-12-04 22:23:35 +00002851
2852 case ISD::FDIV:
Scott Michel97872d32008-02-23 18:41:37 +00002853 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel8efdca42007-12-04 22:23:35 +00002854 return LowerFDIVf32(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002855#if 0
2856 // This is probably a libcall
2857 else if (Op.getValueType() == MVT::f64)
2858 return LowerFDIVf64(Op, DAG);
2859#endif
Scott Michel8efdca42007-12-04 22:23:35 +00002860 else
2861 assert(0 && "Calling FDIV on unsupported MVT");
2862
2863 case ISD::CTPOP:
2864 return LowerCTPOP(Op, DAG);
Scott Michel56a125e2008-11-22 23:50:42 +00002865
2866 case ISD::SELECT_CC:
2867 return LowerSELECT_CC(Op, DAG);
Scott Michel8efdca42007-12-04 22:23:35 +00002868 }
2869
Dan Gohman8181bd12008-07-27 21:46:04 +00002870 return SDValue();
Scott Michel8efdca42007-12-04 22:23:35 +00002871}
2872
Duncan Sands7d9834b2008-12-01 11:39:25 +00002873void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
2874 SmallVectorImpl<SDValue>&Results,
2875 SelectionDAG &DAG)
Scott Michel6e2d68b2008-11-10 23:43:06 +00002876{
2877#if 0
2878 unsigned Opc = (unsigned) N->getOpcode();
2879 MVT OpVT = N->getValueType(0);
2880
2881 switch (Opc) {
2882 default: {
2883 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2884 cerr << "Op.getOpcode() = " << Opc << "\n";
2885 cerr << "*Op.getNode():\n";
2886 N->dump();
2887 abort();
2888 /*NOTREACHED*/
2889 }
2890 }
2891#endif
2892
2893 /* Otherwise, return unchanged */
Scott Michel6e2d68b2008-11-10 23:43:06 +00002894}
2895
Scott Michel8efdca42007-12-04 22:23:35 +00002896//===----------------------------------------------------------------------===//
Scott Michel8efdca42007-12-04 22:23:35 +00002897// Target Optimization Hooks
2898//===----------------------------------------------------------------------===//
2899
Dan Gohman8181bd12008-07-27 21:46:04 +00002900SDValue
Scott Michel8efdca42007-12-04 22:23:35 +00002901SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2902{
2903#if 0
2904 TargetMachine &TM = getTargetMachine();
Scott Michelf9f42e62008-01-29 02:16:57 +00002905#endif
2906 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel8efdca42007-12-04 22:23:35 +00002907 SelectionDAG &DAG = DCI.DAG;
Scott Michel0718cd82008-12-01 17:56:02 +00002908 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2909 MVT NodeVT = N->getValueType(0); // The node's value type
2910 MVT Op0VT = Op0.getValueType(); // The first operand's result
2911 SDValue Result; // Initially, empty result
Scott Michel8efdca42007-12-04 22:23:35 +00002912
2913 switch (N->getOpcode()) {
2914 default: break;
Scott Michelf9f42e62008-01-29 02:16:57 +00002915 case ISD::ADD: {
Dan Gohman8181bd12008-07-27 21:46:04 +00002916 SDValue Op1 = N->getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002917
Scott Michel67224b22008-06-02 22:18:03 +00002918 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002919 SDValue Op01 = Op0.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002920 if (Op01.getOpcode() == ISD::Constant
2921 || Op01.getOpcode() == ISD::TargetConstant) {
2922 // (add <const>, (SPUindirect <arg>, <const>)) ->
2923 // (SPUindirect <arg>, <const + const>)
2924 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2925 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman8181bd12008-07-27 21:46:04 +00002926 SDValue combinedConst =
Scott Michel0718cd82008-12-01 17:56:02 +00002927 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(), Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00002928
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002929 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2930 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002931 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002932 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel0718cd82008-12-01 17:56:02 +00002933 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
Scott Michelf9f42e62008-01-29 02:16:57 +00002934 Op0.getOperand(0), combinedConst);
2935 }
Scott Michel67224b22008-06-02 22:18:03 +00002936 } else if (isa<ConstantSDNode>(Op0)
Scott Michelf9f42e62008-01-29 02:16:57 +00002937 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman8181bd12008-07-27 21:46:04 +00002938 SDValue Op11 = Op1.getOperand(1);
Scott Michelf9f42e62008-01-29 02:16:57 +00002939 if (Op11.getOpcode() == ISD::Constant
2940 || Op11.getOpcode() == ISD::TargetConstant) {
2941 // (add (SPUindirect <arg>, <const>), <const>) ->
2942 // (SPUindirect <arg>, <const + const>)
2943 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2944 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman8181bd12008-07-27 21:46:04 +00002945 SDValue combinedConst =
Scott Michel0718cd82008-12-01 17:56:02 +00002946 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(), Op0VT);
Scott Michelf9f42e62008-01-29 02:16:57 +00002947
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002948 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2949 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002950 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002951 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michelf9f42e62008-01-29 02:16:57 +00002952
2953 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2954 Op1.getOperand(0), combinedConst);
2955 }
2956 }
Scott Michel97872d32008-02-23 18:41:37 +00002957 break;
2958 }
2959 case ISD::SIGN_EXTEND:
2960 case ISD::ZERO_EXTEND:
2961 case ISD::ANY_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00002962 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
Scott Michel97872d32008-02-23 18:41:37 +00002963 // (any_extend (SPUextract_elt0 <arg>)) ->
2964 // (SPUextract_elt0 <arg>)
2965 // Types must match, however...
2966 DEBUG(cerr << "Replace: ");
2967 DEBUG(N->dump(&DAG));
2968 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002969 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002970 DEBUG(cerr << "\n");
2971
2972 return Op0;
2973 }
2974 break;
2975 }
2976 case SPUISD::IndirectAddr: {
2977 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2978 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00002979 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00002980 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2981 // (SPUaform <addr>, 0)
2982
2983 DEBUG(cerr << "Replace: ");
2984 DEBUG(N->dump(&DAG));
2985 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00002986 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00002987 DEBUG(cerr << "\n");
2988
2989 return Op0;
2990 }
2991 }
2992 break;
2993 }
2994 case SPUISD::SHLQUAD_L_BITS:
2995 case SPUISD::SHLQUAD_L_BYTES:
2996 case SPUISD::VEC_SHL:
2997 case SPUISD::VEC_SRL:
2998 case SPUISD::VEC_SRA:
2999 case SPUISD::ROTQUAD_RZ_BYTES:
3000 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003001 SDValue Op1 = N->getOperand(1);
Scott Michel97872d32008-02-23 18:41:37 +00003002
3003 if (isa<ConstantSDNode>(Op1)) {
3004 // Kill degenerate vector shifts:
3005 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
Dan Gohmanfaeb4a32008-09-12 16:56:44 +00003006 if (CN->getZExtValue() == 0) {
Scott Michel97872d32008-02-23 18:41:37 +00003007 Result = Op0;
3008 }
3009 }
3010 break;
3011 }
3012 case SPUISD::PROMOTE_SCALAR: {
3013 switch (Op0.getOpcode()) {
3014 default:
3015 break;
3016 case ISD::ANY_EXTEND:
3017 case ISD::ZERO_EXTEND:
3018 case ISD::SIGN_EXTEND: {
Scott Michel0718cd82008-12-01 17:56:02 +00003019 // (SPUpromote_scalar (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
Scott Michel97872d32008-02-23 18:41:37 +00003020 // <arg>
3021 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman8181bd12008-07-27 21:46:04 +00003022 SDValue Op00 = Op0.getOperand(0);
Scott Michelc630c412008-11-24 17:11:17 +00003023 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman8181bd12008-07-27 21:46:04 +00003024 SDValue Op000 = Op00.getOperand(0);
Scott Michel0718cd82008-12-01 17:56:02 +00003025 if (Op000.getValueType() == NodeVT) {
Scott Michel97872d32008-02-23 18:41:37 +00003026 Result = Op000;
3027 }
3028 }
3029 break;
3030 }
Scott Michelc630c412008-11-24 17:11:17 +00003031 case SPUISD::VEC2PREFSLOT: {
Scott Michel0718cd82008-12-01 17:56:02 +00003032 // (SPUpromote_scalar (SPUvec2prefslot <arg>)) ->
Scott Michel97872d32008-02-23 18:41:37 +00003033 // <arg>
3034 Result = Op0.getOperand(0);
3035 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003036 }
Scott Michel97872d32008-02-23 18:41:37 +00003037 }
3038 break;
Scott Michelf9f42e62008-01-29 02:16:57 +00003039 }
3040 }
Scott Michel394e26d2008-01-17 20:38:41 +00003041 // Otherwise, return unchanged.
Scott Michel0718cd82008-12-01 17:56:02 +00003042#ifndef NDEBUG
Gabor Greif1c80d112008-08-28 21:40:38 +00003043 if (Result.getNode()) {
Scott Michel97872d32008-02-23 18:41:37 +00003044 DEBUG(cerr << "\nReplace.SPU: ");
3045 DEBUG(N->dump(&DAG));
3046 DEBUG(cerr << "\nWith: ");
Gabor Greif1c80d112008-08-28 21:40:38 +00003047 DEBUG(Result.getNode()->dump(&DAG));
Scott Michel97872d32008-02-23 18:41:37 +00003048 DEBUG(cerr << "\n");
3049 }
3050#endif
3051
3052 return Result;
Scott Michel8efdca42007-12-04 22:23:35 +00003053}
3054
3055//===----------------------------------------------------------------------===//
3056// Inline Assembly Support
3057//===----------------------------------------------------------------------===//
3058
3059/// getConstraintType - Given a constraint letter, return the type of
3060/// constraint it is for this target.
Scott Michel4ec722e2008-07-16 17:17:29 +00003061SPUTargetLowering::ConstraintType
Scott Michel8efdca42007-12-04 22:23:35 +00003062SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3063 if (ConstraintLetter.size() == 1) {
3064 switch (ConstraintLetter[0]) {
3065 default: break;
3066 case 'b':
3067 case 'r':
3068 case 'f':
3069 case 'v':
3070 case 'y':
3071 return C_RegisterClass;
Scott Michel4ec722e2008-07-16 17:17:29 +00003072 }
Scott Michel8efdca42007-12-04 22:23:35 +00003073 }
3074 return TargetLowering::getConstraintType(ConstraintLetter);
3075}
3076
Scott Michel4ec722e2008-07-16 17:17:29 +00003077std::pair<unsigned, const TargetRegisterClass*>
Scott Michel8efdca42007-12-04 22:23:35 +00003078SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands92c43912008-06-06 12:08:01 +00003079 MVT VT) const
Scott Michel8efdca42007-12-04 22:23:35 +00003080{
3081 if (Constraint.size() == 1) {
3082 // GCC RS6000 Constraint Letters
3083 switch (Constraint[0]) {
3084 case 'b': // R1-R31
3085 case 'r': // R0-R31
3086 if (VT == MVT::i64)
3087 return std::make_pair(0U, SPU::R64CRegisterClass);
3088 return std::make_pair(0U, SPU::R32CRegisterClass);
3089 case 'f':
3090 if (VT == MVT::f32)
3091 return std::make_pair(0U, SPU::R32FPRegisterClass);
3092 else if (VT == MVT::f64)
3093 return std::make_pair(0U, SPU::R64FPRegisterClass);
3094 break;
Scott Michel4ec722e2008-07-16 17:17:29 +00003095 case 'v':
Scott Michel8efdca42007-12-04 22:23:35 +00003096 return std::make_pair(0U, SPU::GPRCRegisterClass);
3097 }
3098 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003099
Scott Michel8efdca42007-12-04 22:23:35 +00003100 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3101}
3102
Scott Michel97872d32008-02-23 18:41:37 +00003103//! Compute used/known bits for a SPU operand
Scott Michel8efdca42007-12-04 22:23:35 +00003104void
Dan Gohman8181bd12008-07-27 21:46:04 +00003105SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohmand0dfc772008-02-13 22:28:48 +00003106 const APInt &Mask,
Scott Michel4ec722e2008-07-16 17:17:29 +00003107 APInt &KnownZero,
Dan Gohman229fa052008-02-13 00:35:47 +00003108 APInt &KnownOne,
Scott Michel5a6f17b2008-01-30 02:55:46 +00003109 const SelectionDAG &DAG,
3110 unsigned Depth ) const {
Scott Michelbc5fbc12008-04-30 00:30:08 +00003111#if 0
Scott Michel97872d32008-02-23 18:41:37 +00003112 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michelbc5fbc12008-04-30 00:30:08 +00003113#endif
Scott Michel97872d32008-02-23 18:41:37 +00003114
3115 switch (Op.getOpcode()) {
3116 default:
3117 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3118 break;
3119
3120#if 0
3121 case CALL:
3122 case SHUFB:
Scott Michel56a125e2008-11-22 23:50:42 +00003123 case SHUFFLE_MASK:
Scott Michel97872d32008-02-23 18:41:37 +00003124 case CNTB:
3125#endif
3126
3127 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman8181bd12008-07-27 21:46:04 +00003128 SDValue Op0 = Op.getOperand(0);
Duncan Sands92c43912008-06-06 12:08:01 +00003129 MVT Op0VT = Op0.getValueType();
3130 unsigned Op0VTBits = Op0VT.getSizeInBits();
3131 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003132 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3133 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003134 break;
3135 }
Scott Michel4ec722e2008-07-16 17:17:29 +00003136
Scott Michel97872d32008-02-23 18:41:37 +00003137 case SPUISD::LDRESULT:
Scott Michelc630c412008-11-24 17:11:17 +00003138 case SPUISD::VEC2PREFSLOT:
3139 case SPUISD::VEC2PREFSLOT_CHAINED: {
Duncan Sands92c43912008-06-06 12:08:01 +00003140 MVT OpVT = Op.getValueType();
3141 unsigned OpVTBits = OpVT.getSizeInBits();
3142 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michelbc5fbc12008-04-30 00:30:08 +00003143 KnownZero |= APInt(OpVTBits, ~InMask, false);
3144 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michel97872d32008-02-23 18:41:37 +00003145 break;
3146 }
3147
3148#if 0
3149 case EXTRACT_I1_ZEXT:
3150 case EXTRACT_I1_SEXT:
3151 case EXTRACT_I8_ZEXT:
3152 case EXTRACT_I8_SEXT:
3153 case MPY:
3154 case MPYU:
3155 case MPYH:
3156 case MPYHH:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003157 case SPUISD::SHLQUAD_L_BITS:
3158 case SPUISD::SHLQUAD_L_BYTES:
3159 case SPUISD::VEC_SHL:
3160 case SPUISD::VEC_SRL:
3161 case SPUISD::VEC_SRA:
3162 case SPUISD::VEC_ROTL:
3163 case SPUISD::VEC_ROTR:
3164 case SPUISD::ROTQUAD_RZ_BYTES:
3165 case SPUISD::ROTQUAD_RZ_BITS:
Scott Michelbc5fbc12008-04-30 00:30:08 +00003166 case SPUISD::ROTBYTES_LEFT:
3167 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel67224b22008-06-02 22:18:03 +00003168 case SPUISD::SELECT_MASK:
3169 case SPUISD::SELB:
3170 case SPUISD::FPInterp:
3171 case SPUISD::FPRecipEst:
3172 case SPUISD::SEXT32TO64:
Scott Michel97872d32008-02-23 18:41:37 +00003173#endif
3174 }
Scott Michel8efdca42007-12-04 22:23:35 +00003175}
3176
Scott Michelbc5fbc12008-04-30 00:30:08 +00003177// LowerAsmOperandForConstraint
3178void
Dan Gohman8181bd12008-07-27 21:46:04 +00003179SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003180 char ConstraintLetter,
Evan Cheng7f250d62008-09-24 00:05:32 +00003181 bool hasMemory,
Dan Gohman8181bd12008-07-27 21:46:04 +00003182 std::vector<SDValue> &Ops,
Scott Michelbc5fbc12008-04-30 00:30:08 +00003183 SelectionDAG &DAG) const {
3184 // Default, for the time being, to the base class handler
Evan Cheng7f250d62008-09-24 00:05:32 +00003185 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3186 Ops, DAG);
Scott Michelbc5fbc12008-04-30 00:30:08 +00003187}
3188
Scott Michel8efdca42007-12-04 22:23:35 +00003189/// isLegalAddressImmediate - Return true if the integer value can be used
3190/// as the offset of the target addressing mode.
Gabor Greife9f7f582008-08-31 15:37:04 +00003191bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3192 const Type *Ty) const {
Scott Michel8efdca42007-12-04 22:23:35 +00003193 // SPU's addresses are 256K:
3194 return (V > -(1 << 18) && V < (1 << 18) - 1);
3195}
3196
3197bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel4ec722e2008-07-16 17:17:29 +00003198 return false;
Scott Michel8efdca42007-12-04 22:23:35 +00003199}
Dan Gohman36322c72008-10-18 02:06:02 +00003200
3201bool
3202SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3203 // The SPU target isn't yet aware of offsets.
3204 return false;
3205}