blob: 5dbf60bf2129cdbed665d4f5a3c984a782ff50ea [file] [log] [blame]
Scott Michel266bc8f2007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-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 Michel266bc8f2007-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 Michel203b2d62008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000018#include "llvm/ADT/VectorExtras.h"
Scott Michel266bc8f2007-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 Lattner84bc5422007-12-31 04:13:23 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel266bc8f2007-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 Sands83ec4b62008-06-06 12:08:01 +000040 //! MVT mapping to useful data for Cell SPU
Scott Michel266bc8f2007-12-04 22:23:35 +000041 struct valtype_map_s {
Duncan Sands83ec4b62008-06-06 12:08:01 +000042 const MVT valtype;
Scott Michel7f9ba9b2008-01-30 02:55:46 +000043 const int prefslot_byte;
Scott Michel266bc8f2007-12-04 22:23:35 +000044 };
Scott Michel5af8f0e2008-07-16 17:17:29 +000045
Scott Michel266bc8f2007-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 Sands83ec4b62008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel266bc8f2007-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 Michel7f9ba9b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel266bc8f2007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands83ec4b62008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel266bc8f2007-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 Michel9de5d0d2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel266bc8f2007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman475871a2008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel266bc8f2007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
Bill Wendling056292f2008-09-16 21:48:12 +000095 || Opc == ISD::ExternalSymbol
Scott Michel266bc8f2007-12-04 22:23:35 +000096 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
Bill Wendling056292f2008-09-16 21:48:12 +0000100 || Opc == ISD::TargetExternalSymbol
Scott Michel9de5d0d2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000102 }
Scott Michel58c58182008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman475871a2008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel58c58182008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel58c58182008-01-17 20:38:41 +0000110 }
Scott Michel266bc8f2007-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 Michel5af8f0e2008-07-16 17:17:29 +0000123
Scott Michel266bc8f2007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel504c3692007-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 Michel266bc8f2007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000132
Scott Michel266bc8f2007-12-04 22:23:35 +0000133 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng03294662008-10-14 21:26:46 +0000134 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
135 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
136 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Chris Lattnerddf89562008-01-17 19:59:44 +0000137 setTruncStoreAction(MVT::i8, MVT::i1, Custom);
138 setTruncStoreAction(MVT::i16, MVT::i1, Custom);
139 setTruncStoreAction(MVT::i32, MVT::i1, Custom);
140 setTruncStoreAction(MVT::i64, MVT::i1, Custom);
141 setTruncStoreAction(MVT::i128, MVT::i1, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000142
Evan Cheng03294662008-10-14 21:26:46 +0000143 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
144 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
145 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Chris Lattnerddf89562008-01-17 19:59:44 +0000146 setTruncStoreAction(MVT::i8 , MVT::i8, Custom);
147 setTruncStoreAction(MVT::i16 , MVT::i8, Custom);
148 setTruncStoreAction(MVT::i32 , MVT::i8, Custom);
149 setTruncStoreAction(MVT::i64 , MVT::i8, Custom);
150 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000151
Evan Cheng03294662008-10-14 21:26:46 +0000152 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
153 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
154 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000155
156 // SPU constant load actions are custom lowered:
157 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begemanccef5802008-02-14 18:43:04 +0000158 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000159 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
160
161 // SPU's loads and stores have to be custom lowered:
162 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
163 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000164 MVT VT = (MVT::SimpleValueType)sctype;
165
166 setOperationAction(ISD::LOAD, VT, Custom);
167 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000168 }
169
Scott Michel58c58182008-01-17 20:38:41 +0000170 // Custom lower BRCOND for i1, i8 to "promote" the result to
171 // i32 and i16, respectively.
172 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000173
174 // Expand the jumptable branches
175 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
176 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000177 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000178
179 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000180 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
181
Scott Michel266bc8f2007-12-04 22:23:35 +0000182 // PowerPC has no SREM/UREM instructions
183 setOperationAction(ISD::SREM, MVT::i32, Expand);
184 setOperationAction(ISD::UREM, MVT::i32, Expand);
185 setOperationAction(ISD::SREM, MVT::i64, Expand);
186 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000187
Scott Michel266bc8f2007-12-04 22:23:35 +0000188 // We don't support sin/cos/sqrt/fmod
189 setOperationAction(ISD::FSIN , MVT::f64, Expand);
190 setOperationAction(ISD::FCOS , MVT::f64, Expand);
191 setOperationAction(ISD::FREM , MVT::f64, Expand);
192 setOperationAction(ISD::FSIN , MVT::f32, Expand);
193 setOperationAction(ISD::FCOS , MVT::f32, Expand);
194 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000195
Scott Michel266bc8f2007-12-04 22:23:35 +0000196 // If we're enabling GP optimizations, use hardware square root
197 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
198 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000199
Scott Michel266bc8f2007-12-04 22:23:35 +0000200 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
201 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
202
203 // SPU can do rotate right and left, so legalize it... but customize for i8
204 // because instructions don't exist.
Bill Wendling9440e352008-08-31 02:59:23 +0000205
206 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
207 // .td files.
208 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
209 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
210 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
211
Scott Michel266bc8f2007-12-04 22:23:35 +0000212 setOperationAction(ISD::ROTL, MVT::i32, Legal);
213 setOperationAction(ISD::ROTL, MVT::i16, Legal);
214 setOperationAction(ISD::ROTL, MVT::i8, Custom);
215 // SPU has no native version of shift left/right for i8
216 setOperationAction(ISD::SHL, MVT::i8, Custom);
217 setOperationAction(ISD::SRL, MVT::i8, Custom);
218 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michela59d4692008-02-23 18:41:37 +0000219 // And SPU needs custom lowering for shift left/right for i64
220 setOperationAction(ISD::SHL, MVT::i64, Custom);
221 setOperationAction(ISD::SRL, MVT::i64, Custom);
222 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000223
Scott Michel5af8f0e2008-07-16 17:17:29 +0000224 // Custom lower i8, i32 and i64 multiplications
225 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000226 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000227 setOperationAction(ISD::MUL, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000228
Scott Michel8bf61e82008-06-02 22:18:03 +0000229 // Need to custom handle (some) common i8, i64 math ops
230 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000231 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel8bf61e82008-06-02 22:18:03 +0000232 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000233
Scott Michel266bc8f2007-12-04 22:23:35 +0000234 // SPU does not have BSWAP. It does have i32 support CTLZ.
235 // CTPOP has to be custom lowered.
236 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
237 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
238
239 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
240 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
241 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
242 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
243
244 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
245 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
246
247 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000248
Scott Michel8bf61e82008-06-02 22:18:03 +0000249 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000250 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000251 setOperationAction(ISD::SELECT, MVT::i1, Promote);
252 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000253 setOperationAction(ISD::SELECT, MVT::i16, Legal);
254 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000255 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000256
Scott Michel78c47fa2008-03-10 16:58:52 +0000257 setOperationAction(ISD::SETCC, MVT::i1, Promote);
258 setOperationAction(ISD::SETCC, MVT::i8, Legal);
259 setOperationAction(ISD::SETCC, MVT::i16, Legal);
260 setOperationAction(ISD::SETCC, MVT::i32, Legal);
261 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michelad2715e2008-03-05 23:02:02 +0000262
Scott Michela59d4692008-02-23 18:41:37 +0000263 // Zero extension and sign extension for i64 have to be
264 // custom legalized
265 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
266 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
267 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000268
Scott Michel266bc8f2007-12-04 22:23:35 +0000269 // SPU has a legal FP -> signed INT instruction
270 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
271 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
272 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
273 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
274
275 // FDIV on SPU requires custom lowering
276 setOperationAction(ISD::FDIV, MVT::f32, Custom);
277 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
278
279 // SPU has [U|S]INT_TO_FP
280 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
281 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
282 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
283 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
284 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
285 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
286 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
287 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
288
Scott Michel86c041f2007-12-20 00:44:13 +0000289 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
290 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
291 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
292 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000293
294 // We cannot sextinreg(i1). Expand to shifts.
295 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000296
Scott Michel266bc8f2007-12-04 22:23:35 +0000297 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000298 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000299 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000300
301 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000302 // appropriate instructions to materialize the address.
Scott Michel053c1da2008-01-29 02:16:57 +0000303 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
304 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000305 MVT VT = (MVT::SimpleValueType)sctype;
306
307 setOperationAction(ISD::GlobalAddress, VT, Custom);
308 setOperationAction(ISD::ConstantPool, VT, Custom);
309 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000310 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000311
312 // RET must be custom lowered, to meet ABI requirements
313 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000314
Scott Michel266bc8f2007-12-04 22:23:35 +0000315 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
316 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000317
Scott Michel266bc8f2007-12-04 22:23:35 +0000318 // Use the default implementation.
319 setOperationAction(ISD::VAARG , MVT::Other, Expand);
320 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
321 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000322 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000323 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
324 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
325 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
326
327 // Cell SPU has instructions for converting between i64 and fp.
328 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
329 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000330
Scott Michel266bc8f2007-12-04 22:23:35 +0000331 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
332 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
333
334 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
335 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
336
337 // First set operation action for all vector types to expand. Then we
338 // will selectively turn on ones that can be effectively codegen'd.
339 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
340 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
341 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
342 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
343 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
344 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
345
Duncan Sands83ec4b62008-06-06 12:08:01 +0000346 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
347 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
348 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000349
Duncan Sands83ec4b62008-06-06 12:08:01 +0000350 // add/sub are legal for all supported vector VT's.
351 setOperationAction(ISD::ADD , VT, Legal);
352 setOperationAction(ISD::SUB , VT, Legal);
353 // mul has to be custom lowered.
354 setOperationAction(ISD::MUL , VT, Custom);
355
356 setOperationAction(ISD::AND , VT, Legal);
357 setOperationAction(ISD::OR , VT, Legal);
358 setOperationAction(ISD::XOR , VT, Legal);
359 setOperationAction(ISD::LOAD , VT, Legal);
360 setOperationAction(ISD::SELECT, VT, Legal);
361 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000362
Scott Michel266bc8f2007-12-04 22:23:35 +0000363 // These operations need to be expanded:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000364 setOperationAction(ISD::SDIV, VT, Expand);
365 setOperationAction(ISD::SREM, VT, Expand);
366 setOperationAction(ISD::UDIV, VT, Expand);
367 setOperationAction(ISD::UREM, VT, Expand);
368 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000369
370 // Custom lower build_vector, constant pool spills, insert and
371 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000372 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
373 setOperationAction(ISD::ConstantPool, VT, Custom);
374 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
375 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
376 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
377 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000378 }
379
380 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
381 setOperationAction(ISD::AND, MVT::v16i8, Custom);
382 setOperationAction(ISD::OR, MVT::v16i8, Custom);
383 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
384 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000385
Scott Michel266bc8f2007-12-04 22:23:35 +0000386 setShiftAmountType(MVT::i32);
387 setSetCCResultContents(ZeroOrOneSetCCResult);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000388
Scott Michel266bc8f2007-12-04 22:23:35 +0000389 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000390
Scott Michel266bc8f2007-12-04 22:23:35 +0000391 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000392 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000393 setTargetDAGCombine(ISD::ZERO_EXTEND);
394 setTargetDAGCombine(ISD::SIGN_EXTEND);
395 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000396
Scott Michel266bc8f2007-12-04 22:23:35 +0000397 computeRegisterProperties();
398}
399
400const char *
401SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
402{
403 if (node_names.empty()) {
404 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
405 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
406 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
407 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000408 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000409 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000410 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
411 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
412 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
413 node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
414 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
415 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
416 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
Gabor Greif93c53e52008-08-31 15:37:04 +0000417 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED]
418 = "SPUISD::EXTRACT_ELT0_CHAINED";
Scott Michel266bc8f2007-12-04 22:23:35 +0000419 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
420 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
421 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
422 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
423 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
424 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
425 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
426 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michela59d4692008-02-23 18:41:37 +0000427 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
428 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000429 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
430 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
431 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
432 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
433 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michela59d4692008-02-23 18:41:37 +0000434 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
435 "SPUISD::ROTQUAD_RZ_BYTES";
436 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
437 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel266bc8f2007-12-04 22:23:35 +0000438 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
439 "SPUISD::ROTBYTES_RIGHT_S";
440 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
441 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
442 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel8bf61e82008-06-02 22:18:03 +0000443 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
444 "SPUISD::ROTBYTES_LEFT_BITS";
445 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000446 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000447 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
448 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
449 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
450 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000451 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
452 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
453 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
454 }
455
456 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
457
458 return ((i != node_names.end()) ? i->second : 0);
459}
460
Dan Gohman475871a2008-07-27 21:46:04 +0000461MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000462 MVT VT = Op.getValueType();
Scott Micheld976c212008-10-30 01:51:48 +0000463 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel78c47fa2008-03-10 16:58:52 +0000464}
465
Scott Michel266bc8f2007-12-04 22:23:35 +0000466//===----------------------------------------------------------------------===//
467// Calling convention code:
468//===----------------------------------------------------------------------===//
469
470#include "SPUGenCallingConv.inc"
471
472//===----------------------------------------------------------------------===//
473// LowerOperation implementation
474//===----------------------------------------------------------------------===//
475
Scott Michel9de5d0d2008-01-11 02:53:15 +0000476/// Aligned load common code for CellSPU
477/*!
478 \param[in] Op The SelectionDAG load or store operand
479 \param[in] DAG The selection DAG
480 \param[in] ST CellSPU subtarget information structure
481 \param[in,out] alignment Caller initializes this to the load or store node's
482 value from getAlignment(), may be updated while generating the aligned load
483 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
484 offset (divisible by 16, modulo 16 == 0)
485 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
486 offset of the preferred slot (modulo 16 != 0)
487 \param[in,out] VT Caller initializes this value type to the the load or store
488 node's loaded or stored value type; may be updated if an i1-extended load or
489 store.
490 \param[out] was16aligned true if the base pointer had 16-byte alignment,
491 otherwise false. Can help to determine if the chunk needs to be rotated.
492
493 Both load and store lowering load a block of data aligned on a 16-byte
494 boundary. This is the common aligned load code shared between both.
495 */
Dan Gohman475871a2008-07-27 21:46:04 +0000496static SDValue
497AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Michel9de5d0d2008-01-11 02:53:15 +0000498 LSBaseSDNode *LSN,
499 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000500 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000501{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000502 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000503 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman475871a2008-07-27 21:46:04 +0000504 SDValue basePtr = LSN->getBasePtr();
505 SDValue chain = LSN->getChain();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000506
507 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000508 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000509
Gabor Greif93c53e52008-08-31 15:37:04 +0000510 if (Op1.getOpcode() == ISD::Constant
511 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000512 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000513
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000514 alignOffs = (int) CN->getZExtValue();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000515 prefSlotOffs = (int) (alignOffs & 0xf);
516
517 // Adjust the rotation amount to ensure that the final result ends up in
518 // the preferred slot:
519 prefSlotOffs -= vtm->prefslot_byte;
520 basePtr = basePtr.getOperand(0);
521
Scott Michel58c58182008-01-17 20:38:41 +0000522 // Loading from memory, can we adjust alignment?
523 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +0000524 SDValue APtr = basePtr.getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000525 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
526 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
527 alignment = GSDN->getGlobal()->getAlignment();
528 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000529 }
530 } else {
531 alignOffs = 0;
532 prefSlotOffs = -vtm->prefslot_byte;
533 }
Scott Michel203b2d62008-04-30 00:30:08 +0000534 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
535 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
536 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
537 prefSlotOffs = (int) (alignOffs & 0xf);
538 prefSlotOffs -= vtm->prefslot_byte;
539 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000540 } else {
541 alignOffs = 0;
542 prefSlotOffs = -vtm->prefslot_byte;
543 }
544
545 if (alignment == 16) {
546 // Realign the base pointer as a D-Form address:
547 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000548 basePtr = DAG.getNode(ISD::ADD, PtrVT,
549 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000550 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000551 }
552
553 // Emit the vector load:
554 was16aligned = true;
555 return DAG.getLoad(MVT::v16i8, chain, basePtr,
556 LSN->getSrcValue(), LSN->getSrcValueOffset(),
557 LSN->isVolatile(), 16);
558 }
559
560 // Unaligned load or we're using the "large memory" model, which means that
561 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000562 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greif93c53e52008-08-31 15:37:04 +0000563 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
564 DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000565 }
566
567 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000568 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000569 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000570 was16aligned = false;
571 return DAG.getLoad(MVT::v16i8, chain, basePtr,
572 LSN->getSrcValue(), LSN->getSrcValueOffset(),
573 LSN->isVolatile(), 16);
574}
575
Scott Michel266bc8f2007-12-04 22:23:35 +0000576/// Custom lower loads for CellSPU
577/*!
578 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
579 within a 16-byte block, we have to rotate to extract the requested element.
580 */
Dan Gohman475871a2008-07-27 21:46:04 +0000581static SDValue
582LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000583 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000584 SDValue the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000585 MVT VT = LN->getMemoryVT();
Gabor Greifba36cb52008-08-28 21:40:38 +0000586 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000587 ISD::LoadExtType ExtType = LN->getExtensionType();
588 unsigned alignment = LN->getAlignment();
Dan Gohman475871a2008-07-27 21:46:04 +0000589 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000590
Scott Michel266bc8f2007-12-04 22:23:35 +0000591 switch (LN->getAddressingMode()) {
592 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000593 int offset, rotamt;
594 bool was16aligned;
Dan Gohman475871a2008-07-27 21:46:04 +0000595 SDValue result =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000596 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000597
Gabor Greifba36cb52008-08-28 21:40:38 +0000598 if (result.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000599 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000600
601 the_chain = result.getValue(1);
602 // Rotate the chunk if necessary
603 if (rotamt < 0)
604 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000605 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000606 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
607
Scott Michel58c58182008-01-17 20:38:41 +0000608 Ops[0] = the_chain;
609 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000610 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000611 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
612 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000613 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000614 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000615 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000616 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000617 }
618
619 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
620 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000621 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000622
623 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
624 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000625 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000626
Scott Michel9de5d0d2008-01-11 02:53:15 +0000627 // Convert the loaded v16i8 vector to the appropriate vector type
628 // specified by the operand:
629 if (OpVT == VT) {
630 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000631 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000632 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000633 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000634
635 Ops[0] = the_chain;
636 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
637 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
638 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
639 the_chain = result.getValue(1);
640 } else {
641 // Handle the sign and zero-extending loads for i1 and i8:
642 unsigned NewOpC;
643
644 if (ExtType == ISD::SEXTLOAD) {
645 NewOpC = (OpVT == MVT::i1
646 ? SPUISD::EXTRACT_I1_SEXT
647 : SPUISD::EXTRACT_I8_SEXT);
648 } else {
649 assert(ExtType == ISD::ZEXTLOAD);
650 NewOpC = (OpVT == MVT::i1
651 ? SPUISD::EXTRACT_I1_ZEXT
652 : SPUISD::EXTRACT_I8_ZEXT);
653 }
654
655 result = DAG.getNode(NewOpC, OpVT, result);
656 }
657
658 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000659 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000660 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000661 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000662 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000663
Scott Michel58c58182008-01-17 20:38:41 +0000664 result = DAG.getNode(SPUISD::LDRESULT, retvts,
665 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000666 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000667 }
668 case ISD::PRE_INC:
669 case ISD::PRE_DEC:
670 case ISD::POST_INC:
671 case ISD::POST_DEC:
672 case ISD::LAST_INDEXED_MODE:
673 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
674 "UNINDEXED\n";
675 cerr << (unsigned) LN->getAddressingMode() << "\n";
676 abort();
677 /*NOTREACHED*/
678 }
679
Dan Gohman475871a2008-07-27 21:46:04 +0000680 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000681}
682
683/// Custom lower stores for CellSPU
684/*!
685 All CellSPU stores are aligned to 16-byte boundaries, so for elements
686 within a 16-byte block, we have to generate a shuffle to insert the
687 requested element into its place, then store the resulting block.
688 */
Dan Gohman475871a2008-07-27 21:46:04 +0000689static SDValue
690LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000691 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000692 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000693 MVT VT = Value.getValueType();
694 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
695 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000696 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000697
698 switch (SN->getAddressingMode()) {
699 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000700 int chunk_offset, slot_offset;
701 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000702
703 // The vector type we really want to load from the 16-byte chunk, except
704 // in the case of MVT::i1, which has to be v16i8.
Duncan Sands83ec4b62008-06-06 12:08:01 +0000705 MVT vecVT, stVecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000706
Scott Michel266bc8f2007-12-04 22:23:35 +0000707 if (StVT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000708 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
709 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000710
Dan Gohman475871a2008-07-27 21:46:04 +0000711 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000712 AlignedLoad(Op, DAG, ST, SN, alignment,
713 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000714
Gabor Greifba36cb52008-08-28 21:40:38 +0000715 if (alignLoadVec.getNode() == 0)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000716 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000717
Scott Michel9de5d0d2008-01-11 02:53:15 +0000718 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000719 SDValue basePtr = LN->getBasePtr();
720 SDValue the_chain = alignLoadVec.getValue(1);
721 SDValue theValue = SN->getValue();
722 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000723
724 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000725 && (theValue.getOpcode() == ISD::AssertZext
726 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000727 // Drill down and get the value for zero- and sign-extended
728 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000729 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000730 }
731
Scott Michel9de5d0d2008-01-11 02:53:15 +0000732 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000733
Dan Gohman475871a2008-07-27 21:46:04 +0000734 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
735 SDValue insertEltPtr;
736 SDValue insertEltOp;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000737
738 // If the base pointer is already a D-form address, then just create
739 // a new D-form address with a slot offset and the orignal base pointer.
740 // Otherwise generate a D-form address with the slot offset relative
741 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000742 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greifba36cb52008-08-28 21:40:38 +0000743 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michel497e8882008-01-11 21:01:19 +0000744 DEBUG(cerr << "\n");
745
Scott Michel053c1da2008-01-29 02:16:57 +0000746 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
747 (basePtr.getOpcode() == ISD::ADD
748 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000749 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000750 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000751 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000752 }
753
754 insertEltOp = DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000755 result = DAG.getNode(SPUISD::SHUFB, vecVT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000756 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue),
757 alignLoadVec,
758 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000759
Scott Michel9de5d0d2008-01-11 02:53:15 +0000760 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000761 LN->getSrcValue(), LN->getSrcValueOffset(),
762 LN->isVolatile(), LN->getAlignment());
763
764 return result;
765 /*UNREACHED*/
766 }
767 case ISD::PRE_INC:
768 case ISD::PRE_DEC:
769 case ISD::POST_INC:
770 case ISD::POST_DEC:
771 case ISD::LAST_INDEXED_MODE:
772 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
773 "UNINDEXED\n";
774 cerr << (unsigned) SN->getAddressingMode() << "\n";
775 abort();
776 /*NOTREACHED*/
777 }
778
Dan Gohman475871a2008-07-27 21:46:04 +0000779 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000780}
781
782/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000783static SDValue
784LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000785 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000786 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
787 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000788 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
789 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000790 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000791
792 if (TM.getRelocationModel() == Reloc::Static) {
793 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000794 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000795 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000796 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000797 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
798 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000799 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000800 }
801 }
802
803 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000804 "LowerConstantPool: Relocation model other than static"
805 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000806 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000807}
808
Dan Gohman475871a2008-07-27 21:46:04 +0000809static SDValue
810LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000811 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000812 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000813 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
814 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000815 const TargetMachine &TM = DAG.getTarget();
816
817 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000818 if (!ST->usingLargeMem()) {
819 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
820 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000821 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
822 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000823 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
824 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000825 }
826
827 assert(0 &&
828 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000829 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000830}
831
Dan Gohman475871a2008-07-27 21:46:04 +0000832static SDValue
833LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000834 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000835 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
836 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000837 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000838 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000839 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000840
Scott Michel266bc8f2007-12-04 22:23:35 +0000841 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000842 if (!ST->usingLargeMem()) {
843 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
844 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000845 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
846 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000847 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
848 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000849 } else {
850 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000851 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000852 abort();
853 /*NOTREACHED*/
854 }
855
Dan Gohman475871a2008-07-27 21:46:04 +0000856 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000857}
858
859//! Custom lower i64 integer constants
860/*!
861 This code inserts all of the necessary juggling that needs to occur to load
862 a 64-bit constant into a register.
863 */
Dan Gohman475871a2008-07-27 21:46:04 +0000864static SDValue
865LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000866 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000867 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000868
869 if (VT == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000870 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +0000871 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000872 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000873 } else {
874 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000875 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000876 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000877 abort();
878 /*NOTREACHED*/
879 }
880
Dan Gohman475871a2008-07-27 21:46:04 +0000881 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000882}
883
Nate Begemanccef5802008-02-14 18:43:04 +0000884//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000885static SDValue
886LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000887 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000888 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000889
890 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000891 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000892
Nate Begemanccef5802008-02-14 18:43:04 +0000893 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000894 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000895 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000896 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000897 }
898
Dan Gohman475871a2008-07-27 21:46:04 +0000899 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000900}
901
Scott Michel58c58182008-01-17 20:38:41 +0000902//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000903static SDValue
904LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000905{
Dan Gohman475871a2008-07-27 21:46:04 +0000906 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000907 MVT CondVT = Cond.getValueType();
908 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000909
910 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
911 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
912 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
913 Op.getOperand(0),
914 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
915 Op.getOperand(2));
916 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000917 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000918}
919
Dan Gohman475871a2008-07-27 21:46:04 +0000920static SDValue
921LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000922{
923 MachineFunction &MF = DAG.getMachineFunction();
924 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000925 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Micheld976c212008-10-30 01:51:48 +0000926 SmallVector<SDValue, 48> ArgValues;
Dan Gohman475871a2008-07-27 21:46:04 +0000927 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000928 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000929
930 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
931 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000932
Scott Michel266bc8f2007-12-04 22:23:35 +0000933 unsigned ArgOffset = SPUFrameInfo::minStackSize();
934 unsigned ArgRegIdx = 0;
935 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000936
Duncan Sands83ec4b62008-06-06 12:08:01 +0000937 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000938
Scott Michel266bc8f2007-12-04 22:23:35 +0000939 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000940 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
941 ArgNo != e; ++ArgNo) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000942 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
943 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Micheld976c212008-10-30 01:51:48 +0000944 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000945
Scott Micheld976c212008-10-30 01:51:48 +0000946 if (ArgRegIdx < NumArgRegs) {
947 const TargetRegisterClass *ArgRegClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000948
Scott Micheld976c212008-10-30 01:51:48 +0000949 switch (ObjectVT.getSimpleVT()) {
950 default: {
951 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
952 << ObjectVT.getMVTString()
953 << "\n";
954 abort();
955 }
956 case MVT::i8:
957 ArgRegClass = &SPU::R8CRegClass;
958 break;
959 case MVT::i16:
960 ArgRegClass = &SPU::R16CRegClass;
961 break;
962 case MVT::i32:
963 ArgRegClass = &SPU::R32CRegClass;
964 break;
965 case MVT::i64:
966 ArgRegClass = &SPU::R64CRegClass;
967 break;
968 case MVT::f32:
969 ArgRegClass = &SPU::R32FPRegClass;
970 break;
971 case MVT::f64:
972 ArgRegClass = &SPU::R64FPRegClass;
973 break;
974 case MVT::v2f64:
975 case MVT::v4f32:
976 case MVT::v2i64:
977 case MVT::v4i32:
978 case MVT::v8i16:
979 case MVT::v16i8:
980 ArgRegClass = &SPU::VECREGRegClass;
Scott Micheld976c212008-10-30 01:51:48 +0000981 break;
982 }
983
984 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
985 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
986 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
987 ++ArgRegIdx;
988 } else {
989 // We need to load the argument to a virtual register if we determined
990 // above that we ran out of physical registers of the appropriate type
991 // or we're forced to do vararg
Chris Lattner9f72d1a2008-02-13 07:35:30 +0000992 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +0000993 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +0000994 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000995 ArgOffset += StackSlotSize;
996 }
Scott Michel5af8f0e2008-07-16 17:17:29 +0000997
Scott Michel266bc8f2007-12-04 22:23:35 +0000998 ArgValues.push_back(ArgVal);
Scott Micheld976c212008-10-30 01:51:48 +0000999 // Update the chain
1000 Root = ArgVal.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001001 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001002
Scott Micheld976c212008-10-30 01:51:48 +00001003 // vararg handling:
Scott Michel266bc8f2007-12-04 22:23:35 +00001004 if (isVarArg) {
Scott Micheld976c212008-10-30 01:51:48 +00001005 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1006 // We will spill (79-3)+1 registers to the stack
1007 SmallVector<SDValue, 79-3+1> MemOps;
1008
1009 // Create the frame slot
1010
Scott Michel266bc8f2007-12-04 22:23:35 +00001011 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Micheld976c212008-10-30 01:51:48 +00001012 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1013 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1014 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1015 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1016 Root = Store.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001017 MemOps.push_back(Store);
Scott Micheld976c212008-10-30 01:51:48 +00001018
1019 // Increment address by stack slot size for the next stored argument
1020 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001021 }
1022 if (!MemOps.empty())
Scott Micheld976c212008-10-30 01:51:48 +00001023 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001024 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001025
Scott Michel266bc8f2007-12-04 22:23:35 +00001026 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001027
Scott Michel266bc8f2007-12-04 22:23:35 +00001028 // Return the new list of results.
Gabor Greifba36cb52008-08-28 21:40:38 +00001029 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf9516202008-06-30 10:19:09 +00001030 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001031}
1032
1033/// isLSAAddress - Return the immediate to use if the specified
1034/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001035static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001036 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +00001037 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001038
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001039 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001040 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1041 (Addr << 14 >> 14) != Addr)
1042 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001043
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001044 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001045}
1046
1047static
Dan Gohman475871a2008-07-27 21:46:04 +00001048SDValue
1049LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman095cc292008-09-13 01:54:27 +00001050 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1051 SDValue Chain = TheCall->getChain();
Dan Gohman095cc292008-09-13 01:54:27 +00001052 SDValue Callee = TheCall->getCallee();
1053 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001054 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1055 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1056 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1057
1058 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001059 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001060
Scott Michel266bc8f2007-12-04 22:23:35 +00001061 // Accumulate how many bytes are to be pushed on the stack, including the
1062 // linkage area, and parameter passing area. According to the SPU ABI,
1063 // we minimally need space for [LR] and [SP]
1064 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001065
Scott Michel266bc8f2007-12-04 22:23:35 +00001066 // Set up a copy of the stack pointer for use loading and storing any
1067 // arguments that may not fit in the registers available for argument
1068 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001069 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001070
Scott Michel266bc8f2007-12-04 22:23:35 +00001071 // Figure out which arguments are going to go in registers, and which in
1072 // memory.
1073 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1074 unsigned ArgRegIdx = 0;
1075
1076 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001077 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001078 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001079 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001080
1081 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001082 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001083
Scott Michel266bc8f2007-12-04 22:23:35 +00001084 // PtrOff will be used to store the current argument to the stack if a
1085 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001086 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001087 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1088
Duncan Sands83ec4b62008-06-06 12:08:01 +00001089 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001090 default: assert(0 && "Unexpected ValueType for argument!");
1091 case MVT::i32:
1092 case MVT::i64:
1093 case MVT::i128:
1094 if (ArgRegIdx != NumArgRegs) {
1095 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1096 } else {
1097 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001098 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001099 }
1100 break;
1101 case MVT::f32:
1102 case MVT::f64:
1103 if (ArgRegIdx != NumArgRegs) {
1104 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1105 } else {
1106 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001107 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001108 }
1109 break;
1110 case MVT::v4f32:
1111 case MVT::v4i32:
1112 case MVT::v8i16:
1113 case MVT::v16i8:
1114 if (ArgRegIdx != NumArgRegs) {
1115 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1116 } else {
1117 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001118 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001119 }
1120 break;
1121 }
1122 }
1123
1124 // Update number of stack bytes actually used, insert a call sequence start
1125 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnere563bbc2008-10-11 22:08:30 +00001126 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1127 true));
Scott Michel266bc8f2007-12-04 22:23:35 +00001128
1129 if (!MemOpChains.empty()) {
1130 // Adjust the stack pointer for the stack arguments.
1131 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1132 &MemOpChains[0], MemOpChains.size());
1133 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001134
Scott Michel266bc8f2007-12-04 22:23:35 +00001135 // Build a sequence of copy-to-reg nodes chained together with token chain
1136 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001137 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001138 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1139 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1140 InFlag);
1141 InFlag = Chain.getValue(1);
1142 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001143
Dan Gohman475871a2008-07-27 21:46:04 +00001144 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001145 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001146
Bill Wendling056292f2008-09-16 21:48:12 +00001147 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1148 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1149 // node so that legalize doesn't hack it.
Scott Michel19fd42a2008-11-11 03:06:06 +00001150 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001151 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001152 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001153 SDValue Zero = DAG.getConstant(0, PtrVT);
1154 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001155
Scott Michel9de5d0d2008-01-11 02:53:15 +00001156 if (!ST->usingLargeMem()) {
1157 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1158 // style calls, otherwise, external symbols are BRASL calls. This assumes
1159 // that declared/defined symbols are in the same compilation unit and can
1160 // be reached through PC-relative jumps.
1161 //
1162 // NOTE:
1163 // This may be an unsafe assumption for JIT and really large compilation
1164 // units.
1165 if (GV->isDeclaration()) {
1166 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1167 } else {
1168 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1169 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001170 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001171 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1172 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001173 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001174 }
Scott Michel19fd42a2008-11-11 03:06:06 +00001175 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendling056292f2008-09-16 21:48:12 +00001176 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001177 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001178 // If this is an absolute destination address that appears to be a legal
1179 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001180 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001181 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001182
1183 Ops.push_back(Chain);
1184 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001185
Scott Michel266bc8f2007-12-04 22:23:35 +00001186 // Add argument registers to the end of the list so that they are known live
1187 // into the call.
1188 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001189 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001190 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001191
Gabor Greifba36cb52008-08-28 21:40:38 +00001192 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001193 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001194 // Returns a chain and a flag for retval copy to use.
1195 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1196 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001197 InFlag = Chain.getValue(1);
1198
Chris Lattnere563bbc2008-10-11 22:08:30 +00001199 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1200 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001201 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001202 InFlag = Chain.getValue(1);
1203
Dan Gohman475871a2008-07-27 21:46:04 +00001204 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001205 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001206
Scott Michel266bc8f2007-12-04 22:23:35 +00001207 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001208 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001209 default: assert(0 && "Unexpected ret value!");
1210 case MVT::Other: break;
1211 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001212 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001213 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1214 ResultVals[0] = Chain.getValue(0);
1215 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1216 Chain.getValue(2)).getValue(1);
1217 ResultVals[1] = Chain.getValue(0);
1218 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001219 } else {
1220 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1221 ResultVals[0] = Chain.getValue(0);
1222 NumResults = 1;
1223 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001224 break;
1225 case MVT::i64:
1226 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1227 ResultVals[0] = Chain.getValue(0);
1228 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001229 break;
1230 case MVT::f32:
1231 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001232 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001233 InFlag).getValue(1);
1234 ResultVals[0] = Chain.getValue(0);
1235 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001236 break;
1237 case MVT::v2f64:
1238 case MVT::v4f32:
1239 case MVT::v4i32:
1240 case MVT::v8i16:
1241 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001242 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001243 InFlag).getValue(1);
1244 ResultVals[0] = Chain.getValue(0);
1245 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001246 break;
1247 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001248
Scott Michel266bc8f2007-12-04 22:23:35 +00001249 // If the function returns void, just return the chain.
1250 if (NumResults == 0)
1251 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001252
Scott Michel266bc8f2007-12-04 22:23:35 +00001253 // Otherwise, merge everything together with a MERGE_VALUES node.
1254 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001255 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001256 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001257}
1258
Dan Gohman475871a2008-07-27 21:46:04 +00001259static SDValue
1260LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001261 SmallVector<CCValAssign, 16> RVLocs;
1262 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1263 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1264 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001265 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001266
Scott Michel266bc8f2007-12-04 22:23:35 +00001267 // If this is the first return lowered for this function, add the regs to the
1268 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001269 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001270 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001271 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001272 }
1273
Dan Gohman475871a2008-07-27 21:46:04 +00001274 SDValue Chain = Op.getOperand(0);
1275 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001276
Scott Michel266bc8f2007-12-04 22:23:35 +00001277 // Copy the result values into the output registers.
1278 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1279 CCValAssign &VA = RVLocs[i];
1280 assert(VA.isRegLoc() && "Can only return in registers!");
1281 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1282 Flag = Chain.getValue(1);
1283 }
1284
Gabor Greifba36cb52008-08-28 21:40:38 +00001285 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001286 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1287 else
1288 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1289}
1290
1291
1292//===----------------------------------------------------------------------===//
1293// Vector related lowering:
1294//===----------------------------------------------------------------------===//
1295
1296static ConstantSDNode *
1297getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001298 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001299
Scott Michel266bc8f2007-12-04 22:23:35 +00001300 // Check to see if this buildvec has a single non-undef value in its elements.
1301 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1302 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001303 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001304 OpVal = N->getOperand(i);
1305 else if (OpVal != N->getOperand(i))
1306 return 0;
1307 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001308
Gabor Greifba36cb52008-08-28 21:40:38 +00001309 if (OpVal.getNode() != 0) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001310 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001311 return CN;
1312 }
1313 }
1314
1315 return 0; // All UNDEF: use implicit def.; not Constant node
1316}
1317
1318/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1319/// and the value fits into an unsigned 18-bit constant, and if so, return the
1320/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001321SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001322 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001323 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001324 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001325 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001326 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001327 uint32_t upper = uint32_t(UValue >> 32);
1328 uint32_t lower = uint32_t(UValue);
1329 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001330 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001331 Value = Value >> 32;
1332 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001333 if (Value <= 0x3ffff)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001334 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001335 }
1336
Dan Gohman475871a2008-07-27 21:46:04 +00001337 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001338}
1339
1340/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1341/// and the value fits into a signed 16-bit constant, and if so, return the
1342/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001343SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001344 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001345 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001346 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001347 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001348 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001349 uint32_t upper = uint32_t(UValue >> 32);
1350 uint32_t lower = uint32_t(UValue);
1351 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001352 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001353 Value = Value >> 32;
1354 }
Scott Michelad2715e2008-03-05 23:02:02 +00001355 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001356 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001357 }
1358 }
1359
Dan Gohman475871a2008-07-27 21:46:04 +00001360 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001361}
1362
1363/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1364/// and the value fits into a signed 10-bit constant, and if so, return the
1365/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001366SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001367 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001368 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001369 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001370 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001371 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001372 uint32_t upper = uint32_t(UValue >> 32);
1373 uint32_t lower = uint32_t(UValue);
1374 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001375 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001376 Value = Value >> 32;
1377 }
Scott Michelad2715e2008-03-05 23:02:02 +00001378 if (isS10Constant(Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001379 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001380 }
1381
Dan Gohman475871a2008-07-27 21:46:04 +00001382 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001383}
1384
1385/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1386/// and the value fits into a signed 8-bit constant, and if so, return the
1387/// constant.
1388///
1389/// @note: The incoming vector is v16i8 because that's the only way we can load
1390/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1391/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001392SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001393 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001394 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001395 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001396 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001397 && Value <= 0xffff /* truncated from uint64_t */
1398 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001399 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001400 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001401 && (Value & 0xff) == Value)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001402 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001403 }
1404
Dan Gohman475871a2008-07-27 21:46:04 +00001405 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001406}
1407
1408/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1409/// and the value fits into a signed 16-bit constant, and if so, return the
1410/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001411SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001412 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001413 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001414 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001415 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001416 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1417 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001418 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001419 }
1420
Dan Gohman475871a2008-07-27 21:46:04 +00001421 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001422}
1423
1424/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001425SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001426 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001427 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001428 }
1429
Dan Gohman475871a2008-07-27 21:46:04 +00001430 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001431}
1432
1433/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001434SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001435 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001436 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001437 }
1438
Dan Gohman475871a2008-07-27 21:46:04 +00001439 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001440}
1441
1442// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001443// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001444// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1445// zero. Return true if this is not an array of constants, false if it is.
1446//
1447static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1448 uint64_t UndefBits[2]) {
1449 // Start with zero'd results.
1450 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001451
Duncan Sands83ec4b62008-06-06 12:08:01 +00001452 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001453 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001454 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001455
Scott Michel266bc8f2007-12-04 22:23:35 +00001456 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1457 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1458
1459 uint64_t EltBits = 0;
1460 if (OpVal.getOpcode() == ISD::UNDEF) {
1461 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1462 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1463 continue;
Scott Michel19fd42a2008-11-11 03:06:06 +00001464 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001465 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel19fd42a2008-11-11 03:06:06 +00001466 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001467 const APFloat &apf = CN->getValueAPF();
1468 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001469 ? FloatToBits(apf.convertToFloat())
1470 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001471 } else {
1472 // Nonconstant element.
1473 return true;
1474 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001475
Scott Michel266bc8f2007-12-04 22:23:35 +00001476 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1477 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001478
1479 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001480 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1481 return false;
1482}
1483
1484/// If this is a splat (repetition) of a value across the whole vector, return
1485/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001486/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001487/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001488static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001489 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001490 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001491 uint64_t &SplatBits, uint64_t &SplatUndef,
1492 int &SplatSize) {
1493 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1494 // the same as the lower 64-bits, ignoring undefs.
1495 uint64_t Bits64 = Bits128[0] | Bits128[1];
1496 uint64_t Undef64 = Undef128[0] & Undef128[1];
1497 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1498 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1499 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1500 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1501
1502 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1503 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001504
Scott Michel266bc8f2007-12-04 22:23:35 +00001505 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1506 // undefs.
1507 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001508 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001509
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001510 // If the top 16-bits are different than the lower 16-bits, ignoring
1511 // undefs, we have an i32 splat.
1512 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1513 if (MinSplatBits < 16) {
1514 // If the top 8-bits are different than the lower 8-bits, ignoring
1515 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001516 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1517 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001518 // Otherwise, we have an 8-bit splat.
1519 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1520 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1521 SplatSize = 1;
1522 return true;
1523 }
1524 } else {
1525 SplatBits = Bits16;
1526 SplatUndef = Undef16;
1527 SplatSize = 2;
1528 return true;
1529 }
1530 }
1531 } else {
1532 SplatBits = Bits32;
1533 SplatUndef = Undef32;
1534 SplatSize = 4;
1535 return true;
1536 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001537 }
1538 } else {
1539 SplatBits = Bits128[0];
1540 SplatUndef = Undef128[0];
1541 SplatSize = 8;
1542 return true;
1543 }
1544 }
1545
1546 return false; // Can't be a splat if two pieces don't match.
1547}
1548
1549// If this is a case we can't handle, return null and let the default
1550// expansion code take care of it. If we CAN select this case, and if it
1551// selects to a single instruction, return Op. Otherwise, if we can codegen
1552// this case more efficiently than a constant pool load, lower it to the
1553// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001554static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001555 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001556 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001557 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001558 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001559 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001560 uint64_t VectorBits[2];
1561 uint64_t UndefBits[2];
1562 uint64_t SplatBits, SplatUndef;
1563 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001564 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001565 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001566 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001567 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001568 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001569
Duncan Sands83ec4b62008-06-06 12:08:01 +00001570 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001571 default:
1572 case MVT::v4f32: {
1573 uint32_t Value32 = SplatBits;
1574 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001575 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001576 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001577 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001578 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001579 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001580 break;
1581 }
1582 case MVT::v2f64: {
1583 uint64_t f64val = SplatBits;
1584 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001585 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001586 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001587 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001588 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001589 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001590 break;
1591 }
1592 case MVT::v16i8: {
1593 // 8-bit constants have to be expanded to 16-bits
1594 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001595 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001596 for (int i = 0; i < 8; ++i)
1597 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1598 return DAG.getNode(ISD::BIT_CONVERT, VT,
1599 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1600 }
1601 case MVT::v8i16: {
1602 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001603 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001604 Value16 = (unsigned short) (SplatBits & 0xffff);
1605 else
1606 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001607 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1608 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001609 for (int i = 0; i < 8; ++i) Ops[i] = T;
1610 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1611 }
1612 case MVT::v4i32: {
1613 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001614 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001615 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1616 }
1617 case MVT::v2i64: {
1618 uint64_t val = SplatBits;
1619 uint32_t upper = uint32_t(val >> 32);
1620 uint32_t lower = uint32_t(val);
1621
Scott Michel4cb8bd82008-03-06 04:02:54 +00001622 if (upper == lower) {
1623 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001624 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001625 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001626 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001627 SDValue LO32;
1628 SDValue HI32;
1629 SmallVector<SDValue, 16> ShufBytes;
1630 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001631 bool upper_special, lower_special;
1632
1633 // NOTE: This code creates common-case shuffle masks that can be easily
1634 // detected as common expressions. It is not attempting to create highly
1635 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1636
1637 // Detect if the upper or lower half is a special shuffle mask pattern:
1638 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1639 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1640
1641 // Create lower vector if not a special pattern
1642 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001643 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001644 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1645 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1646 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001647 }
1648
1649 // Create upper vector if not a special pattern
1650 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001651 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001652 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1653 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1654 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001655 }
1656
1657 // If either upper or lower are special, then the two input operands are
1658 // the same (basically, one of them is a "don't care")
1659 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001660 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001661 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001662 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001663 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001664 // Unhappy situation... both upper and lower are special, so punt with
1665 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001666 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001667 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001668 Zero, Zero);
1669 }
1670
1671 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001672 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001673 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001674 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001675 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001676 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001677 process_upper = (upper_special && (i & 1) == 0);
1678 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001679
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001680 if (process_upper || process_lower) {
1681 if ((process_upper && upper == 0)
1682 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001683 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001684 else if ((process_upper && upper == 0xffffffff)
1685 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001686 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001687 else if ((process_upper && upper == 0x80000000)
1688 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001689 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001690 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001691 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001692 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001693
1694 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001695 }
1696
1697 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001698 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001699 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001700 }
1701 }
1702 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001703
Dan Gohman475871a2008-07-27 21:46:04 +00001704 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001705}
1706
1707/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1708/// which the Cell can operate. The code inspects V3 to ascertain whether the
1709/// permutation vector, V3, is monotonically increasing with one "exception"
1710/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1711/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1712/// In either case, the net result is going to eventually invoke SHUFB to
1713/// permute/shuffle the bytes from V1 and V2.
1714/// \note
1715/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1716/// control word for byte/halfword/word insertion. This takes care of a single
1717/// element move from V2 into V1.
1718/// \note
1719/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001720static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1721 SDValue V1 = Op.getOperand(0);
1722 SDValue V2 = Op.getOperand(1);
1723 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001724
Scott Michel266bc8f2007-12-04 22:23:35 +00001725 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001726
Scott Michel266bc8f2007-12-04 22:23:35 +00001727 // If we have a single element being moved from V1 to V2, this can be handled
1728 // using the C*[DX] compute mask instructions, but the vector elements have
1729 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001730 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001731 unsigned EltsFromV2 = 0;
1732 unsigned V2Elt = 0;
1733 unsigned V2EltIdx0 = 0;
1734 unsigned CurrElt = 0;
1735 bool monotonic = true;
1736 if (EltVT == MVT::i8)
1737 V2EltIdx0 = 16;
1738 else if (EltVT == MVT::i16)
1739 V2EltIdx0 = 8;
1740 else if (EltVT == MVT::i32)
1741 V2EltIdx0 = 4;
1742 else
1743 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1744
1745 for (unsigned i = 0, e = PermMask.getNumOperands();
1746 EltsFromV2 <= 1 && monotonic && i != e;
1747 ++i) {
1748 unsigned SrcElt;
1749 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1750 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001751 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001752 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001753
1754 if (SrcElt >= V2EltIdx0) {
1755 ++EltsFromV2;
1756 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1757 } else if (CurrElt != SrcElt) {
1758 monotonic = false;
1759 }
1760
1761 ++CurrElt;
1762 }
1763
1764 if (EltsFromV2 == 1 && monotonic) {
1765 // Compute mask and shuffle
1766 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001767 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1768 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001769 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001770 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001771 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001772 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1773 // Copy register's contents as index in INSERT_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001774 SDValue ShufMaskOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001775 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001776 DAG.getTargetConstant(V2Elt, MVT::i32),
1777 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001778 // Use shuffle mask in SHUFB synthetic instruction:
1779 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1780 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001781 // Convert the SHUFFLE_VECTOR mask's input element units to the
1782 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001783 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001784
Dan Gohman475871a2008-07-27 21:46:04 +00001785 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001786 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1787 unsigned SrcElt;
1788 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001789 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001790 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001791 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001792
Scott Michela59d4692008-02-23 18:41:37 +00001793 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001794 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1795 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001796 }
1797 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001798
Dan Gohman475871a2008-07-27 21:46:04 +00001799 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001800 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001801 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1802 }
1803}
1804
Dan Gohman475871a2008-07-27 21:46:04 +00001805static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1806 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001807
Gabor Greifba36cb52008-08-28 21:40:38 +00001808 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001809 // For a constant, build the appropriate constant vector, which will
1810 // eventually simplify to a vector register load.
1811
Gabor Greifba36cb52008-08-28 21:40:38 +00001812 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001813 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001814 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001815 size_t n_copies;
1816
1817 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001818 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001819 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001820 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001821 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1822 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1823 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1824 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1825 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1826 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1827 }
1828
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001829 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001830 for (size_t j = 0; j < n_copies; ++j)
1831 ConstVecValues.push_back(CValue);
1832
1833 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001834 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001835 } else {
1836 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001837 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001838 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1839 case MVT::i8:
1840 case MVT::i16:
1841 case MVT::i32:
1842 case MVT::i64:
1843 case MVT::f32:
1844 case MVT::f64:
1845 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1846 }
1847 }
1848
Dan Gohman475871a2008-07-27 21:46:04 +00001849 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001850}
1851
Dan Gohman475871a2008-07-27 21:46:04 +00001852static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001853 switch (Op.getValueType().getSimpleVT()) {
1854 default:
1855 cerr << "CellSPU: Unknown vector multiplication, got "
1856 << Op.getValueType().getMVTString()
1857 << "\n";
1858 abort();
1859 /*NOTREACHED*/
1860
Scott Michel266bc8f2007-12-04 22:23:35 +00001861 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001862 SDValue rA = Op.getOperand(0);
1863 SDValue rB = Op.getOperand(1);
1864 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1865 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1866 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1867 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001868
1869 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1870 break;
1871 }
1872
1873 // Multiply two v8i16 vectors (pipeline friendly version):
1874 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1875 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1876 // c) Use SELB to select upper and lower halves from the intermediate results
1877 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001878 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001879 // dual-issue. This code does manage to do this, even if it's a little on
1880 // the wacky side
1881 case MVT::v8i16: {
1882 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001883 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001884 SDValue Chain = Op.getOperand(0);
1885 SDValue rA = Op.getOperand(0);
1886 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001887 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1888 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001889
Dan Gohman475871a2008-07-27 21:46:04 +00001890 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001891 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001892 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001893 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001894
Dan Gohman475871a2008-07-27 21:46:04 +00001895 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001896 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001897 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001898
Dan Gohman475871a2008-07-27 21:46:04 +00001899 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001900 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001901 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001902
1903 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001904 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1905 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1906 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1907 HHProd_v4i32,
1908 DAG.getConstant(16, MVT::i16))),
1909 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001910 }
1911
1912 // This M00sE is N@stI! (apologies to Monty Python)
1913 //
1914 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1915 // is to break it all apart, sign extend, and reassemble the various
1916 // intermediate products.
1917 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001918 SDValue rA = Op.getOperand(0);
1919 SDValue rB = Op.getOperand(1);
1920 SDValue c8 = DAG.getConstant(8, MVT::i32);
1921 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001922
Dan Gohman475871a2008-07-27 21:46:04 +00001923 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001924 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001925 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1926 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001927
Dan Gohman475871a2008-07-27 21:46:04 +00001928 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001929
Dan Gohman475871a2008-07-27 21:46:04 +00001930 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001931
Dan Gohman475871a2008-07-27 21:46:04 +00001932 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001933 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001934 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001935
Dan Gohman475871a2008-07-27 21:46:04 +00001936 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001937 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001938
Dan Gohman475871a2008-07-27 21:46:04 +00001939 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001940 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1941 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1942 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001943
Dan Gohman475871a2008-07-27 21:46:04 +00001944 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001945
Dan Gohman475871a2008-07-27 21:46:04 +00001946 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001947 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00001948 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001949 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1950 LoProdMask, LoProdMask,
1951 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001952
Dan Gohman475871a2008-07-27 21:46:04 +00001953 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001954 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001955 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001956
Dan Gohman475871a2008-07-27 21:46:04 +00001957 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001958 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001959 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001960
Dan Gohman475871a2008-07-27 21:46:04 +00001961 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001962 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001963 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1964 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00001965
Dan Gohman475871a2008-07-27 21:46:04 +00001966 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001967 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001968 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001969 DAG.getNode(SPUISD::VEC_SRA,
1970 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001971 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001972 DAG.getNode(SPUISD::VEC_SRA,
1973 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001974
Dan Gohman475871a2008-07-27 21:46:04 +00001975 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00001976 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1977 HLProd,
1978 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
1979 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00001980
Dan Gohman475871a2008-07-27 21:46:04 +00001981 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00001982 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001983
1984 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001985 DAG.getNode(ISD::OR, MVT::v4i32,
1986 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00001987 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001988 }
1989
Dan Gohman475871a2008-07-27 21:46:04 +00001990 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001991}
1992
Dan Gohman475871a2008-07-27 21:46:04 +00001993static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001994 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001995 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00001996
Dan Gohman475871a2008-07-27 21:46:04 +00001997 SDValue A = Op.getOperand(0);
1998 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001999 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002000
2001 unsigned VRegBR, VRegC;
2002
2003 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002004 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2005 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002006 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002007 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2008 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002009 }
2010 // TODO: make sure we're feeding FPInterp the right arguments
2011 // Right now: fi B, frest(B)
2012
2013 // Computes BRcpl =
2014 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002015 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002016 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2017 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002018 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002019
Scott Michel266bc8f2007-12-04 22:23:35 +00002020 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002021 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002022 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002023 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002024 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002025 // What's the Chain variable do? It's magic!
2026 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002027
2028 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002029 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002030 DAG.getNode(ISD::FMUL, VT,
2031 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002032 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002033 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002034 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002035}
2036
Dan Gohman475871a2008-07-27 21:46:04 +00002037static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002038 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002039 SDValue N = Op.getOperand(0);
2040 SDValue Elt = Op.getOperand(1);
2041 SDValue ShufMask[16];
Scott Michel19fd42a2008-11-11 03:06:06 +00002042 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
Scott Michel266bc8f2007-12-04 22:23:35 +00002043
2044 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2045
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002046 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002047
2048 // sanity checks:
2049 if (VT == MVT::i8 && EltNo >= 16)
2050 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2051 else if (VT == MVT::i16 && EltNo >= 8)
2052 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2053 else if (VT == MVT::i32 && EltNo >= 4)
2054 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2055 else if (VT == MVT::i64 && EltNo >= 2)
2056 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2057
2058 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2059 // i32 and i64: Element 0 is the preferred slot
2060 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2061 }
2062
2063 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002064 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002065 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002066
Duncan Sands83ec4b62008-06-06 12:08:01 +00002067 switch (VT.getSimpleVT()) {
2068 default:
2069 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002070 case MVT::i8: {
2071 prefslot_begin = prefslot_end = 3;
2072 break;
2073 }
2074 case MVT::i16: {
2075 prefslot_begin = 2; prefslot_end = 3;
2076 break;
2077 }
Scott Michel73ce1c52008-11-10 23:43:06 +00002078 case MVT::i32:
2079 case MVT::f32: {
Scott Michel266bc8f2007-12-04 22:23:35 +00002080 prefslot_begin = 0; prefslot_end = 3;
2081 break;
2082 }
Scott Michel73ce1c52008-11-10 23:43:06 +00002083 case MVT::i64:
2084 case MVT::f64: {
Scott Michel266bc8f2007-12-04 22:23:35 +00002085 prefslot_begin = 0; prefslot_end = 7;
2086 break;
2087 }
2088 }
2089
Scott Michel0e5665b2007-12-19 21:17:42 +00002090 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002091 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002092
Scott Michel266bc8f2007-12-04 22:23:35 +00002093 for (int i = 0; i < 16; ++i) {
2094 // zero fill uppper part of preferred slot, don't care about the
2095 // other slots:
2096 unsigned int mask_val;
2097
2098 if (i <= prefslot_end) {
2099 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002100 ((i < prefslot_begin)
2101 ? 0x80
2102 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002103
Scott Michel0e5665b2007-12-19 21:17:42 +00002104 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002105 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002106 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2107 }
2108
Dan Gohman475871a2008-07-27 21:46:04 +00002109 SDValue ShufMaskVec =
Scott Michel266bc8f2007-12-04 22:23:35 +00002110 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002111 &ShufMask[0],
2112 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002113
2114 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002115 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2116 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002117
Scott Michel266bc8f2007-12-04 22:23:35 +00002118}
2119
Dan Gohman475871a2008-07-27 21:46:04 +00002120static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2121 SDValue VecOp = Op.getOperand(0);
2122 SDValue ValOp = Op.getOperand(1);
2123 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002124 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002125
2126 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2127 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2128
Duncan Sands83ec4b62008-06-06 12:08:01 +00002129 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002130 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002131 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002132
Dan Gohman475871a2008-07-27 21:46:04 +00002133 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002134 DAG.getNode(SPUISD::SHUFB, VT,
2135 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2136 VecOp,
2137 DAG.getNode(SPUISD::INSERT_MASK, VT,
2138 DAG.getNode(ISD::ADD, PtrVT,
2139 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002140 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002141 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002142
2143 return result;
2144}
2145
Dan Gohman475871a2008-07-27 21:46:04 +00002146static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002147{
Dan Gohman475871a2008-07-27 21:46:04 +00002148 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002149
2150 assert(Op.getValueType() == MVT::i8);
2151 switch (Opc) {
2152 default:
2153 assert(0 && "Unhandled i8 math operator");
2154 /*NOTREACHED*/
2155 break;
2156 case ISD::SUB: {
2157 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2158 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002159 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002160 N0 = (N0.getOpcode() != ISD::Constant
2161 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002162 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2163 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002164 N1 = (N1.getOpcode() != ISD::Constant
2165 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002166 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2167 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002168 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002169 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002170 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002171 case ISD::ROTR:
2172 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002173 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002174 unsigned N1Opc;
2175 N0 = (N0.getOpcode() != ISD::Constant
2176 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002177 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2178 MVT::i16));
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002179 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greif93c53e52008-08-31 15:37:04 +00002180 ? ISD::ZERO_EXTEND
2181 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002182 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002183 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002184 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002185 MVT::i32));
Dan Gohman475871a2008-07-27 21:46:04 +00002186 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002187 DAG.getNode(ISD::OR, MVT::i16, N0,
2188 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002189 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002190 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002191 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2192 }
2193 case ISD::SRL:
2194 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002195 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002196 unsigned N1Opc;
2197 N0 = (N0.getOpcode() != ISD::Constant
2198 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002199 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2200 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002201 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2202 ? ISD::ZERO_EXTEND
2203 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002204 N1 = (N1.getOpcode() != ISD::Constant
2205 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002206 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2207 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002208 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002209 DAG.getNode(Opc, MVT::i16, N0, N1));
2210 }
2211 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002212 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002213 unsigned N1Opc;
2214 N0 = (N0.getOpcode() != ISD::Constant
2215 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002216 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2217 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002218 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2219 ? ISD::SIGN_EXTEND
2220 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002221 N1 = (N1.getOpcode() != ISD::Constant
2222 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002223 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2224 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002225 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002226 DAG.getNode(Opc, MVT::i16, N0, N1));
2227 }
2228 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002229 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002230 unsigned N1Opc;
2231 N0 = (N0.getOpcode() != ISD::Constant
2232 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002233 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2234 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002235 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002236 N1 = (N1.getOpcode() != ISD::Constant
2237 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002238 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2239 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002240 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002241 DAG.getNode(Opc, MVT::i16, N0, N1));
2242 break;
2243 }
2244 }
2245
Dan Gohman475871a2008-07-27 21:46:04 +00002246 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002247}
2248
Dan Gohman475871a2008-07-27 21:46:04 +00002249static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002250{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002251 MVT VT = Op.getValueType();
2252 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002253
Dan Gohman475871a2008-07-27 21:46:04 +00002254 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002255
2256 switch (Opc) {
2257 case ISD::ZERO_EXTEND:
2258 case ISD::SIGN_EXTEND:
2259 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002260 MVT Op0VT = Op0.getValueType();
2261 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002262
2263 assert(Op0VT == MVT::i32
2264 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002265 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002266
2267 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2268 ? SPUISD::ROTBYTES_RIGHT_S
2269 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002270 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002271 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2272
2273 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2274 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2275 DAG.getNode(NewOpc, Op0VecVT,
2276 PromoteScalar,
2277 DAG.getConstant(4, MVT::i32))));
2278 }
2279
Scott Michel8bf61e82008-06-02 22:18:03 +00002280 case ISD::ADD: {
2281 // Turn operands into vectors to satisfy type checking (shufb works on
2282 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002283 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002284 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002285 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002286 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002287 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002288
2289 // Create the shuffle mask for "rotating" the borrow up one register slot
2290 // once the borrow is generated.
2291 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2292 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2293 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2294 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2295
Dan Gohman475871a2008-07-27 21:46:04 +00002296 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002297 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002298 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002299 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2300 CarryGen, CarryGen,
2301 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2302 &ShufBytes[0], ShufBytes.size()));
2303
2304 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2305 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2306 Op0, Op1, ShiftedCarry));
2307 }
2308
2309 case ISD::SUB: {
2310 // Turn operands into vectors to satisfy type checking (shufb works on
2311 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002312 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002313 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002314 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002315 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002316 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002317
2318 // Create the shuffle mask for "rotating" the borrow up one register slot
2319 // once the borrow is generated.
2320 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2321 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2322 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2323 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2324
Dan Gohman475871a2008-07-27 21:46:04 +00002325 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002326 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002327 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002328 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2329 BorrowGen, BorrowGen,
2330 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2331 &ShufBytes[0], ShufBytes.size()));
2332
2333 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2334 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2335 Op0, Op1, ShiftedBorrow));
2336 }
2337
Scott Michela59d4692008-02-23 18:41:37 +00002338 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002339 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002340 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002341 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2342 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002343 DAG.getNode(SPUISD::SELB, VecVT,
2344 Op0Vec,
2345 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002346 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002347 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002348 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002349 DAG.getNode(ISD::SRL, ShiftAmtVT,
2350 ShiftAmt,
2351 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002352 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002353 DAG.getNode(ISD::AND, ShiftAmtVT,
2354 ShiftAmt,
2355 DAG.getConstant(7, ShiftAmtVT));
2356
2357 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2358 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2359 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2360 MaskLower, ShiftAmtBytes),
2361 ShiftAmtBits));
2362 }
2363
2364 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002365 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002366 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002367 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002368 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002369 DAG.getNode(ISD::SRL, ShiftAmtVT,
2370 ShiftAmt,
2371 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002372 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002373 DAG.getNode(ISD::AND, ShiftAmtVT,
2374 ShiftAmt,
2375 DAG.getConstant(7, ShiftAmtVT));
2376
2377 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2378 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2379 Op0, ShiftAmtBytes),
2380 ShiftAmtBits);
2381 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002382
2383 case ISD::SRA: {
2384 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002385 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002386 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002387 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002388 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002389
2390 // Negate variable shift amounts
2391 if (!isa<ConstantSDNode>(ShiftAmt)) {
2392 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2393 DAG.getConstant(0, ShiftVT), ShiftAmt);
2394 }
2395
Dan Gohman475871a2008-07-27 21:46:04 +00002396 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002397 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2398 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2399 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2400 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002401 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002402 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002403 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002404 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2405 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002406 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002407 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2408 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002409 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002410 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2411 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002412 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002413 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2414 RotateLeftBytes, ShiftAmt);
2415
2416 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2417 RotateLeftBits);
2418 }
Scott Michela59d4692008-02-23 18:41:37 +00002419 }
2420
Dan Gohman475871a2008-07-27 21:46:04 +00002421 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002422}
2423
Scott Michel266bc8f2007-12-04 22:23:35 +00002424//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002425static SDValue
2426LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2427 SDValue ConstVec;
2428 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002429 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002430
2431 ConstVec = Op.getOperand(0);
2432 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002433 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2434 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002435 ConstVec = ConstVec.getOperand(0);
2436 } else {
2437 ConstVec = Op.getOperand(1);
2438 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002439 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002440 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002441 }
2442 }
2443 }
2444
Gabor Greifba36cb52008-08-28 21:40:38 +00002445 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002446 uint64_t VectorBits[2];
2447 uint64_t UndefBits[2];
2448 uint64_t SplatBits, SplatUndef;
2449 int SplatSize;
2450
Gabor Greifba36cb52008-08-28 21:40:38 +00002451 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002452 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002453 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002454 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002455 SDValue tcVec[16];
2456 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002457 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2458
2459 // Turn the BUILD_VECTOR into a set of target constants:
2460 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002461 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002462
Gabor Greifba36cb52008-08-28 21:40:38 +00002463 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002464 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002465 }
2466 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002467 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2468 // lowered. Return the operation, rather than a null SDValue.
2469 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002470}
2471
2472//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002473static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002474 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002475 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002476 default:
2477 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002478 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002479 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002480 abort();
2481 /*NOTREACHED*/
2482
2483 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002484 SDValue rA = Op.getOperand(0);
2485 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002486
2487 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002488 DAG.getNode(ISD::ADD, MVT::i32,
2489 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2490 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2491 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002492 }
2493 }
2494
Dan Gohman475871a2008-07-27 21:46:04 +00002495 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002496}
2497
2498//! Custom lowering for CTPOP (count population)
2499/*!
2500 Custom lowering code that counts the number ones in the input
2501 operand. SPU has such an instruction, but it counts the number of
2502 ones per byte, which then have to be accumulated.
2503*/
Dan Gohman475871a2008-07-27 21:46:04 +00002504static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002505 MVT VT = Op.getValueType();
2506 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002507
Duncan Sands83ec4b62008-06-06 12:08:01 +00002508 switch (VT.getSimpleVT()) {
2509 default:
2510 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002511 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002512 SDValue N = Op.getOperand(0);
2513 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002514
Dan Gohman475871a2008-07-27 21:46:04 +00002515 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2516 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002517
2518 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2519 }
2520
2521 case MVT::i16: {
2522 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002523 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002524
Chris Lattner84bc5422007-12-31 04:13:23 +00002525 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002526
Dan Gohman475871a2008-07-27 21:46:04 +00002527 SDValue N = Op.getOperand(0);
2528 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2529 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002530 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002531
Dan Gohman475871a2008-07-27 21:46:04 +00002532 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2533 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002534
2535 // CNTB_result becomes the chain to which all of the virtual registers
2536 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002537 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002538 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002539
Dan Gohman475871a2008-07-27 21:46:04 +00002540 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002541 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2542
Dan Gohman475871a2008-07-27 21:46:04 +00002543 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002544
2545 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002546 DAG.getNode(ISD::ADD, MVT::i16,
2547 DAG.getNode(ISD::SRL, MVT::i16,
2548 Tmp1, Shift1),
2549 Tmp1),
2550 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002551 }
2552
2553 case MVT::i32: {
2554 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002555 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002556
Chris Lattner84bc5422007-12-31 04:13:23 +00002557 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2558 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002559
Dan Gohman475871a2008-07-27 21:46:04 +00002560 SDValue N = Op.getOperand(0);
2561 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2562 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2563 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2564 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002565
Dan Gohman475871a2008-07-27 21:46:04 +00002566 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2567 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002568
2569 // CNTB_result becomes the chain to which all of the virtual registers
2570 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002571 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002572 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002573
Dan Gohman475871a2008-07-27 21:46:04 +00002574 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002575 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2576
Dan Gohman475871a2008-07-27 21:46:04 +00002577 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002578 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002579 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002580
Dan Gohman475871a2008-07-27 21:46:04 +00002581 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002582 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002583 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002584
Dan Gohman475871a2008-07-27 21:46:04 +00002585 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002586 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2587
Dan Gohman475871a2008-07-27 21:46:04 +00002588 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002589 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002590 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2591 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002592 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002593 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002594 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002595
2596 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2597 }
2598
2599 case MVT::i64:
2600 break;
2601 }
2602
Dan Gohman475871a2008-07-27 21:46:04 +00002603 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002604}
2605
2606/// LowerOperation - Provide custom lowering hooks for some operations.
2607///
Dan Gohman475871a2008-07-27 21:46:04 +00002608SDValue
2609SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002610{
Scott Michela59d4692008-02-23 18:41:37 +00002611 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002612 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002613
2614 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002615 default: {
2616 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002617 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002618 cerr << "*Op.getNode():\n";
2619 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002620 abort();
2621 }
2622 case ISD::LOAD:
2623 case ISD::SEXTLOAD:
2624 case ISD::ZEXTLOAD:
2625 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2626 case ISD::STORE:
2627 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2628 case ISD::ConstantPool:
2629 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2630 case ISD::GlobalAddress:
2631 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2632 case ISD::JumpTable:
2633 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2634 case ISD::Constant:
2635 return LowerConstant(Op, DAG);
2636 case ISD::ConstantFP:
2637 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002638 case ISD::BRCOND:
2639 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002640 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002641 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002642 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002643 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002644 case ISD::RET:
2645 return LowerRET(Op, DAG, getTargetMachine());
2646
Scott Michela59d4692008-02-23 18:41:37 +00002647
2648 // i8, i64 math ops:
2649 case ISD::ZERO_EXTEND:
2650 case ISD::SIGN_EXTEND:
2651 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002652 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002653 case ISD::SUB:
2654 case ISD::ROTR:
2655 case ISD::ROTL:
2656 case ISD::SRL:
2657 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002658 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002659 if (VT == MVT::i8)
2660 return LowerI8Math(Op, DAG, Opc);
2661 else if (VT == MVT::i64)
2662 return LowerI64Math(Op, DAG, Opc);
2663 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002664 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002665
2666 // Vector-related lowering.
2667 case ISD::BUILD_VECTOR:
2668 return LowerBUILD_VECTOR(Op, DAG);
2669 case ISD::SCALAR_TO_VECTOR:
2670 return LowerSCALAR_TO_VECTOR(Op, DAG);
2671 case ISD::VECTOR_SHUFFLE:
2672 return LowerVECTOR_SHUFFLE(Op, DAG);
2673 case ISD::EXTRACT_VECTOR_ELT:
2674 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2675 case ISD::INSERT_VECTOR_ELT:
2676 return LowerINSERT_VECTOR_ELT(Op, DAG);
2677
2678 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2679 case ISD::AND:
2680 case ISD::OR:
2681 case ISD::XOR:
2682 return LowerByteImmed(Op, DAG);
2683
2684 // Vector and i8 multiply:
2685 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002686 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002687 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002688 else if (VT == MVT::i8)
2689 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002690 else
Scott Michela59d4692008-02-23 18:41:37 +00002691 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002692
2693 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002694 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002695 return LowerFDIVf32(Op, DAG);
2696// else if (Op.getValueType() == MVT::f64)
2697// return LowerFDIVf64(Op, DAG);
2698 else
2699 assert(0 && "Calling FDIV on unsupported MVT");
2700
2701 case ISD::CTPOP:
2702 return LowerCTPOP(Op, DAG);
2703 }
2704
Dan Gohman475871a2008-07-27 21:46:04 +00002705 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002706}
2707
Scott Michel73ce1c52008-11-10 23:43:06 +00002708SDNode *SPUTargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG)
2709{
2710#if 0
2711 unsigned Opc = (unsigned) N->getOpcode();
2712 MVT OpVT = N->getValueType(0);
2713
2714 switch (Opc) {
2715 default: {
2716 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2717 cerr << "Op.getOpcode() = " << Opc << "\n";
2718 cerr << "*Op.getNode():\n";
2719 N->dump();
2720 abort();
2721 /*NOTREACHED*/
2722 }
2723 }
2724#endif
2725
2726 /* Otherwise, return unchanged */
2727 return 0;
2728}
2729
Scott Michel266bc8f2007-12-04 22:23:35 +00002730//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002731// Target Optimization Hooks
2732//===----------------------------------------------------------------------===//
2733
Dan Gohman475871a2008-07-27 21:46:04 +00002734SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002735SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2736{
2737#if 0
2738 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002739#endif
2740 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002741 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002742 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2743 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002744
2745 switch (N->getOpcode()) {
2746 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002747 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002748 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002749
Scott Michel8bf61e82008-06-02 22:18:03 +00002750 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002751 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002752 if (Op01.getOpcode() == ISD::Constant
2753 || Op01.getOpcode() == ISD::TargetConstant) {
2754 // (add <const>, (SPUindirect <arg>, <const>)) ->
2755 // (SPUindirect <arg>, <const + const>)
2756 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2757 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002758 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002759 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002760 Op0.getValueType());
2761
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002762 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2763 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002764 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002765 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002766 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2767 Op0.getOperand(0), combinedConst);
2768 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002769 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002770 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002771 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002772 if (Op11.getOpcode() == ISD::Constant
2773 || Op11.getOpcode() == ISD::TargetConstant) {
2774 // (add (SPUindirect <arg>, <const>), <const>) ->
2775 // (SPUindirect <arg>, <const + const>)
2776 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2777 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002778 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002779 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002780 Op0.getValueType());
2781
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002782 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2783 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002784 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002785 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002786
2787 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2788 Op1.getOperand(0), combinedConst);
2789 }
2790 }
Scott Michela59d4692008-02-23 18:41:37 +00002791 break;
2792 }
2793 case ISD::SIGN_EXTEND:
2794 case ISD::ZERO_EXTEND:
2795 case ISD::ANY_EXTEND: {
2796 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2797 N->getValueType(0) == Op0.getValueType()) {
2798 // (any_extend (SPUextract_elt0 <arg>)) ->
2799 // (SPUextract_elt0 <arg>)
2800 // Types must match, however...
2801 DEBUG(cerr << "Replace: ");
2802 DEBUG(N->dump(&DAG));
2803 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002804 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002805 DEBUG(cerr << "\n");
2806
2807 return Op0;
2808 }
2809 break;
2810 }
2811 case SPUISD::IndirectAddr: {
2812 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2813 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002814 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002815 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2816 // (SPUaform <addr>, 0)
2817
2818 DEBUG(cerr << "Replace: ");
2819 DEBUG(N->dump(&DAG));
2820 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002821 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002822 DEBUG(cerr << "\n");
2823
2824 return Op0;
2825 }
2826 }
2827 break;
2828 }
2829 case SPUISD::SHLQUAD_L_BITS:
2830 case SPUISD::SHLQUAD_L_BYTES:
2831 case SPUISD::VEC_SHL:
2832 case SPUISD::VEC_SRL:
2833 case SPUISD::VEC_SRA:
2834 case SPUISD::ROTQUAD_RZ_BYTES:
2835 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002836 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002837
2838 if (isa<ConstantSDNode>(Op1)) {
2839 // Kill degenerate vector shifts:
2840 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2841
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002842 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002843 Result = Op0;
2844 }
2845 }
2846 break;
2847 }
2848 case SPUISD::PROMOTE_SCALAR: {
2849 switch (Op0.getOpcode()) {
2850 default:
2851 break;
2852 case ISD::ANY_EXTEND:
2853 case ISD::ZERO_EXTEND:
2854 case ISD::SIGN_EXTEND: {
2855 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2856 // <arg>
2857 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002858 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002859 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00002860 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002861 if (Op000.getValueType() == N->getValueType(0)) {
2862 Result = Op000;
2863 }
2864 }
2865 break;
2866 }
2867 case SPUISD::EXTRACT_ELT0: {
2868 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2869 // <arg>
2870 Result = Op0.getOperand(0);
2871 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002872 }
Scott Michela59d4692008-02-23 18:41:37 +00002873 }
2874 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002875 }
2876 }
Scott Michel58c58182008-01-17 20:38:41 +00002877 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002878#if 1
Gabor Greifba36cb52008-08-28 21:40:38 +00002879 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00002880 DEBUG(cerr << "\nReplace.SPU: ");
2881 DEBUG(N->dump(&DAG));
2882 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002883 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002884 DEBUG(cerr << "\n");
2885 }
2886#endif
2887
2888 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002889}
2890
2891//===----------------------------------------------------------------------===//
2892// Inline Assembly Support
2893//===----------------------------------------------------------------------===//
2894
2895/// getConstraintType - Given a constraint letter, return the type of
2896/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002897SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002898SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2899 if (ConstraintLetter.size() == 1) {
2900 switch (ConstraintLetter[0]) {
2901 default: break;
2902 case 'b':
2903 case 'r':
2904 case 'f':
2905 case 'v':
2906 case 'y':
2907 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002908 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002909 }
2910 return TargetLowering::getConstraintType(ConstraintLetter);
2911}
2912
Scott Michel5af8f0e2008-07-16 17:17:29 +00002913std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002914SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002915 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002916{
2917 if (Constraint.size() == 1) {
2918 // GCC RS6000 Constraint Letters
2919 switch (Constraint[0]) {
2920 case 'b': // R1-R31
2921 case 'r': // R0-R31
2922 if (VT == MVT::i64)
2923 return std::make_pair(0U, SPU::R64CRegisterClass);
2924 return std::make_pair(0U, SPU::R32CRegisterClass);
2925 case 'f':
2926 if (VT == MVT::f32)
2927 return std::make_pair(0U, SPU::R32FPRegisterClass);
2928 else if (VT == MVT::f64)
2929 return std::make_pair(0U, SPU::R64FPRegisterClass);
2930 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002931 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002932 return std::make_pair(0U, SPU::GPRCRegisterClass);
2933 }
2934 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002935
Scott Michel266bc8f2007-12-04 22:23:35 +00002936 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2937}
2938
Scott Michela59d4692008-02-23 18:41:37 +00002939//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002940void
Dan Gohman475871a2008-07-27 21:46:04 +00002941SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002942 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002943 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002944 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002945 const SelectionDAG &DAG,
2946 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002947#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002948 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002949#endif
Scott Michela59d4692008-02-23 18:41:37 +00002950
2951 switch (Op.getOpcode()) {
2952 default:
2953 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2954 break;
2955
2956#if 0
2957 case CALL:
2958 case SHUFB:
2959 case INSERT_MASK:
2960 case CNTB:
2961#endif
2962
2963 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00002964 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002965 MVT Op0VT = Op0.getValueType();
2966 unsigned Op0VTBits = Op0VT.getSizeInBits();
2967 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002968 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2969 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002970 break;
2971 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002972
Scott Michela59d4692008-02-23 18:41:37 +00002973 case SPUISD::LDRESULT:
2974 case SPUISD::EXTRACT_ELT0:
2975 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002976 MVT OpVT = Op.getValueType();
2977 unsigned OpVTBits = OpVT.getSizeInBits();
2978 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002979 KnownZero |= APInt(OpVTBits, ~InMask, false);
2980 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002981 break;
2982 }
2983
2984#if 0
2985 case EXTRACT_I1_ZEXT:
2986 case EXTRACT_I1_SEXT:
2987 case EXTRACT_I8_ZEXT:
2988 case EXTRACT_I8_SEXT:
2989 case MPY:
2990 case MPYU:
2991 case MPYH:
2992 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00002993 case SPUISD::SHLQUAD_L_BITS:
2994 case SPUISD::SHLQUAD_L_BYTES:
2995 case SPUISD::VEC_SHL:
2996 case SPUISD::VEC_SRL:
2997 case SPUISD::VEC_SRA:
2998 case SPUISD::VEC_ROTL:
2999 case SPUISD::VEC_ROTR:
3000 case SPUISD::ROTQUAD_RZ_BYTES:
3001 case SPUISD::ROTQUAD_RZ_BITS:
3002 case SPUISD::ROTBYTES_RIGHT_S:
3003 case SPUISD::ROTBYTES_LEFT:
3004 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003005 case SPUISD::SELECT_MASK:
3006 case SPUISD::SELB:
3007 case SPUISD::FPInterp:
3008 case SPUISD::FPRecipEst:
3009 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003010#endif
3011 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003012}
3013
Scott Michel203b2d62008-04-30 00:30:08 +00003014// LowerAsmOperandForConstraint
3015void
Dan Gohman475871a2008-07-27 21:46:04 +00003016SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003017 char ConstraintLetter,
Evan Chengda43bcf2008-09-24 00:05:32 +00003018 bool hasMemory,
Dan Gohman475871a2008-07-27 21:46:04 +00003019 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003020 SelectionDAG &DAG) const {
3021 // Default, for the time being, to the base class handler
Evan Chengda43bcf2008-09-24 00:05:32 +00003022 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3023 Ops, DAG);
Scott Michel203b2d62008-04-30 00:30:08 +00003024}
3025
Scott Michel266bc8f2007-12-04 22:23:35 +00003026/// isLegalAddressImmediate - Return true if the integer value can be used
3027/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003028bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3029 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003030 // SPU's addresses are 256K:
3031 return (V > -(1 << 18) && V < (1 << 18) - 1);
3032}
3033
3034bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003035 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003036}
Dan Gohman6520e202008-10-18 02:06:02 +00003037
3038bool
3039SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3040 // The SPU target isn't yet aware of offsets.
3041 return false;
3042}