blob: 607d0dcc048c04b29eb6a480ef648fd77bc848fe [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 */
88 bool isMemoryOperand(const SDOperand &Op)
89 {
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
95 || Opc == ISD::ExternalSymbol
96 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
100 || 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
105 bool isIndirectOperand(const SDOperand &Op)
106 {
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:
Scott Michel58c58182008-01-17 20:38:41 +0000134 setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +0000135 setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote);
136 setLoadXAction(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
143 setLoadXAction(ISD::EXTLOAD, MVT::i8, Custom);
144 setLoadXAction(ISD::SEXTLOAD, MVT::i8, Custom);
145 setLoadXAction(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
Scott Michel266bc8f2007-12-04 22:23:35 +0000152 setLoadXAction(ISD::EXTLOAD, MVT::i16, Custom);
153 setLoadXAction(ISD::SEXTLOAD, MVT::i16, Custom);
154 setLoadXAction(ISD::ZEXTLOAD, MVT::i16, Custom);
155
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.
205 setOperationAction(ISD::ROTR, MVT::i32, Legal);
206 setOperationAction(ISD::ROTR, MVT::i16, Legal);
207 setOperationAction(ISD::ROTR, MVT::i8, Custom);
208 setOperationAction(ISD::ROTL, MVT::i32, Legal);
209 setOperationAction(ISD::ROTL, MVT::i16, Legal);
210 setOperationAction(ISD::ROTL, MVT::i8, Custom);
211 // SPU has no native version of shift left/right for i8
212 setOperationAction(ISD::SHL, MVT::i8, Custom);
213 setOperationAction(ISD::SRL, MVT::i8, Custom);
214 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michela59d4692008-02-23 18:41:37 +0000215 // And SPU needs custom lowering for shift left/right for i64
216 setOperationAction(ISD::SHL, MVT::i64, Custom);
217 setOperationAction(ISD::SRL, MVT::i64, Custom);
218 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000219
Scott Michel5af8f0e2008-07-16 17:17:29 +0000220 // Custom lower i8, i32 and i64 multiplications
221 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000222 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000223 setOperationAction(ISD::MUL, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000224
Scott Michel8bf61e82008-06-02 22:18:03 +0000225 // Need to custom handle (some) common i8, i64 math ops
226 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000227 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel8bf61e82008-06-02 22:18:03 +0000228 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000229
Scott Michel266bc8f2007-12-04 22:23:35 +0000230 // SPU does not have BSWAP. It does have i32 support CTLZ.
231 // CTPOP has to be custom lowered.
232 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
233 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
234
235 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
236 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
237 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
238 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
239
240 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
241 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
242
243 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000244
Scott Michel8bf61e82008-06-02 22:18:03 +0000245 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000246 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000247 setOperationAction(ISD::SELECT, MVT::i1, Promote);
248 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000249 setOperationAction(ISD::SELECT, MVT::i16, Legal);
250 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000251 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000252
Scott Michel78c47fa2008-03-10 16:58:52 +0000253 setOperationAction(ISD::SETCC, MVT::i1, Promote);
254 setOperationAction(ISD::SETCC, MVT::i8, Legal);
255 setOperationAction(ISD::SETCC, MVT::i16, Legal);
256 setOperationAction(ISD::SETCC, MVT::i32, Legal);
257 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michelad2715e2008-03-05 23:02:02 +0000258
Scott Michela59d4692008-02-23 18:41:37 +0000259 // Zero extension and sign extension for i64 have to be
260 // custom legalized
261 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
262 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
263 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000264
Scott Michel266bc8f2007-12-04 22:23:35 +0000265 // SPU has a legal FP -> signed INT instruction
266 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
267 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
268 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
269 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
270
271 // FDIV on SPU requires custom lowering
272 setOperationAction(ISD::FDIV, MVT::f32, Custom);
273 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
274
275 // SPU has [U|S]INT_TO_FP
276 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
277 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
278 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
279 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
280 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
281 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
282 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
283 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
284
Scott Michel86c041f2007-12-20 00:44:13 +0000285 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
286 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
287 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
288 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000289
290 // We cannot sextinreg(i1). Expand to shifts.
291 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000292
Scott Michel266bc8f2007-12-04 22:23:35 +0000293 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000294 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000295 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000296
297 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000298 // appropriate instructions to materialize the address.
Scott Michel053c1da2008-01-29 02:16:57 +0000299 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
300 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000301 MVT VT = (MVT::SimpleValueType)sctype;
302
303 setOperationAction(ISD::GlobalAddress, VT, Custom);
304 setOperationAction(ISD::ConstantPool, VT, Custom);
305 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000306 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000307
308 // RET must be custom lowered, to meet ABI requirements
309 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000310
Scott Michel266bc8f2007-12-04 22:23:35 +0000311 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
312 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000313
Scott Michel266bc8f2007-12-04 22:23:35 +0000314 // Use the default implementation.
315 setOperationAction(ISD::VAARG , MVT::Other, Expand);
316 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
317 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000318 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000319 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
320 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
321 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
322
323 // Cell SPU has instructions for converting between i64 and fp.
324 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
325 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000326
Scott Michel266bc8f2007-12-04 22:23:35 +0000327 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
328 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
329
330 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
331 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
332
333 // First set operation action for all vector types to expand. Then we
334 // will selectively turn on ones that can be effectively codegen'd.
335 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
336 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
337 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
338 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
339 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
340 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
341
Duncan Sands83ec4b62008-06-06 12:08:01 +0000342 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
343 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
344 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000345
Duncan Sands83ec4b62008-06-06 12:08:01 +0000346 // add/sub are legal for all supported vector VT's.
347 setOperationAction(ISD::ADD , VT, Legal);
348 setOperationAction(ISD::SUB , VT, Legal);
349 // mul has to be custom lowered.
350 setOperationAction(ISD::MUL , VT, Custom);
351
352 setOperationAction(ISD::AND , VT, Legal);
353 setOperationAction(ISD::OR , VT, Legal);
354 setOperationAction(ISD::XOR , VT, Legal);
355 setOperationAction(ISD::LOAD , VT, Legal);
356 setOperationAction(ISD::SELECT, VT, Legal);
357 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000358
Scott Michel266bc8f2007-12-04 22:23:35 +0000359 // These operations need to be expanded:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000360 setOperationAction(ISD::SDIV, VT, Expand);
361 setOperationAction(ISD::SREM, VT, Expand);
362 setOperationAction(ISD::UDIV, VT, Expand);
363 setOperationAction(ISD::UREM, VT, Expand);
364 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000365
366 // Custom lower build_vector, constant pool spills, insert and
367 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000368 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
369 setOperationAction(ISD::ConstantPool, VT, Custom);
370 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
371 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
372 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
373 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000374 }
375
376 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
377 setOperationAction(ISD::AND, MVT::v16i8, Custom);
378 setOperationAction(ISD::OR, MVT::v16i8, Custom);
379 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
380 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000381
Scott Michel266bc8f2007-12-04 22:23:35 +0000382 setShiftAmountType(MVT::i32);
383 setSetCCResultContents(ZeroOrOneSetCCResult);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000384
Scott Michel266bc8f2007-12-04 22:23:35 +0000385 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000386
Scott Michel266bc8f2007-12-04 22:23:35 +0000387 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000388 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000389 setTargetDAGCombine(ISD::ZERO_EXTEND);
390 setTargetDAGCombine(ISD::SIGN_EXTEND);
391 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000392
Scott Michel266bc8f2007-12-04 22:23:35 +0000393 computeRegisterProperties();
394}
395
396const char *
397SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
398{
399 if (node_names.empty()) {
400 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
401 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
402 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
403 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000404 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000405 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000406 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
407 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
408 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
409 node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
410 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
411 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
412 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
413 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED] = "SPUISD::EXTRACT_ELT0_CHAINED";
414 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
415 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
416 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
417 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
418 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
419 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
420 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
421 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michela59d4692008-02-23 18:41:37 +0000422 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
423 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000424 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
425 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
426 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
427 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
428 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michela59d4692008-02-23 18:41:37 +0000429 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
430 "SPUISD::ROTQUAD_RZ_BYTES";
431 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
432 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel266bc8f2007-12-04 22:23:35 +0000433 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
434 "SPUISD::ROTBYTES_RIGHT_S";
435 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
436 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
437 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel8bf61e82008-06-02 22:18:03 +0000438 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
439 "SPUISD::ROTBYTES_LEFT_BITS";
440 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000441 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000442 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
443 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
444 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
445 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000446 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
447 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
448 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
449 }
450
451 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
452
453 return ((i != node_names.end()) ? i->second : 0);
454}
455
Duncan Sands83ec4b62008-06-06 12:08:01 +0000456MVT SPUTargetLowering::getSetCCResultType(const SDOperand &Op) const {
457 MVT VT = Op.getValueType();
458 if (VT.isInteger())
Scott Michel405fba12008-03-10 23:49:09 +0000459 return VT;
460 else
461 return MVT::i32;
Scott Michel78c47fa2008-03-10 16:58:52 +0000462}
463
Scott Michel266bc8f2007-12-04 22:23:35 +0000464//===----------------------------------------------------------------------===//
465// Calling convention code:
466//===----------------------------------------------------------------------===//
467
468#include "SPUGenCallingConv.inc"
469
470//===----------------------------------------------------------------------===//
471// LowerOperation implementation
472//===----------------------------------------------------------------------===//
473
Scott Michel9de5d0d2008-01-11 02:53:15 +0000474/// Aligned load common code for CellSPU
475/*!
476 \param[in] Op The SelectionDAG load or store operand
477 \param[in] DAG The selection DAG
478 \param[in] ST CellSPU subtarget information structure
479 \param[in,out] alignment Caller initializes this to the load or store node's
480 value from getAlignment(), may be updated while generating the aligned load
481 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
482 offset (divisible by 16, modulo 16 == 0)
483 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
484 offset of the preferred slot (modulo 16 != 0)
485 \param[in,out] VT Caller initializes this value type to the the load or store
486 node's loaded or stored value type; may be updated if an i1-extended load or
487 store.
488 \param[out] was16aligned true if the base pointer had 16-byte alignment,
489 otherwise false. Can help to determine if the chunk needs to be rotated.
490
491 Both load and store lowering load a block of data aligned on a 16-byte
492 boundary. This is the common aligned load code shared between both.
493 */
494static SDOperand
495AlignedLoad(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST,
496 LSBaseSDNode *LSN,
497 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000498 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000499{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000500 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000501 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
502 SDOperand basePtr = LSN->getBasePtr();
503 SDOperand chain = LSN->getChain();
504
505 if (basePtr.getOpcode() == ISD::ADD) {
506 SDOperand Op1 = basePtr.Val->getOperand(1);
507
508 if (Op1.getOpcode() == ISD::Constant || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000509 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000510
511 alignOffs = (int) CN->getValue();
512 prefSlotOffs = (int) (alignOffs & 0xf);
513
514 // Adjust the rotation amount to ensure that the final result ends up in
515 // the preferred slot:
516 prefSlotOffs -= vtm->prefslot_byte;
517 basePtr = basePtr.getOperand(0);
518
Scott Michel58c58182008-01-17 20:38:41 +0000519 // Loading from memory, can we adjust alignment?
520 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
521 SDOperand APtr = basePtr.getOperand(0);
522 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
523 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
524 alignment = GSDN->getGlobal()->getAlignment();
525 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000526 }
527 } else {
528 alignOffs = 0;
529 prefSlotOffs = -vtm->prefslot_byte;
530 }
Scott Michel203b2d62008-04-30 00:30:08 +0000531 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
532 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
533 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
534 prefSlotOffs = (int) (alignOffs & 0xf);
535 prefSlotOffs -= vtm->prefslot_byte;
536 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000537 } else {
538 alignOffs = 0;
539 prefSlotOffs = -vtm->prefslot_byte;
540 }
541
542 if (alignment == 16) {
543 // Realign the base pointer as a D-Form address:
544 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000545 basePtr = DAG.getNode(ISD::ADD, PtrVT,
546 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000547 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000548 }
549
550 // Emit the vector load:
551 was16aligned = true;
552 return DAG.getLoad(MVT::v16i8, chain, basePtr,
553 LSN->getSrcValue(), LSN->getSrcValueOffset(),
554 LSN->isVolatile(), 16);
555 }
556
557 // Unaligned load or we're using the "large memory" model, which means that
558 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000559 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Scott Michel053c1da2008-01-29 02:16:57 +0000560 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr, DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000561 }
562
563 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000564 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000565 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000566 was16aligned = false;
567 return DAG.getLoad(MVT::v16i8, chain, basePtr,
568 LSN->getSrcValue(), LSN->getSrcValueOffset(),
569 LSN->isVolatile(), 16);
570}
571
Scott Michel266bc8f2007-12-04 22:23:35 +0000572/// Custom lower loads for CellSPU
573/*!
574 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
575 within a 16-byte block, we have to rotate to extract the requested element.
576 */
577static SDOperand
578LowerLOAD(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
579 LoadSDNode *LN = cast<LoadSDNode>(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +0000580 SDOperand the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000581 MVT VT = LN->getMemoryVT();
582 MVT OpVT = Op.Val->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000583 ISD::LoadExtType ExtType = LN->getExtensionType();
584 unsigned alignment = LN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000585 SDOperand Ops[8];
586
Scott Michel266bc8f2007-12-04 22:23:35 +0000587 switch (LN->getAddressingMode()) {
588 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000589 int offset, rotamt;
590 bool was16aligned;
591 SDOperand result =
592 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000593
Scott Michel9de5d0d2008-01-11 02:53:15 +0000594 if (result.Val == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000595 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000596
597 the_chain = result.getValue(1);
598 // Rotate the chunk if necessary
599 if (rotamt < 0)
600 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000601 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000602 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
603
Scott Michel58c58182008-01-17 20:38:41 +0000604 Ops[0] = the_chain;
605 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000606 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000607 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
608 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000609 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000610 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000611 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000612 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000613 }
614
615 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
616 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000617 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000618
619 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
620 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000621 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000622
Scott Michel9de5d0d2008-01-11 02:53:15 +0000623 // Convert the loaded v16i8 vector to the appropriate vector type
624 // specified by the operand:
625 if (OpVT == VT) {
626 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000627 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000628 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000629 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000630
631 Ops[0] = the_chain;
632 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
633 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
634 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
635 the_chain = result.getValue(1);
636 } else {
637 // Handle the sign and zero-extending loads for i1 and i8:
638 unsigned NewOpC;
639
640 if (ExtType == ISD::SEXTLOAD) {
641 NewOpC = (OpVT == MVT::i1
642 ? SPUISD::EXTRACT_I1_SEXT
643 : SPUISD::EXTRACT_I8_SEXT);
644 } else {
645 assert(ExtType == ISD::ZEXTLOAD);
646 NewOpC = (OpVT == MVT::i1
647 ? SPUISD::EXTRACT_I1_ZEXT
648 : SPUISD::EXTRACT_I8_ZEXT);
649 }
650
651 result = DAG.getNode(NewOpC, OpVT, result);
652 }
653
654 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000655 SDOperand retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000656 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000657 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000658 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000659
Scott Michel58c58182008-01-17 20:38:41 +0000660 result = DAG.getNode(SPUISD::LDRESULT, retvts,
661 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000662 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000663 }
664 case ISD::PRE_INC:
665 case ISD::PRE_DEC:
666 case ISD::POST_INC:
667 case ISD::POST_DEC:
668 case ISD::LAST_INDEXED_MODE:
669 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
670 "UNINDEXED\n";
671 cerr << (unsigned) LN->getAddressingMode() << "\n";
672 abort();
673 /*NOTREACHED*/
674 }
675
676 return SDOperand();
677}
678
679/// Custom lower stores for CellSPU
680/*!
681 All CellSPU stores are aligned to 16-byte boundaries, so for elements
682 within a 16-byte block, we have to generate a shuffle to insert the
683 requested element into its place, then store the resulting block.
684 */
685static SDOperand
686LowerSTORE(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
687 StoreSDNode *SN = cast<StoreSDNode>(Op);
688 SDOperand Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000689 MVT VT = Value.getValueType();
690 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
691 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000692 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000693
694 switch (SN->getAddressingMode()) {
695 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000696 int chunk_offset, slot_offset;
697 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000698
699 // The vector type we really want to load from the 16-byte chunk, except
700 // in the case of MVT::i1, which has to be v16i8.
Duncan Sands83ec4b62008-06-06 12:08:01 +0000701 MVT vecVT, stVecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000702
Scott Michel266bc8f2007-12-04 22:23:35 +0000703 if (StVT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000704 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
705 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000706
Scott Michel9de5d0d2008-01-11 02:53:15 +0000707 SDOperand alignLoadVec =
708 AlignedLoad(Op, DAG, ST, SN, alignment,
709 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000710
Scott Michel9de5d0d2008-01-11 02:53:15 +0000711 if (alignLoadVec.Val == 0)
712 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000713
Scott Michel9de5d0d2008-01-11 02:53:15 +0000714 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
715 SDOperand basePtr = LN->getBasePtr();
716 SDOperand the_chain = alignLoadVec.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000717 SDOperand theValue = SN->getValue();
718 SDOperand result;
719
720 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000721 && (theValue.getOpcode() == ISD::AssertZext
722 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000723 // Drill down and get the value for zero- and sign-extended
724 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000725 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000726 }
727
Scott Michel9de5d0d2008-01-11 02:53:15 +0000728 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000729
Scott Michel9de5d0d2008-01-11 02:53:15 +0000730 SDOperand insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
731 SDOperand insertEltPtr;
732 SDOperand insertEltOp;
733
734 // If the base pointer is already a D-form address, then just create
735 // a new D-form address with a slot offset and the orignal base pointer.
736 // Otherwise generate a D-form address with the slot offset relative
737 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000738 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
739 DEBUG(basePtr.Val->dump(&DAG));
740 DEBUG(cerr << "\n");
741
Scott Michel053c1da2008-01-29 02:16:57 +0000742 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
743 (basePtr.getOpcode() == ISD::ADD
744 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000745 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000746 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000747 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000748 }
749
750 insertEltOp = DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000751 result = DAG.getNode(SPUISD::SHUFB, vecVT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000752 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue),
753 alignLoadVec,
754 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000755
Scott Michel9de5d0d2008-01-11 02:53:15 +0000756 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000757 LN->getSrcValue(), LN->getSrcValueOffset(),
758 LN->isVolatile(), LN->getAlignment());
759
760 return result;
761 /*UNREACHED*/
762 }
763 case ISD::PRE_INC:
764 case ISD::PRE_DEC:
765 case ISD::POST_INC:
766 case ISD::POST_DEC:
767 case ISD::LAST_INDEXED_MODE:
768 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
769 "UNINDEXED\n";
770 cerr << (unsigned) SN->getAddressingMode() << "\n";
771 abort();
772 /*NOTREACHED*/
773 }
774
775 return SDOperand();
776}
777
778/// Generate the address of a constant pool entry.
779static SDOperand
780LowerConstantPool(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000781 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000782 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
783 Constant *C = CP->getConstVal();
784 SDOperand CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
Scott Michel266bc8f2007-12-04 22:23:35 +0000785 SDOperand Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000786 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000787
788 if (TM.getRelocationModel() == Reloc::Static) {
789 if (!ST->usingLargeMem()) {
790 // Just return the SDOperand with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000791 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000792 } else {
Scott Michel266bc8f2007-12-04 22:23:35 +0000793 SDOperand Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
794 SDOperand Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000795 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000796 }
797 }
798
799 assert(0 &&
800 "LowerConstantPool: Relocation model other than static not supported.");
801 return SDOperand();
802}
803
804static SDOperand
805LowerJumpTable(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000806 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000807 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
808 SDOperand JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
809 SDOperand Zero = DAG.getConstant(0, PtrVT);
810 const TargetMachine &TM = DAG.getTarget();
811
812 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000813 if (!ST->usingLargeMem()) {
814 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
815 } else {
816 SDOperand Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
817 SDOperand Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
818 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
819 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000820 }
821
822 assert(0 &&
823 "LowerJumpTable: Relocation model other than static not supported.");
824 return SDOperand();
825}
826
827static SDOperand
828LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000829 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000830 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
831 GlobalValue *GV = GSDN->getGlobal();
832 SDOperand GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000833 const TargetMachine &TM = DAG.getTarget();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000834 SDOperand Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000835
Scott Michel266bc8f2007-12-04 22:23:35 +0000836 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000837 if (!ST->usingLargeMem()) {
838 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
839 } else {
840 SDOperand Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
841 SDOperand Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
842 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
843 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000844 } else {
845 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000846 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000847 abort();
848 /*NOTREACHED*/
849 }
850
851 return SDOperand();
852}
853
854//! Custom lower i64 integer constants
855/*!
856 This code inserts all of the necessary juggling that needs to occur to load
857 a 64-bit constant into a register.
858 */
859static SDOperand
860LowerConstant(SDOperand Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000861 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000862 ConstantSDNode *CN = cast<ConstantSDNode>(Op.Val);
863
864 if (VT == MVT::i64) {
865 SDOperand T = DAG.getConstant(CN->getValue(), MVT::i64);
866 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000867 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000868 } else {
869 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000870 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000871 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000872 abort();
873 /*NOTREACHED*/
874 }
875
876 return SDOperand();
877}
878
Nate Begemanccef5802008-02-14 18:43:04 +0000879//! Custom lower double precision floating point constants
Scott Michel266bc8f2007-12-04 22:23:35 +0000880static SDOperand
881LowerConstantFP(SDOperand Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000882 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000883 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.Val);
884
885 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000886 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000887
Nate Begemanccef5802008-02-14 18:43:04 +0000888 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000889 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000890 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000891 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000892 }
893
894 return SDOperand();
895}
896
Scott Michel58c58182008-01-17 20:38:41 +0000897//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
898static SDOperand
899LowerBRCOND(SDOperand Op, SelectionDAG &DAG)
900{
901 SDOperand Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000902 MVT CondVT = Cond.getValueType();
903 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000904
905 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
906 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
907 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
908 Op.getOperand(0),
909 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
910 Op.getOperand(2));
911 } else
912 return SDOperand(); // Unchanged
913}
914
Scott Michel266bc8f2007-12-04 22:23:35 +0000915static SDOperand
916LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
917{
918 MachineFunction &MF = DAG.getMachineFunction();
919 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000920 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +0000921 SmallVector<SDOperand, 8> ArgValues;
922 SDOperand Root = Op.getOperand(0);
923 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
924
925 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
926 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000927
Scott Michel266bc8f2007-12-04 22:23:35 +0000928 unsigned ArgOffset = SPUFrameInfo::minStackSize();
929 unsigned ArgRegIdx = 0;
930 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000931
Duncan Sands83ec4b62008-06-06 12:08:01 +0000932 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000933
Scott Michel266bc8f2007-12-04 22:23:35 +0000934 // Add DAG nodes to load the arguments or copy them out of registers.
935 for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
936 SDOperand ArgVal;
937 bool needsLoad = false;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000938 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
939 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michel266bc8f2007-12-04 22:23:35 +0000940
Duncan Sands83ec4b62008-06-06 12:08:01 +0000941 switch (ObjectVT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000942 default: {
943 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000944 << ObjectVT.getMVTString()
Scott Michel266bc8f2007-12-04 22:23:35 +0000945 << "\n";
946 abort();
947 }
948 case MVT::i8:
949 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000950 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R8CRegClass);
951 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000952 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i8);
953 ++ArgRegIdx;
954 } else {
955 needsLoad = true;
956 }
957 break;
958 case MVT::i16:
959 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000960 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
961 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000962 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i16);
963 ++ArgRegIdx;
964 } else {
965 needsLoad = true;
966 }
967 break;
968 case MVT::i32:
969 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000970 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
971 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000972 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
973 ++ArgRegIdx;
974 } else {
975 needsLoad = true;
976 }
977 break;
978 case MVT::i64:
979 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000980 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64CRegClass);
981 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000982 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64);
983 ++ArgRegIdx;
984 } else {
985 needsLoad = true;
986 }
987 break;
988 case MVT::f32:
989 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000990 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
991 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000992 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f32);
993 ++ArgRegIdx;
994 } else {
995 needsLoad = true;
996 }
997 break;
998 case MVT::f64:
999 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001000 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64FPRegClass);
1001 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001002 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f64);
1003 ++ArgRegIdx;
1004 } else {
1005 needsLoad = true;
1006 }
1007 break;
1008 case MVT::v2f64:
1009 case MVT::v4f32:
Scott Michelad2715e2008-03-05 23:02:02 +00001010 case MVT::v2i64:
Scott Michel266bc8f2007-12-04 22:23:35 +00001011 case MVT::v4i32:
1012 case MVT::v8i16:
1013 case MVT::v16i8:
1014 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001015 unsigned VReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1016 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001017 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1018 ++ArgRegIdx;
1019 } else {
1020 needsLoad = true;
1021 }
1022 break;
1023 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001024
Scott Michel266bc8f2007-12-04 22:23:35 +00001025 // We need to load the argument to a virtual register if we determined above
1026 // that we ran out of physical registers of the appropriate type
1027 if (needsLoad) {
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001028 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
1029 SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
1030 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001031 ArgOffset += StackSlotSize;
1032 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001033
Scott Michel266bc8f2007-12-04 22:23:35 +00001034 ArgValues.push_back(ArgVal);
1035 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001036
Scott Michel266bc8f2007-12-04 22:23:35 +00001037 // If the function takes variable number of arguments, make a frame index for
1038 // the start of the first vararg value... for expansion of llvm.va_start.
1039 if (isVarArg) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001040 VarArgsFrameIndex = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8,
Scott Michel266bc8f2007-12-04 22:23:35 +00001041 ArgOffset);
1042 SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1043 // If this function is vararg, store any remaining integer argument regs to
1044 // their spots on the stack so that they may be loaded by deferencing the
1045 // result of va_next.
1046 SmallVector<SDOperand, 8> MemOps;
1047 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001048 unsigned VReg = RegInfo.createVirtualRegister(&SPU::GPRCRegClass);
1049 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001050 SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
1051 SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
1052 MemOps.push_back(Store);
1053 // Increment the address by four for the next argument to store
Duncan Sands83ec4b62008-06-06 12:08:01 +00001054 SDOperand PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001055 FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
1056 }
1057 if (!MemOps.empty())
1058 Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
1059 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001060
Scott Michel266bc8f2007-12-04 22:23:35 +00001061 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001062
Scott Michel266bc8f2007-12-04 22:23:35 +00001063 // Return the new list of results.
Duncan Sandsf9516202008-06-30 10:19:09 +00001064 return DAG.getMergeValues(Op.Val->getVTList(), &ArgValues[0],
1065 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001066}
1067
1068/// isLSAAddress - Return the immediate to use if the specified
1069/// value is representable as a LSA address.
1070static SDNode *isLSAAddress(SDOperand Op, SelectionDAG &DAG) {
1071 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
1072 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001073
Scott Michel266bc8f2007-12-04 22:23:35 +00001074 int Addr = C->getValue();
1075 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1076 (Addr << 14 >> 14) != Addr)
1077 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001078
Scott Michel266bc8f2007-12-04 22:23:35 +00001079 return DAG.getConstant((int)C->getValue() >> 2, MVT::i32).Val;
1080}
1081
1082static
1083SDOperand
Scott Michel9de5d0d2008-01-11 02:53:15 +00001084LowerCALL(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001085 SDOperand Chain = Op.getOperand(0);
1086#if 0
1087 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
1088 bool isTailCall = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
1089#endif
1090 SDOperand Callee = Op.getOperand(4);
1091 unsigned NumOps = (Op.getNumOperands() - 5) / 2;
1092 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1093 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1094 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1095
1096 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001097 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001098
Scott Michel266bc8f2007-12-04 22:23:35 +00001099 // Accumulate how many bytes are to be pushed on the stack, including the
1100 // linkage area, and parameter passing area. According to the SPU ABI,
1101 // we minimally need space for [LR] and [SP]
1102 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001103
Scott Michel266bc8f2007-12-04 22:23:35 +00001104 // Set up a copy of the stack pointer for use loading and storing any
1105 // arguments that may not fit in the registers available for argument
1106 // passing.
1107 SDOperand StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001108
Scott Michel266bc8f2007-12-04 22:23:35 +00001109 // Figure out which arguments are going to go in registers, and which in
1110 // memory.
1111 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1112 unsigned ArgRegIdx = 0;
1113
1114 // Keep track of registers passing arguments
1115 std::vector<std::pair<unsigned, SDOperand> > RegsToPass;
1116 // And the arguments passed on the stack
1117 SmallVector<SDOperand, 8> MemOpChains;
1118
1119 for (unsigned i = 0; i != NumOps; ++i) {
1120 SDOperand Arg = Op.getOperand(5+2*i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001121
Scott Michel266bc8f2007-12-04 22:23:35 +00001122 // PtrOff will be used to store the current argument to the stack if a
1123 // register cannot be found for it.
1124 SDOperand PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
1125 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1126
Duncan Sands83ec4b62008-06-06 12:08:01 +00001127 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001128 default: assert(0 && "Unexpected ValueType for argument!");
1129 case MVT::i32:
1130 case MVT::i64:
1131 case MVT::i128:
1132 if (ArgRegIdx != NumArgRegs) {
1133 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1134 } else {
1135 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001136 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001137 }
1138 break;
1139 case MVT::f32:
1140 case MVT::f64:
1141 if (ArgRegIdx != NumArgRegs) {
1142 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1143 } else {
1144 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001145 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001146 }
1147 break;
1148 case MVT::v4f32:
1149 case MVT::v4i32:
1150 case MVT::v8i16:
1151 case MVT::v16i8:
1152 if (ArgRegIdx != NumArgRegs) {
1153 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1154 } else {
1155 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001156 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001157 }
1158 break;
1159 }
1160 }
1161
1162 // Update number of stack bytes actually used, insert a call sequence start
1163 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
1164 Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumStackBytes, PtrVT));
1165
1166 if (!MemOpChains.empty()) {
1167 // Adjust the stack pointer for the stack arguments.
1168 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1169 &MemOpChains[0], MemOpChains.size());
1170 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001171
Scott Michel266bc8f2007-12-04 22:23:35 +00001172 // Build a sequence of copy-to-reg nodes chained together with token chain
1173 // and flag operands which copy the outgoing args into the appropriate regs.
1174 SDOperand InFlag;
1175 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1176 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1177 InFlag);
1178 InFlag = Chain.getValue(1);
1179 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001180
Scott Michel266bc8f2007-12-04 22:23:35 +00001181 SmallVector<SDOperand, 8> Ops;
1182 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001183
Scott Michel266bc8f2007-12-04 22:23:35 +00001184 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1185 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1186 // node so that legalize doesn't hack it.
1187 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1188 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001189 MVT CalleeVT = Callee.getValueType();
Scott Michel9de5d0d2008-01-11 02:53:15 +00001190 SDOperand Zero = DAG.getConstant(0, PtrVT);
1191 SDOperand GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001192
Scott Michel9de5d0d2008-01-11 02:53:15 +00001193 if (!ST->usingLargeMem()) {
1194 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1195 // style calls, otherwise, external symbols are BRASL calls. This assumes
1196 // that declared/defined symbols are in the same compilation unit and can
1197 // be reached through PC-relative jumps.
1198 //
1199 // NOTE:
1200 // This may be an unsafe assumption for JIT and really large compilation
1201 // units.
1202 if (GV->isDeclaration()) {
1203 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1204 } else {
1205 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1206 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001207 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001208 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1209 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001210 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001211 }
1212 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
1213 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001214 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001215 // If this is an absolute destination address that appears to be a legal
1216 // local store address, use the munged value.
1217 Callee = SDOperand(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001218 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001219
1220 Ops.push_back(Chain);
1221 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001222
Scott Michel266bc8f2007-12-04 22:23:35 +00001223 // Add argument registers to the end of the list so that they are known live
1224 // into the call.
1225 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001226 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001227 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001228
Scott Michel266bc8f2007-12-04 22:23:35 +00001229 if (InFlag.Val)
1230 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001231 // Returns a chain and a flag for retval copy to use.
1232 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1233 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001234 InFlag = Chain.getValue(1);
1235
Evan Chengebaaa912008-02-05 22:44:06 +00001236 Chain = DAG.getCALLSEQ_END(Chain,
1237 DAG.getConstant(NumStackBytes, PtrVT),
1238 DAG.getConstant(0, PtrVT),
1239 InFlag);
1240 if (Op.Val->getValueType(0) != MVT::Other)
1241 InFlag = Chain.getValue(1);
1242
Scott Michel266bc8f2007-12-04 22:23:35 +00001243 SDOperand ResultVals[3];
1244 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001245
Scott Michel266bc8f2007-12-04 22:23:35 +00001246 // If the call has results, copy the values out of the ret val registers.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001247 switch (Op.Val->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001248 default: assert(0 && "Unexpected ret value!");
1249 case MVT::Other: break;
1250 case MVT::i32:
1251 if (Op.Val->getValueType(1) == MVT::i32) {
1252 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1253 ResultVals[0] = Chain.getValue(0);
1254 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1255 Chain.getValue(2)).getValue(1);
1256 ResultVals[1] = Chain.getValue(0);
1257 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001258 } else {
1259 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1260 ResultVals[0] = Chain.getValue(0);
1261 NumResults = 1;
1262 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001263 break;
1264 case MVT::i64:
1265 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1266 ResultVals[0] = Chain.getValue(0);
1267 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001268 break;
1269 case MVT::f32:
1270 case MVT::f64:
1271 Chain = DAG.getCopyFromReg(Chain, SPU::R3, Op.Val->getValueType(0),
1272 InFlag).getValue(1);
1273 ResultVals[0] = Chain.getValue(0);
1274 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001275 break;
1276 case MVT::v2f64:
1277 case MVT::v4f32:
1278 case MVT::v4i32:
1279 case MVT::v8i16:
1280 case MVT::v16i8:
1281 Chain = DAG.getCopyFromReg(Chain, SPU::R3, Op.Val->getValueType(0),
1282 InFlag).getValue(1);
1283 ResultVals[0] = Chain.getValue(0);
1284 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001285 break;
1286 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001287
Scott Michel266bc8f2007-12-04 22:23:35 +00001288 // If the function returns void, just return the chain.
1289 if (NumResults == 0)
1290 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001291
Scott Michel266bc8f2007-12-04 22:23:35 +00001292 // Otherwise, merge everything together with a MERGE_VALUES node.
1293 ResultVals[NumResults++] = Chain;
Duncan Sands4bdcb612008-07-02 17:40:58 +00001294 SDOperand Res = DAG.getMergeValues(ResultVals, NumResults);
Scott Michel266bc8f2007-12-04 22:23:35 +00001295 return Res.getValue(Op.ResNo);
1296}
1297
1298static SDOperand
1299LowerRET(SDOperand Op, SelectionDAG &DAG, TargetMachine &TM) {
1300 SmallVector<CCValAssign, 16> RVLocs;
1301 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1302 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1303 CCState CCInfo(CC, isVarArg, TM, RVLocs);
1304 CCInfo.AnalyzeReturn(Op.Val, RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001305
Scott Michel266bc8f2007-12-04 22:23:35 +00001306 // If this is the first return lowered for this function, add the regs to the
1307 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001308 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001309 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001310 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001311 }
1312
1313 SDOperand Chain = Op.getOperand(0);
1314 SDOperand Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001315
Scott Michel266bc8f2007-12-04 22:23:35 +00001316 // Copy the result values into the output registers.
1317 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1318 CCValAssign &VA = RVLocs[i];
1319 assert(VA.isRegLoc() && "Can only return in registers!");
1320 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1321 Flag = Chain.getValue(1);
1322 }
1323
1324 if (Flag.Val)
1325 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1326 else
1327 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1328}
1329
1330
1331//===----------------------------------------------------------------------===//
1332// Vector related lowering:
1333//===----------------------------------------------------------------------===//
1334
1335static ConstantSDNode *
1336getVecImm(SDNode *N) {
1337 SDOperand OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001338
Scott Michel266bc8f2007-12-04 22:23:35 +00001339 // Check to see if this buildvec has a single non-undef value in its elements.
1340 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1341 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
1342 if (OpVal.Val == 0)
1343 OpVal = N->getOperand(i);
1344 else if (OpVal != N->getOperand(i))
1345 return 0;
1346 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001347
Scott Michel266bc8f2007-12-04 22:23:35 +00001348 if (OpVal.Val != 0) {
1349 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1350 return CN;
1351 }
1352 }
1353
1354 return 0; // All UNDEF: use implicit def.; not Constant node
1355}
1356
1357/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1358/// and the value fits into an unsigned 18-bit constant, and if so, return the
1359/// constant
1360SDOperand SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001361 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001362 if (ConstantSDNode *CN = getVecImm(N)) {
1363 uint64_t Value = CN->getValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001364 if (ValueType == MVT::i64) {
1365 uint64_t UValue = CN->getValue();
1366 uint32_t upper = uint32_t(UValue >> 32);
1367 uint32_t lower = uint32_t(UValue);
1368 if (upper != lower)
1369 return SDOperand();
1370 Value = Value >> 32;
1371 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001372 if (Value <= 0x3ffff)
1373 return DAG.getConstant(Value, ValueType);
1374 }
1375
1376 return SDOperand();
1377}
1378
1379/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1380/// and the value fits into a signed 16-bit constant, and if so, return the
1381/// constant
1382SDOperand SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001383 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001384 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001385 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001386 if (ValueType == MVT::i64) {
1387 uint64_t UValue = CN->getValue();
1388 uint32_t upper = uint32_t(UValue >> 32);
1389 uint32_t lower = uint32_t(UValue);
1390 if (upper != lower)
1391 return SDOperand();
1392 Value = Value >> 32;
1393 }
Scott Michelad2715e2008-03-05 23:02:02 +00001394 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
1395 return DAG.getConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001396 }
1397 }
1398
1399 return SDOperand();
1400}
1401
1402/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1403/// and the value fits into a signed 10-bit constant, and if so, return the
1404/// constant
1405SDOperand SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001406 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001407 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001408 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001409 if (ValueType == MVT::i64) {
1410 uint64_t UValue = CN->getValue();
1411 uint32_t upper = uint32_t(UValue >> 32);
1412 uint32_t lower = uint32_t(UValue);
1413 if (upper != lower)
1414 return SDOperand();
1415 Value = Value >> 32;
1416 }
Scott Michelad2715e2008-03-05 23:02:02 +00001417 if (isS10Constant(Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001418 return DAG.getConstant(Value, ValueType);
1419 }
1420
1421 return SDOperand();
1422}
1423
1424/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1425/// and the value fits into a signed 8-bit constant, and if so, return the
1426/// constant.
1427///
1428/// @note: The incoming vector is v16i8 because that's the only way we can load
1429/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1430/// same value.
1431SDOperand SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001432 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001433 if (ConstantSDNode *CN = getVecImm(N)) {
1434 int Value = (int) CN->getValue();
1435 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001436 && Value <= 0xffff /* truncated from uint64_t */
1437 && ((short) Value >> 8) == ((short) Value & 0xff))
Scott Michel266bc8f2007-12-04 22:23:35 +00001438 return DAG.getConstant(Value & 0xff, ValueType);
1439 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001440 && (Value & 0xff) == Value)
Scott Michel266bc8f2007-12-04 22:23:35 +00001441 return DAG.getConstant(Value, ValueType);
1442 }
1443
1444 return SDOperand();
1445}
1446
1447/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1448/// and the value fits into a signed 16-bit constant, and if so, return the
1449/// constant
1450SDOperand SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001451 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001452 if (ConstantSDNode *CN = getVecImm(N)) {
1453 uint64_t Value = CN->getValue();
1454 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001455 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1456 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001457 return DAG.getConstant(Value >> 16, ValueType);
1458 }
1459
1460 return SDOperand();
1461}
1462
1463/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
1464SDOperand SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
1465 if (ConstantSDNode *CN = getVecImm(N)) {
1466 return DAG.getConstant((unsigned) CN->getValue(), MVT::i32);
1467 }
1468
1469 return SDOperand();
1470}
1471
1472/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
1473SDOperand SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
1474 if (ConstantSDNode *CN = getVecImm(N)) {
1475 return DAG.getConstant((unsigned) CN->getValue(), MVT::i64);
1476 }
1477
1478 return SDOperand();
1479}
1480
1481// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001482// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001483// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1484// zero. Return true if this is not an array of constants, false if it is.
1485//
1486static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1487 uint64_t UndefBits[2]) {
1488 // Start with zero'd results.
1489 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001490
Duncan Sands83ec4b62008-06-06 12:08:01 +00001491 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001492 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
1493 SDOperand OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001494
Scott Michel266bc8f2007-12-04 22:23:35 +00001495 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1496 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1497
1498 uint64_t EltBits = 0;
1499 if (OpVal.getOpcode() == ISD::UNDEF) {
1500 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1501 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1502 continue;
1503 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1504 EltBits = CN->getValue() & (~0ULL >> (64-EltBitSize));
1505 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
1506 const APFloat &apf = CN->getValueAPF();
1507 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001508 ? FloatToBits(apf.convertToFloat())
1509 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001510 } else {
1511 // Nonconstant element.
1512 return true;
1513 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001514
Scott Michel266bc8f2007-12-04 22:23:35 +00001515 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1516 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001517
1518 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001519 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1520 return false;
1521}
1522
1523/// If this is a splat (repetition) of a value across the whole vector, return
1524/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001525/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001526/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001527static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001528 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001529 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001530 uint64_t &SplatBits, uint64_t &SplatUndef,
1531 int &SplatSize) {
1532 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1533 // the same as the lower 64-bits, ignoring undefs.
1534 uint64_t Bits64 = Bits128[0] | Bits128[1];
1535 uint64_t Undef64 = Undef128[0] & Undef128[1];
1536 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1537 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1538 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1539 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1540
1541 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1542 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001543
Scott Michel266bc8f2007-12-04 22:23:35 +00001544 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1545 // undefs.
1546 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001547 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001548
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001549 // If the top 16-bits are different than the lower 16-bits, ignoring
1550 // undefs, we have an i32 splat.
1551 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1552 if (MinSplatBits < 16) {
1553 // If the top 8-bits are different than the lower 8-bits, ignoring
1554 // undefs, we have an i16 splat.
1555 if ((Bits16 & (uint16_t(~Undef16) >> 8)) == ((Bits16 >> 8) & ~Undef16)) {
1556 // Otherwise, we have an 8-bit splat.
1557 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1558 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1559 SplatSize = 1;
1560 return true;
1561 }
1562 } else {
1563 SplatBits = Bits16;
1564 SplatUndef = Undef16;
1565 SplatSize = 2;
1566 return true;
1567 }
1568 }
1569 } else {
1570 SplatBits = Bits32;
1571 SplatUndef = Undef32;
1572 SplatSize = 4;
1573 return true;
1574 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001575 }
1576 } else {
1577 SplatBits = Bits128[0];
1578 SplatUndef = Undef128[0];
1579 SplatSize = 8;
1580 return true;
1581 }
1582 }
1583
1584 return false; // Can't be a splat if two pieces don't match.
1585}
1586
1587// If this is a case we can't handle, return null and let the default
1588// expansion code take care of it. If we CAN select this case, and if it
1589// selects to a single instruction, return Op. Otherwise, if we can codegen
1590// this case more efficiently than a constant pool load, lower it to the
1591// sequence of ops that should be used.
1592static SDOperand LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001593 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001594 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001595 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001596 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001597 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001598 uint64_t VectorBits[2];
1599 uint64_t UndefBits[2];
1600 uint64_t SplatBits, SplatUndef;
1601 int SplatSize;
1602 if (GetConstantBuildVectorBits(Op.Val, VectorBits, UndefBits)
1603 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001604 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001605 SplatBits, SplatUndef, SplatSize))
1606 return SDOperand(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001607
Duncan Sands83ec4b62008-06-06 12:08:01 +00001608 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001609 default:
1610 case MVT::v4f32: {
1611 uint32_t Value32 = SplatBits;
1612 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001613 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001614 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
1615 SDOperand T = DAG.getConstant(Value32, MVT::i32);
1616 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001617 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001618 break;
1619 }
1620 case MVT::v2f64: {
1621 uint64_t f64val = SplatBits;
1622 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001623 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001624 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
1625 SDOperand T = DAG.getConstant(f64val, MVT::i64);
1626 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001627 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001628 break;
1629 }
1630 case MVT::v16i8: {
1631 // 8-bit constants have to be expanded to 16-bits
1632 unsigned short Value16 = SplatBits | (SplatBits << 8);
1633 SDOperand Ops[8];
1634 for (int i = 0; i < 8; ++i)
1635 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1636 return DAG.getNode(ISD::BIT_CONVERT, VT,
1637 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1638 }
1639 case MVT::v8i16: {
1640 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001641 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001642 Value16 = (unsigned short) (SplatBits & 0xffff);
1643 else
1644 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Duncan Sands83ec4b62008-06-06 12:08:01 +00001645 SDOperand T = DAG.getConstant(Value16, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001646 SDOperand Ops[8];
1647 for (int i = 0; i < 8; ++i) Ops[i] = T;
1648 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1649 }
1650 case MVT::v4i32: {
1651 unsigned int Value = SplatBits;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001652 SDOperand T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001653 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1654 }
1655 case MVT::v2i64: {
1656 uint64_t val = SplatBits;
1657 uint32_t upper = uint32_t(val >> 32);
1658 uint32_t lower = uint32_t(val);
1659
Scott Michel4cb8bd82008-03-06 04:02:54 +00001660 if (upper == lower) {
1661 // Magic constant that can be matched by IL, ILA, et. al.
1662 SDOperand Val = DAG.getTargetConstant(val, MVT::i64);
1663 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001664 } else {
Scott Michel266bc8f2007-12-04 22:23:35 +00001665 SDOperand LO32;
1666 SDOperand HI32;
1667 SmallVector<SDOperand, 16> ShufBytes;
1668 SDOperand Result;
1669 bool upper_special, lower_special;
1670
1671 // NOTE: This code creates common-case shuffle masks that can be easily
1672 // detected as common expressions. It is not attempting to create highly
1673 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1674
1675 // Detect if the upper or lower half is a special shuffle mask pattern:
1676 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1677 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1678
1679 // Create lower vector if not a special pattern
1680 if (!lower_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001681 SDOperand LO32C = DAG.getConstant(lower, MVT::i32);
1682 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1683 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1684 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001685 }
1686
1687 // Create upper vector if not a special pattern
1688 if (!upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001689 SDOperand HI32C = DAG.getConstant(upper, MVT::i32);
1690 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1691 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1692 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001693 }
1694
1695 // If either upper or lower are special, then the two input operands are
1696 // the same (basically, one of them is a "don't care")
1697 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001698 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001699 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001700 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001701 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001702 // Unhappy situation... both upper and lower are special, so punt with
1703 // a target constant:
Scott Michel266bc8f2007-12-04 22:23:35 +00001704 SDOperand Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001705 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001706 Zero, Zero);
1707 }
1708
1709 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001710 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001711 for (int j = 0; j < 4; ++j) {
1712 SDOperand V;
1713 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001714 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001715 process_upper = (upper_special && (i & 1) == 0);
1716 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001717
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001718 if (process_upper || process_lower) {
1719 if ((process_upper && upper == 0)
1720 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001721 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001722 else if ((process_upper && upper == 0xffffffff)
1723 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001724 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001725 else if ((process_upper && upper == 0x80000000)
1726 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001727 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001728 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001729 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001730 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001731
1732 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001733 }
1734
1735 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001736 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001737 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001738 }
1739 }
1740 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001741
Scott Michel266bc8f2007-12-04 22:23:35 +00001742 return SDOperand();
1743}
1744
1745/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1746/// which the Cell can operate. The code inspects V3 to ascertain whether the
1747/// permutation vector, V3, is monotonically increasing with one "exception"
1748/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1749/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1750/// In either case, the net result is going to eventually invoke SHUFB to
1751/// permute/shuffle the bytes from V1 and V2.
1752/// \note
1753/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1754/// control word for byte/halfword/word insertion. This takes care of a single
1755/// element move from V2 into V1.
1756/// \note
1757/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
1758static SDOperand LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG) {
1759 SDOperand V1 = Op.getOperand(0);
1760 SDOperand V2 = Op.getOperand(1);
1761 SDOperand PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001762
Scott Michel266bc8f2007-12-04 22:23:35 +00001763 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001764
Scott Michel266bc8f2007-12-04 22:23:35 +00001765 // If we have a single element being moved from V1 to V2, this can be handled
1766 // using the C*[DX] compute mask instructions, but the vector elements have
1767 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001768 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001769 unsigned EltsFromV2 = 0;
1770 unsigned V2Elt = 0;
1771 unsigned V2EltIdx0 = 0;
1772 unsigned CurrElt = 0;
1773 bool monotonic = true;
1774 if (EltVT == MVT::i8)
1775 V2EltIdx0 = 16;
1776 else if (EltVT == MVT::i16)
1777 V2EltIdx0 = 8;
1778 else if (EltVT == MVT::i32)
1779 V2EltIdx0 = 4;
1780 else
1781 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1782
1783 for (unsigned i = 0, e = PermMask.getNumOperands();
1784 EltsFromV2 <= 1 && monotonic && i != e;
1785 ++i) {
1786 unsigned SrcElt;
1787 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1788 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001789 else
Scott Michel266bc8f2007-12-04 22:23:35 +00001790 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getValue();
1791
1792 if (SrcElt >= V2EltIdx0) {
1793 ++EltsFromV2;
1794 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1795 } else if (CurrElt != SrcElt) {
1796 monotonic = false;
1797 }
1798
1799 ++CurrElt;
1800 }
1801
1802 if (EltsFromV2 == 1 && monotonic) {
1803 // Compute mask and shuffle
1804 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001805 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1806 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001807 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001808 // Initialize temporary register to 0
1809 SDOperand InitTempReg =
1810 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1811 // Copy register's contents as index in INSERT_MASK:
1812 SDOperand ShufMaskOp =
1813 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001814 DAG.getTargetConstant(V2Elt, MVT::i32),
1815 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001816 // Use shuffle mask in SHUFB synthetic instruction:
1817 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1818 } else {
1819 // Convert the SHUFFLE_VECTOR mask's input element units to the actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001820 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001821
Scott Michel266bc8f2007-12-04 22:23:35 +00001822 SmallVector<SDOperand, 16> ResultMask;
1823 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1824 unsigned SrcElt;
1825 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001826 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001827 else
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001828 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001829
Scott Michela59d4692008-02-23 18:41:37 +00001830 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001831 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1832 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001833 }
1834 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001835
Scott Michel266bc8f2007-12-04 22:23:35 +00001836 SDOperand VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001837 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001838 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1839 }
1840}
1841
1842static SDOperand LowerSCALAR_TO_VECTOR(SDOperand Op, SelectionDAG &DAG) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001843 SDOperand Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001844
1845 if (Op0.Val->getOpcode() == ISD::Constant) {
1846 // For a constant, build the appropriate constant vector, which will
1847 // eventually simplify to a vector register load.
1848
1849 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.Val);
1850 SmallVector<SDOperand, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001851 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001852 size_t n_copies;
1853
1854 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001855 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001856 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001857 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001858 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1859 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1860 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1861 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1862 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1863 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1864 }
1865
1866 SDOperand CValue = DAG.getConstant(CN->getValue(), VT);
1867 for (size_t j = 0; j < n_copies; ++j)
1868 ConstVecValues.push_back(CValue);
1869
1870 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001871 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001872 } else {
1873 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001874 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001875 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1876 case MVT::i8:
1877 case MVT::i16:
1878 case MVT::i32:
1879 case MVT::i64:
1880 case MVT::f32:
1881 case MVT::f64:
1882 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1883 }
1884 }
1885
1886 return SDOperand();
1887}
1888
1889static SDOperand LowerVectorMUL(SDOperand Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001890 switch (Op.getValueType().getSimpleVT()) {
1891 default:
1892 cerr << "CellSPU: Unknown vector multiplication, got "
1893 << Op.getValueType().getMVTString()
1894 << "\n";
1895 abort();
1896 /*NOTREACHED*/
1897
Scott Michel266bc8f2007-12-04 22:23:35 +00001898 case MVT::v4i32: {
1899 SDOperand rA = Op.getOperand(0);
1900 SDOperand rB = Op.getOperand(1);
1901 SDOperand HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1902 SDOperand HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1903 SDOperand LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1904 SDOperand Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
1905
1906 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1907 break;
1908 }
1909
1910 // Multiply two v8i16 vectors (pipeline friendly version):
1911 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1912 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1913 // c) Use SELB to select upper and lower halves from the intermediate results
1914 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001915 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001916 // dual-issue. This code does manage to do this, even if it's a little on
1917 // the wacky side
1918 case MVT::v8i16: {
1919 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001920 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00001921 SDOperand Chain = Op.getOperand(0);
1922 SDOperand rA = Op.getOperand(0);
1923 SDOperand rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001924 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1925 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001926
1927 SDOperand FSMBOp =
1928 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001929 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001930 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001931
1932 SDOperand HHProd =
1933 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001934 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001935
1936 SDOperand HHProd_v4i32 =
1937 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001938 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001939
1940 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001941 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1942 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1943 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1944 HHProd_v4i32,
1945 DAG.getConstant(16, MVT::i16))),
1946 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001947 }
1948
1949 // This M00sE is N@stI! (apologies to Monty Python)
1950 //
1951 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1952 // is to break it all apart, sign extend, and reassemble the various
1953 // intermediate products.
1954 case MVT::v16i8: {
Scott Michel266bc8f2007-12-04 22:23:35 +00001955 SDOperand rA = Op.getOperand(0);
1956 SDOperand rB = Op.getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00001957 SDOperand c8 = DAG.getConstant(8, MVT::i32);
1958 SDOperand c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001959
1960 SDOperand LLProd =
1961 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001962 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1963 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001964
1965 SDOperand rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
1966
1967 SDOperand rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
1968
1969 SDOperand LHProd =
1970 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001971 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001972
Scott Michel8bf61e82008-06-02 22:18:03 +00001973 SDOperand FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001974 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001975
Scott Michela59d4692008-02-23 18:41:37 +00001976 SDOperand LoProdParts =
1977 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1978 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1979 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001980
1981 SDOperand LoProdMask = DAG.getConstant(0xffff, MVT::i32);
1982
Scott Michel5af8f0e2008-07-16 17:17:29 +00001983 SDOperand LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001984 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00001985 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001986 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1987 LoProdMask, LoProdMask,
1988 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001989
1990 SDOperand rAH =
1991 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001992 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001993
1994 SDOperand rBH =
1995 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001996 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001997
1998 SDOperand HLProd =
1999 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002000 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2001 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00002002
2003 SDOperand HHProd_1 =
2004 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002005 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
2006 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32, rAH, c8)),
2007 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
2008 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002009
2010 SDOperand HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00002011 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2012 HLProd,
2013 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2014 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002015
2016 SDOperand HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002017 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002018
2019 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002020 DAG.getNode(ISD::OR, MVT::v4i32,
2021 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002022 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002023 }
2024
2025 return SDOperand();
2026}
2027
2028static SDOperand LowerFDIVf32(SDOperand Op, SelectionDAG &DAG) {
2029 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002030 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002031
2032 SDOperand A = Op.getOperand(0);
2033 SDOperand B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002034 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002035
2036 unsigned VRegBR, VRegC;
2037
2038 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002039 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2040 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002041 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002042 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2043 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002044 }
2045 // TODO: make sure we're feeding FPInterp the right arguments
2046 // Right now: fi B, frest(B)
2047
2048 // Computes BRcpl =
2049 // (Floating Interpolate (FP Reciprocal Estimate B))
2050 SDOperand BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002051 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2052 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002053 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002054
Scott Michel266bc8f2007-12-04 22:23:35 +00002055 // Computes A * BRcpl and stores in a temporary register
2056 SDOperand AxBRcpl =
2057 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002058 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002059 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002060 // What's the Chain variable do? It's magic!
2061 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002062
2063 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002064 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002065 DAG.getNode(ISD::FMUL, VT,
2066 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002067 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002068 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002069 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002070}
2071
Scott Michel266bc8f2007-12-04 22:23:35 +00002072static SDOperand LowerEXTRACT_VECTOR_ELT(SDOperand Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002073 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002074 SDOperand N = Op.getOperand(0);
2075 SDOperand Elt = Op.getOperand(1);
2076 SDOperand ShufMask[16];
2077 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
2078
2079 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2080
2081 int EltNo = (int) C->getValue();
2082
2083 // sanity checks:
2084 if (VT == MVT::i8 && EltNo >= 16)
2085 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2086 else if (VT == MVT::i16 && EltNo >= 8)
2087 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2088 else if (VT == MVT::i32 && EltNo >= 4)
2089 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2090 else if (VT == MVT::i64 && EltNo >= 2)
2091 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2092
2093 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2094 // i32 and i64: Element 0 is the preferred slot
2095 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2096 }
2097
2098 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002099 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002100 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002101
Duncan Sands83ec4b62008-06-06 12:08:01 +00002102 switch (VT.getSimpleVT()) {
2103 default:
2104 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002105 case MVT::i8: {
2106 prefslot_begin = prefslot_end = 3;
2107 break;
2108 }
2109 case MVT::i16: {
2110 prefslot_begin = 2; prefslot_end = 3;
2111 break;
2112 }
2113 case MVT::i32: {
2114 prefslot_begin = 0; prefslot_end = 3;
2115 break;
2116 }
2117 case MVT::i64: {
2118 prefslot_begin = 0; prefslot_end = 7;
2119 break;
2120 }
2121 }
2122
Scott Michel0e5665b2007-12-19 21:17:42 +00002123 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002124 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002125
Scott Michel266bc8f2007-12-04 22:23:35 +00002126 for (int i = 0; i < 16; ++i) {
2127 // zero fill uppper part of preferred slot, don't care about the
2128 // other slots:
2129 unsigned int mask_val;
2130
2131 if (i <= prefslot_end) {
2132 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002133 ((i < prefslot_begin)
2134 ? 0x80
2135 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002136
Scott Michel0e5665b2007-12-19 21:17:42 +00002137 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002138 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002139 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2140 }
2141
2142 SDOperand ShufMaskVec =
2143 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002144 &ShufMask[0],
2145 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002146
2147 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002148 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2149 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002150
Scott Michel266bc8f2007-12-04 22:23:35 +00002151}
2152
2153static SDOperand LowerINSERT_VECTOR_ELT(SDOperand Op, SelectionDAG &DAG) {
2154 SDOperand VecOp = Op.getOperand(0);
2155 SDOperand ValOp = Op.getOperand(1);
2156 SDOperand IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002157 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002158
2159 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2160 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2161
Duncan Sands83ec4b62008-06-06 12:08:01 +00002162 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002163 // Use $2 because it's always 16-byte aligned and it's available:
2164 SDOperand PtrBase = DAG.getRegister(SPU::R2, PtrVT);
2165
2166 SDOperand result =
2167 DAG.getNode(SPUISD::SHUFB, VT,
2168 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2169 VecOp,
2170 DAG.getNode(SPUISD::INSERT_MASK, VT,
2171 DAG.getNode(ISD::ADD, PtrVT,
2172 PtrBase,
2173 DAG.getConstant(CN->getValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002174 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002175
2176 return result;
2177}
2178
Scott Michela59d4692008-02-23 18:41:37 +00002179static SDOperand LowerI8Math(SDOperand Op, SelectionDAG &DAG, unsigned Opc)
2180{
Scott Michel266bc8f2007-12-04 22:23:35 +00002181 SDOperand N0 = Op.getOperand(0); // Everything has at least one operand
2182
2183 assert(Op.getValueType() == MVT::i8);
2184 switch (Opc) {
2185 default:
2186 assert(0 && "Unhandled i8 math operator");
2187 /*NOTREACHED*/
2188 break;
2189 case ISD::SUB: {
2190 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2191 // the result:
2192 SDOperand N1 = Op.getOperand(1);
2193 N0 = (N0.getOpcode() != ISD::Constant
2194 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
2195 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
2196 N1 = (N1.getOpcode() != ISD::Constant
2197 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
2198 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002199 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002200 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002201 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002202 case ISD::ROTR:
2203 case ISD::ROTL: {
2204 SDOperand N1 = Op.getOperand(1);
2205 unsigned N1Opc;
2206 N0 = (N0.getOpcode() != ISD::Constant
2207 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
2208 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002209 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::ZERO_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002210 N1 = (N1.getOpcode() != ISD::Constant
2211 ? DAG.getNode(N1Opc, MVT::i16, N1)
2212 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
2213 SDOperand ExpandArg =
2214 DAG.getNode(ISD::OR, MVT::i16, N0,
2215 DAG.getNode(ISD::SHL, MVT::i16,
2216 N0, DAG.getConstant(8, MVT::i16)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002217 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002218 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2219 }
2220 case ISD::SRL:
2221 case ISD::SHL: {
2222 SDOperand N1 = Op.getOperand(1);
2223 unsigned N1Opc;
2224 N0 = (N0.getOpcode() != ISD::Constant
2225 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
2226 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002227 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::ZERO_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002228 N1 = (N1.getOpcode() != ISD::Constant
2229 ? DAG.getNode(N1Opc, MVT::i16, N1)
2230 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002231 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002232 DAG.getNode(Opc, MVT::i16, N0, N1));
2233 }
2234 case ISD::SRA: {
2235 SDOperand N1 = Op.getOperand(1);
2236 unsigned N1Opc;
2237 N0 = (N0.getOpcode() != ISD::Constant
2238 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
2239 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002240 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002241 N1 = (N1.getOpcode() != ISD::Constant
2242 ? DAG.getNode(N1Opc, MVT::i16, N1)
2243 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002244 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002245 DAG.getNode(Opc, MVT::i16, N0, N1));
2246 }
2247 case ISD::MUL: {
2248 SDOperand N1 = Op.getOperand(1);
2249 unsigned N1Opc;
2250 N0 = (N0.getOpcode() != ISD::Constant
2251 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
2252 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002253 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002254 N1 = (N1.getOpcode() != ISD::Constant
2255 ? DAG.getNode(N1Opc, MVT::i16, N1)
2256 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002257 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002258 DAG.getNode(Opc, MVT::i16, N0, N1));
2259 break;
2260 }
2261 }
2262
2263 return SDOperand();
2264}
2265
Scott Michela59d4692008-02-23 18:41:37 +00002266static SDOperand LowerI64Math(SDOperand Op, SelectionDAG &DAG, unsigned Opc)
2267{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002268 MVT VT = Op.getValueType();
2269 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002270
2271 SDOperand Op0 = Op.getOperand(0);
2272
2273 switch (Opc) {
2274 case ISD::ZERO_EXTEND:
2275 case ISD::SIGN_EXTEND:
2276 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002277 MVT Op0VT = Op0.getValueType();
2278 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002279
2280 assert(Op0VT == MVT::i32
2281 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002282 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002283
2284 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2285 ? SPUISD::ROTBYTES_RIGHT_S
2286 : SPUISD::ROTQUAD_RZ_BYTES);
2287 SDOperand PromoteScalar =
2288 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2289
2290 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2291 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2292 DAG.getNode(NewOpc, Op0VecVT,
2293 PromoteScalar,
2294 DAG.getConstant(4, MVT::i32))));
2295 }
2296
Scott Michel8bf61e82008-06-02 22:18:03 +00002297 case ISD::ADD: {
2298 // Turn operands into vectors to satisfy type checking (shufb works on
2299 // vectors)
2300 SDOperand Op0 =
2301 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
2302 SDOperand Op1 =
2303 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
2304 SmallVector<SDOperand, 16> ShufBytes;
2305
2306 // Create the shuffle mask for "rotating" the borrow up one register slot
2307 // once the borrow is generated.
2308 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2309 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2310 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2311 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2312
2313 SDOperand CarryGen =
2314 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
2315 SDOperand ShiftedCarry =
2316 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2317 CarryGen, CarryGen,
2318 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2319 &ShufBytes[0], ShufBytes.size()));
2320
2321 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2322 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2323 Op0, Op1, ShiftedCarry));
2324 }
2325
2326 case ISD::SUB: {
2327 // Turn operands into vectors to satisfy type checking (shufb works on
2328 // vectors)
2329 SDOperand Op0 =
2330 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
2331 SDOperand Op1 =
2332 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
2333 SmallVector<SDOperand, 16> ShufBytes;
2334
2335 // Create the shuffle mask for "rotating" the borrow up one register slot
2336 // once the borrow is generated.
2337 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2338 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2339 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2340 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2341
2342 SDOperand BorrowGen =
2343 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
2344 SDOperand ShiftedBorrow =
2345 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2346 BorrowGen, BorrowGen,
2347 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2348 &ShufBytes[0], ShufBytes.size()));
2349
2350 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2351 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2352 Op0, Op1, ShiftedBorrow));
2353 }
2354
Scott Michela59d4692008-02-23 18:41:37 +00002355 case ISD::SHL: {
2356 SDOperand ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002357 MVT ShiftAmtVT = ShiftAmt.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002358 SDOperand Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2359 SDOperand MaskLower =
2360 DAG.getNode(SPUISD::SELB, VecVT,
2361 Op0Vec,
2362 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002363 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002364 DAG.getConstant(0xff00ULL, MVT::i16)));
2365 SDOperand ShiftAmtBytes =
2366 DAG.getNode(ISD::SRL, ShiftAmtVT,
2367 ShiftAmt,
2368 DAG.getConstant(3, ShiftAmtVT));
2369 SDOperand ShiftAmtBits =
2370 DAG.getNode(ISD::AND, ShiftAmtVT,
2371 ShiftAmt,
2372 DAG.getConstant(7, ShiftAmtVT));
2373
2374 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2375 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2376 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2377 MaskLower, ShiftAmtBytes),
2378 ShiftAmtBits));
2379 }
2380
2381 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002382 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002383 SDOperand ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002384 MVT ShiftAmtVT = ShiftAmt.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002385 SDOperand ShiftAmtBytes =
2386 DAG.getNode(ISD::SRL, ShiftAmtVT,
2387 ShiftAmt,
2388 DAG.getConstant(3, ShiftAmtVT));
2389 SDOperand ShiftAmtBits =
2390 DAG.getNode(ISD::AND, ShiftAmtVT,
2391 ShiftAmt,
2392 DAG.getConstant(7, ShiftAmtVT));
2393
2394 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2395 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2396 Op0, ShiftAmtBytes),
2397 ShiftAmtBits);
2398 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002399
2400 case ISD::SRA: {
2401 // Promote Op0 to vector
2402 SDOperand Op0 =
2403 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
2404 SDOperand ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002405 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002406
2407 // Negate variable shift amounts
2408 if (!isa<ConstantSDNode>(ShiftAmt)) {
2409 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2410 DAG.getConstant(0, ShiftVT), ShiftAmt);
2411 }
2412
2413 SDOperand UpperHalfSign =
2414 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2415 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2416 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2417 Op0, DAG.getConstant(31, MVT::i32))));
2418 SDOperand UpperHalfSignMask =
2419 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
2420 SDOperand UpperLowerMask =
2421 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2422 DAG.getConstant(0xff00, MVT::i16));
2423 SDOperand UpperLowerSelect =
2424 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2425 UpperHalfSignMask, Op0, UpperLowerMask);
2426 SDOperand RotateLeftBytes =
2427 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2428 UpperLowerSelect, ShiftAmt);
2429 SDOperand RotateLeftBits =
2430 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2431 RotateLeftBytes, ShiftAmt);
2432
2433 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2434 RotateLeftBits);
2435 }
Scott Michela59d4692008-02-23 18:41:37 +00002436 }
2437
2438 return SDOperand();
2439}
2440
Scott Michel266bc8f2007-12-04 22:23:35 +00002441//! Lower byte immediate operations for v16i8 vectors:
2442static SDOperand
2443LowerByteImmed(SDOperand Op, SelectionDAG &DAG) {
2444 SDOperand ConstVec;
2445 SDOperand Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002446 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002447
2448 ConstVec = Op.getOperand(0);
2449 Arg = Op.getOperand(1);
2450 if (ConstVec.Val->getOpcode() != ISD::BUILD_VECTOR) {
2451 if (ConstVec.Val->getOpcode() == ISD::BIT_CONVERT) {
2452 ConstVec = ConstVec.getOperand(0);
2453 } else {
2454 ConstVec = Op.getOperand(1);
2455 Arg = Op.getOperand(0);
2456 if (ConstVec.Val->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002457 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002458 }
2459 }
2460 }
2461
2462 if (ConstVec.Val->getOpcode() == ISD::BUILD_VECTOR) {
2463 uint64_t VectorBits[2];
2464 uint64_t UndefBits[2];
2465 uint64_t SplatBits, SplatUndef;
2466 int SplatSize;
2467
2468 if (!GetConstantBuildVectorBits(ConstVec.Val, VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002469 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002470 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002471 SplatBits, SplatUndef, SplatSize)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002472 SDOperand tcVec[16];
2473 SDOperand tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
2474 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2475
2476 // Turn the BUILD_VECTOR into a set of target constants:
2477 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002478 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002479
2480 return DAG.getNode(Op.Val->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002481 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002482 }
2483 }
2484
2485 return SDOperand();
2486}
2487
2488//! Lower i32 multiplication
Duncan Sands83ec4b62008-06-06 12:08:01 +00002489static SDOperand LowerMUL(SDOperand Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002490 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002491 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002492 default:
2493 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002494 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002495 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002496 abort();
2497 /*NOTREACHED*/
2498
2499 case MVT::i32: {
2500 SDOperand rA = Op.getOperand(0);
2501 SDOperand rB = Op.getOperand(1);
2502
2503 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002504 DAG.getNode(ISD::ADD, MVT::i32,
2505 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2506 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2507 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002508 }
2509 }
2510
2511 return SDOperand();
2512}
2513
2514//! Custom lowering for CTPOP (count population)
2515/*!
2516 Custom lowering code that counts the number ones in the input
2517 operand. SPU has such an instruction, but it counts the number of
2518 ones per byte, which then have to be accumulated.
2519*/
2520static SDOperand LowerCTPOP(SDOperand Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002521 MVT VT = Op.getValueType();
2522 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002523
Duncan Sands83ec4b62008-06-06 12:08:01 +00002524 switch (VT.getSimpleVT()) {
2525 default:
2526 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002527 case MVT::i8: {
2528 SDOperand N = Op.getOperand(0);
2529 SDOperand Elt0 = DAG.getConstant(0, MVT::i32);
2530
2531 SDOperand Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2532 SDOperand CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
2533
2534 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2535 }
2536
2537 case MVT::i16: {
2538 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002539 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002540
Chris Lattner84bc5422007-12-31 04:13:23 +00002541 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002542
2543 SDOperand N = Op.getOperand(0);
2544 SDOperand Elt0 = DAG.getConstant(0, MVT::i16);
2545 SDOperand Mask0 = DAG.getConstant(0x0f, MVT::i16);
2546 SDOperand Shift1 = DAG.getConstant(8, MVT::i16);
2547
2548 SDOperand Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2549 SDOperand CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
2550
2551 // CNTB_result becomes the chain to which all of the virtual registers
2552 // CNTB_reg, SUM1_reg become associated:
2553 SDOperand CNTB_result =
2554 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002555
Scott Michel266bc8f2007-12-04 22:23:35 +00002556 SDOperand CNTB_rescopy =
2557 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2558
2559 SDOperand Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
2560
2561 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002562 DAG.getNode(ISD::ADD, MVT::i16,
2563 DAG.getNode(ISD::SRL, MVT::i16,
2564 Tmp1, Shift1),
2565 Tmp1),
2566 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002567 }
2568
2569 case MVT::i32: {
2570 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002571 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002572
Chris Lattner84bc5422007-12-31 04:13:23 +00002573 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2574 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002575
2576 SDOperand N = Op.getOperand(0);
2577 SDOperand Elt0 = DAG.getConstant(0, MVT::i32);
2578 SDOperand Mask0 = DAG.getConstant(0xff, MVT::i32);
2579 SDOperand Shift1 = DAG.getConstant(16, MVT::i32);
2580 SDOperand Shift2 = DAG.getConstant(8, MVT::i32);
2581
2582 SDOperand Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2583 SDOperand CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
2584
2585 // CNTB_result becomes the chain to which all of the virtual registers
2586 // CNTB_reg, SUM1_reg become associated:
2587 SDOperand CNTB_result =
2588 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002589
Scott Michel266bc8f2007-12-04 22:23:35 +00002590 SDOperand CNTB_rescopy =
2591 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2592
2593 SDOperand Comp1 =
2594 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002595 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002596
2597 SDOperand Sum1 =
2598 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002599 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002600
2601 SDOperand Sum1_rescopy =
2602 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2603
2604 SDOperand Comp2 =
2605 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002606 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2607 Shift2);
Scott Michel266bc8f2007-12-04 22:23:35 +00002608 SDOperand Sum2 =
2609 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002610 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002611
2612 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2613 }
2614
2615 case MVT::i64:
2616 break;
2617 }
2618
2619 return SDOperand();
2620}
2621
2622/// LowerOperation - Provide custom lowering hooks for some operations.
2623///
2624SDOperand
2625SPUTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG)
2626{
Scott Michela59d4692008-02-23 18:41:37 +00002627 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002628 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002629
2630 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002631 default: {
2632 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002633 cerr << "Op.getOpcode() = " << Opc << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002634 cerr << "*Op.Val:\n";
2635 Op.Val->dump();
2636 abort();
2637 }
2638 case ISD::LOAD:
2639 case ISD::SEXTLOAD:
2640 case ISD::ZEXTLOAD:
2641 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2642 case ISD::STORE:
2643 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2644 case ISD::ConstantPool:
2645 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2646 case ISD::GlobalAddress:
2647 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2648 case ISD::JumpTable:
2649 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2650 case ISD::Constant:
2651 return LowerConstant(Op, DAG);
2652 case ISD::ConstantFP:
2653 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002654 case ISD::BRCOND:
2655 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002656 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002657 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002658 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002659 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002660 case ISD::RET:
2661 return LowerRET(Op, DAG, getTargetMachine());
2662
Scott Michela59d4692008-02-23 18:41:37 +00002663
2664 // i8, i64 math ops:
2665 case ISD::ZERO_EXTEND:
2666 case ISD::SIGN_EXTEND:
2667 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002668 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002669 case ISD::SUB:
2670 case ISD::ROTR:
2671 case ISD::ROTL:
2672 case ISD::SRL:
2673 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002674 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002675 if (VT == MVT::i8)
2676 return LowerI8Math(Op, DAG, Opc);
2677 else if (VT == MVT::i64)
2678 return LowerI64Math(Op, DAG, Opc);
2679 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002680 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002681
2682 // Vector-related lowering.
2683 case ISD::BUILD_VECTOR:
2684 return LowerBUILD_VECTOR(Op, DAG);
2685 case ISD::SCALAR_TO_VECTOR:
2686 return LowerSCALAR_TO_VECTOR(Op, DAG);
2687 case ISD::VECTOR_SHUFFLE:
2688 return LowerVECTOR_SHUFFLE(Op, DAG);
2689 case ISD::EXTRACT_VECTOR_ELT:
2690 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2691 case ISD::INSERT_VECTOR_ELT:
2692 return LowerINSERT_VECTOR_ELT(Op, DAG);
2693
2694 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2695 case ISD::AND:
2696 case ISD::OR:
2697 case ISD::XOR:
2698 return LowerByteImmed(Op, DAG);
2699
2700 // Vector and i8 multiply:
2701 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002702 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002703 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002704 else if (VT == MVT::i8)
2705 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002706 else
Scott Michela59d4692008-02-23 18:41:37 +00002707 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002708
2709 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002710 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002711 return LowerFDIVf32(Op, DAG);
2712// else if (Op.getValueType() == MVT::f64)
2713// return LowerFDIVf64(Op, DAG);
2714 else
2715 assert(0 && "Calling FDIV on unsupported MVT");
2716
2717 case ISD::CTPOP:
2718 return LowerCTPOP(Op, DAG);
2719 }
2720
2721 return SDOperand();
2722}
2723
2724//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002725// Target Optimization Hooks
2726//===----------------------------------------------------------------------===//
2727
2728SDOperand
2729SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2730{
2731#if 0
2732 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002733#endif
2734 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002735 SelectionDAG &DAG = DCI.DAG;
Scott Michela59d4692008-02-23 18:41:37 +00002736 SDOperand Op0 = N->getOperand(0); // everything has at least one operand
2737 SDOperand Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002738
2739 switch (N->getOpcode()) {
2740 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002741 case ISD::ADD: {
Scott Michel053c1da2008-01-29 02:16:57 +00002742 SDOperand Op1 = N->getOperand(1);
2743
Scott Michel8bf61e82008-06-02 22:18:03 +00002744 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Scott Michel053c1da2008-01-29 02:16:57 +00002745 SDOperand Op01 = Op0.getOperand(1);
2746 if (Op01.getOpcode() == ISD::Constant
2747 || Op01.getOpcode() == ISD::TargetConstant) {
2748 // (add <const>, (SPUindirect <arg>, <const>)) ->
2749 // (SPUindirect <arg>, <const + const>)
2750 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2751 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
2752 SDOperand combinedConst =
2753 DAG.getConstant(CN0->getValue() + CN1->getValue(),
2754 Op0.getValueType());
2755
2756 DEBUG(cerr << "Replace: (add " << CN0->getValue() << ", "
2757 << "(SPUindirect <arg>, " << CN1->getValue() << "))\n");
2758 DEBUG(cerr << "With: (SPUindirect <arg>, "
2759 << CN0->getValue() + CN1->getValue() << ")\n");
2760 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2761 Op0.getOperand(0), combinedConst);
2762 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002763 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002764 && Op1.getOpcode() == SPUISD::IndirectAddr) {
2765 SDOperand Op11 = Op1.getOperand(1);
2766 if (Op11.getOpcode() == ISD::Constant
2767 || Op11.getOpcode() == ISD::TargetConstant) {
2768 // (add (SPUindirect <arg>, <const>), <const>) ->
2769 // (SPUindirect <arg>, <const + const>)
2770 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2771 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
2772 SDOperand combinedConst =
2773 DAG.getConstant(CN0->getValue() + CN1->getValue(),
2774 Op0.getValueType());
2775
2776 DEBUG(cerr << "Replace: (add " << CN0->getValue() << ", "
2777 << "(SPUindirect <arg>, " << CN1->getValue() << "))\n");
2778 DEBUG(cerr << "With: (SPUindirect <arg>, "
2779 << CN0->getValue() + CN1->getValue() << ")\n");
2780
2781 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2782 Op1.getOperand(0), combinedConst);
2783 }
2784 }
Scott Michela59d4692008-02-23 18:41:37 +00002785 break;
2786 }
2787 case ISD::SIGN_EXTEND:
2788 case ISD::ZERO_EXTEND:
2789 case ISD::ANY_EXTEND: {
2790 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2791 N->getValueType(0) == Op0.getValueType()) {
2792 // (any_extend (SPUextract_elt0 <arg>)) ->
2793 // (SPUextract_elt0 <arg>)
2794 // Types must match, however...
2795 DEBUG(cerr << "Replace: ");
2796 DEBUG(N->dump(&DAG));
2797 DEBUG(cerr << "\nWith: ");
2798 DEBUG(Op0.Val->dump(&DAG));
2799 DEBUG(cerr << "\n");
2800
2801 return Op0;
2802 }
2803 break;
2804 }
2805 case SPUISD::IndirectAddr: {
2806 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2807 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
2808 if (CN->getValue() == 0) {
2809 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2810 // (SPUaform <addr>, 0)
2811
2812 DEBUG(cerr << "Replace: ");
2813 DEBUG(N->dump(&DAG));
2814 DEBUG(cerr << "\nWith: ");
2815 DEBUG(Op0.Val->dump(&DAG));
2816 DEBUG(cerr << "\n");
2817
2818 return Op0;
2819 }
2820 }
2821 break;
2822 }
2823 case SPUISD::SHLQUAD_L_BITS:
2824 case SPUISD::SHLQUAD_L_BYTES:
2825 case SPUISD::VEC_SHL:
2826 case SPUISD::VEC_SRL:
2827 case SPUISD::VEC_SRA:
2828 case SPUISD::ROTQUAD_RZ_BYTES:
2829 case SPUISD::ROTQUAD_RZ_BITS: {
2830 SDOperand Op1 = N->getOperand(1);
2831
2832 if (isa<ConstantSDNode>(Op1)) {
2833 // Kill degenerate vector shifts:
2834 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2835
2836 if (CN->getValue() == 0) {
2837 Result = Op0;
2838 }
2839 }
2840 break;
2841 }
2842 case SPUISD::PROMOTE_SCALAR: {
2843 switch (Op0.getOpcode()) {
2844 default:
2845 break;
2846 case ISD::ANY_EXTEND:
2847 case ISD::ZERO_EXTEND:
2848 case ISD::SIGN_EXTEND: {
2849 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2850 // <arg>
2851 // but only if the SPUpromote_scalar and <arg> types match.
2852 SDOperand Op00 = Op0.getOperand(0);
2853 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
2854 SDOperand Op000 = Op00.getOperand(0);
2855 if (Op000.getValueType() == N->getValueType(0)) {
2856 Result = Op000;
2857 }
2858 }
2859 break;
2860 }
2861 case SPUISD::EXTRACT_ELT0: {
2862 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2863 // <arg>
2864 Result = Op0.getOperand(0);
2865 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002866 }
Scott Michela59d4692008-02-23 18:41:37 +00002867 }
2868 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002869 }
2870 }
Scott Michel58c58182008-01-17 20:38:41 +00002871 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002872#if 1
Scott Michela59d4692008-02-23 18:41:37 +00002873 if (Result.Val) {
2874 DEBUG(cerr << "\nReplace.SPU: ");
2875 DEBUG(N->dump(&DAG));
2876 DEBUG(cerr << "\nWith: ");
2877 DEBUG(Result.Val->dump(&DAG));
2878 DEBUG(cerr << "\n");
2879 }
2880#endif
2881
2882 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002883}
2884
2885//===----------------------------------------------------------------------===//
2886// Inline Assembly Support
2887//===----------------------------------------------------------------------===//
2888
2889/// getConstraintType - Given a constraint letter, return the type of
2890/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002891SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002892SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2893 if (ConstraintLetter.size() == 1) {
2894 switch (ConstraintLetter[0]) {
2895 default: break;
2896 case 'b':
2897 case 'r':
2898 case 'f':
2899 case 'v':
2900 case 'y':
2901 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002902 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002903 }
2904 return TargetLowering::getConstraintType(ConstraintLetter);
2905}
2906
Scott Michel5af8f0e2008-07-16 17:17:29 +00002907std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002908SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002909 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002910{
2911 if (Constraint.size() == 1) {
2912 // GCC RS6000 Constraint Letters
2913 switch (Constraint[0]) {
2914 case 'b': // R1-R31
2915 case 'r': // R0-R31
2916 if (VT == MVT::i64)
2917 return std::make_pair(0U, SPU::R64CRegisterClass);
2918 return std::make_pair(0U, SPU::R32CRegisterClass);
2919 case 'f':
2920 if (VT == MVT::f32)
2921 return std::make_pair(0U, SPU::R32FPRegisterClass);
2922 else if (VT == MVT::f64)
2923 return std::make_pair(0U, SPU::R64FPRegisterClass);
2924 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002925 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002926 return std::make_pair(0U, SPU::GPRCRegisterClass);
2927 }
2928 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002929
Scott Michel266bc8f2007-12-04 22:23:35 +00002930 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2931}
2932
Scott Michela59d4692008-02-23 18:41:37 +00002933//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002934void
2935SPUTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002936 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002937 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002938 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002939 const SelectionDAG &DAG,
2940 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002941#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002942 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002943#endif
Scott Michela59d4692008-02-23 18:41:37 +00002944
2945 switch (Op.getOpcode()) {
2946 default:
2947 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2948 break;
2949
2950#if 0
2951 case CALL:
2952 case SHUFB:
2953 case INSERT_MASK:
2954 case CNTB:
2955#endif
2956
2957 case SPUISD::PROMOTE_SCALAR: {
2958 SDOperand Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002959 MVT Op0VT = Op0.getValueType();
2960 unsigned Op0VTBits = Op0VT.getSizeInBits();
2961 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002962 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2963 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002964 break;
2965 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002966
Scott Michela59d4692008-02-23 18:41:37 +00002967 case SPUISD::LDRESULT:
2968 case SPUISD::EXTRACT_ELT0:
2969 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002970 MVT OpVT = Op.getValueType();
2971 unsigned OpVTBits = OpVT.getSizeInBits();
2972 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002973 KnownZero |= APInt(OpVTBits, ~InMask, false);
2974 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002975 break;
2976 }
2977
2978#if 0
2979 case EXTRACT_I1_ZEXT:
2980 case EXTRACT_I1_SEXT:
2981 case EXTRACT_I8_ZEXT:
2982 case EXTRACT_I8_SEXT:
2983 case MPY:
2984 case MPYU:
2985 case MPYH:
2986 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00002987 case SPUISD::SHLQUAD_L_BITS:
2988 case SPUISD::SHLQUAD_L_BYTES:
2989 case SPUISD::VEC_SHL:
2990 case SPUISD::VEC_SRL:
2991 case SPUISD::VEC_SRA:
2992 case SPUISD::VEC_ROTL:
2993 case SPUISD::VEC_ROTR:
2994 case SPUISD::ROTQUAD_RZ_BYTES:
2995 case SPUISD::ROTQUAD_RZ_BITS:
2996 case SPUISD::ROTBYTES_RIGHT_S:
2997 case SPUISD::ROTBYTES_LEFT:
2998 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00002999 case SPUISD::SELECT_MASK:
3000 case SPUISD::SELB:
3001 case SPUISD::FPInterp:
3002 case SPUISD::FPRecipEst:
3003 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003004#endif
3005 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003006}
3007
Scott Michel203b2d62008-04-30 00:30:08 +00003008// LowerAsmOperandForConstraint
3009void
3010SPUTargetLowering::LowerAsmOperandForConstraint(SDOperand Op,
3011 char ConstraintLetter,
3012 std::vector<SDOperand> &Ops,
3013 SelectionDAG &DAG) const {
3014 // Default, for the time being, to the base class handler
3015 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, Ops, DAG);
3016}
3017
Scott Michel266bc8f2007-12-04 22:23:35 +00003018/// isLegalAddressImmediate - Return true if the integer value can be used
3019/// as the offset of the target addressing mode.
3020bool SPUTargetLowering::isLegalAddressImmediate(int64_t V, const Type *Ty) const {
3021 // SPU's addresses are 256K:
3022 return (V > -(1 << 18) && V < (1 << 18) - 1);
3023}
3024
3025bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003026 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003027}