blob: de2592d117d3fe2698bd4e0e4abf64402b75de02 [file] [log] [blame]
Scott Michel266bc8f2007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel266bc8f2007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SPUTargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPURegisterNames.h"
15#include "SPUISelLowering.h"
16#include "SPUTargetMachine.h"
Scott Michel203b2d62008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000018#include "llvm/ADT/VectorExtras.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000019#include "llvm/CodeGen/CallingConvLower.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner84bc5422007-12-31 04:13:23 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000025#include "llvm/Constants.h"
26#include "llvm/Function.h"
27#include "llvm/Intrinsics.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/MathExtras.h"
30#include "llvm/Target/TargetOptions.h"
31
32#include <map>
33
34using namespace llvm;
35
36// Used in getTargetNodeName() below
37namespace {
38 std::map<unsigned, const char *> node_names;
39
Duncan Sands83ec4b62008-06-06 12:08:01 +000040 //! MVT mapping to useful data for Cell SPU
Scott Michel266bc8f2007-12-04 22:23:35 +000041 struct valtype_map_s {
Duncan Sands83ec4b62008-06-06 12:08:01 +000042 const MVT valtype;
Scott Michel7f9ba9b2008-01-30 02:55:46 +000043 const int prefslot_byte;
Scott Michel266bc8f2007-12-04 22:23:35 +000044 };
Scott Michel5af8f0e2008-07-16 17:17:29 +000045
Scott Michel266bc8f2007-12-04 22:23:35 +000046 const valtype_map_s valtype_map[] = {
47 { MVT::i1, 3 },
48 { MVT::i8, 3 },
49 { MVT::i16, 2 },
50 { MVT::i32, 0 },
51 { MVT::f32, 0 },
52 { MVT::i64, 0 },
53 { MVT::f64, 0 },
54 { MVT::i128, 0 }
55 };
56
57 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
58
Duncan Sands83ec4b62008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel266bc8f2007-12-04 22:23:35 +000060 const valtype_map_s *retval = 0;
61
62 for (size_t i = 0; i < n_valtype_map; ++i) {
63 if (valtype_map[i].valtype == VT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel266bc8f2007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands83ec4b62008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +000074 abort();
75 }
76#endif
77
78 return retval;
79 }
80
81 //! Predicate that returns true if operand is a memory target
82 /*!
83 \arg Op Operand to test
84 \return true if the operand is a memory target (i.e., global
Scott Michel9de5d0d2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel266bc8f2007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman475871a2008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel266bc8f2007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
Bill Wendling056292f2008-09-16 21:48:12 +000095 || Opc == ISD::ExternalSymbol
Scott Michel266bc8f2007-12-04 22:23:35 +000096 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
Bill Wendling056292f2008-09-16 21:48:12 +0000100 || Opc == ISD::TargetExternalSymbol
Scott Michel9de5d0d2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000102 }
Scott Michel58c58182008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman475871a2008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel58c58182008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel58c58182008-01-17 20:38:41 +0000110 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000111}
112
113SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
114 : TargetLowering(TM),
115 SPUTM(TM)
116{
117 // Fold away setcc operations if possible.
118 setPow2DivIsCheap();
119
120 // Use _setjmp/_longjmp instead of setjmp/longjmp.
121 setUseUnderscoreSetJmp(true);
122 setUseUnderscoreLongJmp(true);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000123
Scott Michel266bc8f2007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel504c3692007-12-17 22:32:34 +0000125 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
126 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
127 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
128 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
129 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
130 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel266bc8f2007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000132
Scott Michel266bc8f2007-12-04 22:23:35 +0000133 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng03294662008-10-14 21:26:46 +0000134 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
135 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
136 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Chris Lattnerddf89562008-01-17 19:59:44 +0000137 setTruncStoreAction(MVT::i8, MVT::i1, Custom);
138 setTruncStoreAction(MVT::i16, MVT::i1, Custom);
139 setTruncStoreAction(MVT::i32, MVT::i1, Custom);
140 setTruncStoreAction(MVT::i64, MVT::i1, Custom);
141 setTruncStoreAction(MVT::i128, MVT::i1, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000142
Evan Cheng03294662008-10-14 21:26:46 +0000143 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
144 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
145 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Chris Lattnerddf89562008-01-17 19:59:44 +0000146 setTruncStoreAction(MVT::i8 , MVT::i8, Custom);
147 setTruncStoreAction(MVT::i16 , MVT::i8, Custom);
148 setTruncStoreAction(MVT::i32 , MVT::i8, Custom);
149 setTruncStoreAction(MVT::i64 , MVT::i8, Custom);
150 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000151
Evan Cheng03294662008-10-14 21:26:46 +0000152 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
153 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
154 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000155
156 // SPU constant load actions are custom lowered:
157 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begemanccef5802008-02-14 18:43:04 +0000158 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000159 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
160
161 // SPU's loads and stores have to be custom lowered:
162 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
163 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000164 MVT VT = (MVT::SimpleValueType)sctype;
165
166 setOperationAction(ISD::LOAD, VT, Custom);
167 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000168 }
169
Scott Michel58c58182008-01-17 20:38:41 +0000170 // Custom lower BRCOND for i1, i8 to "promote" the result to
171 // i32 and i16, respectively.
172 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000173
174 // Expand the jumptable branches
175 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
176 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000177 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000178
179 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000180 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
181
Scott Michel266bc8f2007-12-04 22:23:35 +0000182 // PowerPC has no SREM/UREM instructions
183 setOperationAction(ISD::SREM, MVT::i32, Expand);
184 setOperationAction(ISD::UREM, MVT::i32, Expand);
185 setOperationAction(ISD::SREM, MVT::i64, Expand);
186 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000187
Scott Michel266bc8f2007-12-04 22:23:35 +0000188 // We don't support sin/cos/sqrt/fmod
189 setOperationAction(ISD::FSIN , MVT::f64, Expand);
190 setOperationAction(ISD::FCOS , MVT::f64, Expand);
191 setOperationAction(ISD::FREM , MVT::f64, Expand);
192 setOperationAction(ISD::FSIN , MVT::f32, Expand);
193 setOperationAction(ISD::FCOS , MVT::f32, Expand);
194 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000195
Scott Michel266bc8f2007-12-04 22:23:35 +0000196 // If we're enabling GP optimizations, use hardware square root
197 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
198 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000199
Scott Michel266bc8f2007-12-04 22:23:35 +0000200 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
201 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
202
203 // SPU can do rotate right and left, so legalize it... but customize for i8
204 // because instructions don't exist.
Bill Wendling9440e352008-08-31 02:59:23 +0000205
206 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
207 // .td files.
208 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
209 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
210 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
211
Scott Michel266bc8f2007-12-04 22:23:35 +0000212 setOperationAction(ISD::ROTL, MVT::i32, Legal);
213 setOperationAction(ISD::ROTL, MVT::i16, Legal);
214 setOperationAction(ISD::ROTL, MVT::i8, Custom);
215 // SPU has no native version of shift left/right for i8
216 setOperationAction(ISD::SHL, MVT::i8, Custom);
217 setOperationAction(ISD::SRL, MVT::i8, Custom);
218 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michela59d4692008-02-23 18:41:37 +0000219 // And SPU needs custom lowering for shift left/right for i64
220 setOperationAction(ISD::SHL, MVT::i64, Custom);
221 setOperationAction(ISD::SRL, MVT::i64, Custom);
222 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000223
Scott Michel5af8f0e2008-07-16 17:17:29 +0000224 // Custom lower i8, i32 and i64 multiplications
225 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000226 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000227 setOperationAction(ISD::MUL, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000228
Scott Michel8bf61e82008-06-02 22:18:03 +0000229 // Need to custom handle (some) common i8, i64 math ops
230 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000231 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel8bf61e82008-06-02 22:18:03 +0000232 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000233
Scott Michel266bc8f2007-12-04 22:23:35 +0000234 // SPU does not have BSWAP. It does have i32 support CTLZ.
235 // CTPOP has to be custom lowered.
236 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
237 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
238
239 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
240 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
241 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
242 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
243
244 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
245 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
246
247 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000248
Scott Michel8bf61e82008-06-02 22:18:03 +0000249 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000250 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000251 setOperationAction(ISD::SELECT, MVT::i1, Promote);
252 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000253 setOperationAction(ISD::SELECT, MVT::i16, Legal);
254 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000255 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000256
Scott Michel78c47fa2008-03-10 16:58:52 +0000257 setOperationAction(ISD::SETCC, MVT::i1, Promote);
258 setOperationAction(ISD::SETCC, MVT::i8, Legal);
259 setOperationAction(ISD::SETCC, MVT::i16, Legal);
260 setOperationAction(ISD::SETCC, MVT::i32, Legal);
261 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michelad2715e2008-03-05 23:02:02 +0000262
Scott Michela59d4692008-02-23 18:41:37 +0000263 // Zero extension and sign extension for i64 have to be
264 // custom legalized
265 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
266 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
267 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000268
Scott Michel266bc8f2007-12-04 22:23:35 +0000269 // SPU has a legal FP -> signed INT instruction
270 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
271 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
272 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
273 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
274
275 // FDIV on SPU requires custom lowering
276 setOperationAction(ISD::FDIV, MVT::f32, Custom);
277 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
278
279 // SPU has [U|S]INT_TO_FP
280 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
281 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
282 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
283 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
284 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
285 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
286 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
287 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
288
Scott Michel86c041f2007-12-20 00:44:13 +0000289 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
290 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
291 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
292 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000293
294 // We cannot sextinreg(i1). Expand to shifts.
295 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000296
Scott Michel266bc8f2007-12-04 22:23:35 +0000297 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000298 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000299 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000300
301 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000302 // appropriate instructions to materialize the address.
Scott Michel053c1da2008-01-29 02:16:57 +0000303 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
304 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000305 MVT VT = (MVT::SimpleValueType)sctype;
306
307 setOperationAction(ISD::GlobalAddress, VT, Custom);
308 setOperationAction(ISD::ConstantPool, VT, Custom);
309 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000310 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000311
312 // RET must be custom lowered, to meet ABI requirements
313 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000314
Scott Michel266bc8f2007-12-04 22:23:35 +0000315 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
316 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000317
Scott Michel266bc8f2007-12-04 22:23:35 +0000318 // Use the default implementation.
319 setOperationAction(ISD::VAARG , MVT::Other, Expand);
320 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
321 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000322 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000323 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
324 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
325 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
326
327 // Cell SPU has instructions for converting between i64 and fp.
328 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
329 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000330
Scott Michel266bc8f2007-12-04 22:23:35 +0000331 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
332 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
333
334 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
335 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
336
337 // First set operation action for all vector types to expand. Then we
338 // will selectively turn on ones that can be effectively codegen'd.
339 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
340 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
341 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
342 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
343 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
344 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
345
Duncan Sands83ec4b62008-06-06 12:08:01 +0000346 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
347 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
348 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000349
Duncan Sands83ec4b62008-06-06 12:08:01 +0000350 // add/sub are legal for all supported vector VT's.
351 setOperationAction(ISD::ADD , VT, Legal);
352 setOperationAction(ISD::SUB , VT, Legal);
353 // mul has to be custom lowered.
354 setOperationAction(ISD::MUL , VT, Custom);
355
356 setOperationAction(ISD::AND , VT, Legal);
357 setOperationAction(ISD::OR , VT, Legal);
358 setOperationAction(ISD::XOR , VT, Legal);
359 setOperationAction(ISD::LOAD , VT, Legal);
360 setOperationAction(ISD::SELECT, VT, Legal);
361 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000362
Scott Michel266bc8f2007-12-04 22:23:35 +0000363 // These operations need to be expanded:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000364 setOperationAction(ISD::SDIV, VT, Expand);
365 setOperationAction(ISD::SREM, VT, Expand);
366 setOperationAction(ISD::UDIV, VT, Expand);
367 setOperationAction(ISD::UREM, VT, Expand);
368 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000369
370 // Custom lower build_vector, constant pool spills, insert and
371 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000372 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
373 setOperationAction(ISD::ConstantPool, VT, Custom);
374 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
375 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
376 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
377 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000378 }
379
380 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
381 setOperationAction(ISD::AND, MVT::v16i8, Custom);
382 setOperationAction(ISD::OR, MVT::v16i8, Custom);
383 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
384 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000385
Scott Michel266bc8f2007-12-04 22:23:35 +0000386 setShiftAmountType(MVT::i32);
387 setSetCCResultContents(ZeroOrOneSetCCResult);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000388
Scott Michel266bc8f2007-12-04 22:23:35 +0000389 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000390
Scott Michel266bc8f2007-12-04 22:23:35 +0000391 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000392 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000393 setTargetDAGCombine(ISD::ZERO_EXTEND);
394 setTargetDAGCombine(ISD::SIGN_EXTEND);
395 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000396
Scott Michel266bc8f2007-12-04 22:23:35 +0000397 computeRegisterProperties();
398}
399
400const char *
401SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
402{
403 if (node_names.empty()) {
404 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
405 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
406 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
407 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000408 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000409 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000410 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
411 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
412 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
413 node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
414 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
415 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
416 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
Gabor Greif93c53e52008-08-31 15:37:04 +0000417 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED]
418 = "SPUISD::EXTRACT_ELT0_CHAINED";
Scott Michel266bc8f2007-12-04 22:23:35 +0000419 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
420 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
421 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
422 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
423 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
424 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
425 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
426 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michela59d4692008-02-23 18:41:37 +0000427 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
428 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000429 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
430 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
431 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
432 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
433 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michela59d4692008-02-23 18:41:37 +0000434 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
435 "SPUISD::ROTQUAD_RZ_BYTES";
436 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
437 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel266bc8f2007-12-04 22:23:35 +0000438 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
439 "SPUISD::ROTBYTES_RIGHT_S";
440 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
441 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
442 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel8bf61e82008-06-02 22:18:03 +0000443 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
444 "SPUISD::ROTBYTES_LEFT_BITS";
445 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000446 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000447 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
448 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
449 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
450 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000451 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
452 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
453 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
454 }
455
456 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
457
458 return ((i != node_names.end()) ? i->second : 0);
459}
460
Dan Gohman475871a2008-07-27 21:46:04 +0000461MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000462 MVT VT = Op.getValueType();
Scott Micheld976c212008-10-30 01:51:48 +0000463 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel78c47fa2008-03-10 16:58:52 +0000464}
465
Scott Michel266bc8f2007-12-04 22:23:35 +0000466//===----------------------------------------------------------------------===//
467// Calling convention code:
468//===----------------------------------------------------------------------===//
469
470#include "SPUGenCallingConv.inc"
471
472//===----------------------------------------------------------------------===//
473// LowerOperation implementation
474//===----------------------------------------------------------------------===//
475
Scott Michel9de5d0d2008-01-11 02:53:15 +0000476/// Aligned load common code for CellSPU
477/*!
478 \param[in] Op The SelectionDAG load or store operand
479 \param[in] DAG The selection DAG
480 \param[in] ST CellSPU subtarget information structure
481 \param[in,out] alignment Caller initializes this to the load or store node's
482 value from getAlignment(), may be updated while generating the aligned load
483 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
484 offset (divisible by 16, modulo 16 == 0)
485 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
486 offset of the preferred slot (modulo 16 != 0)
487 \param[in,out] VT Caller initializes this value type to the the load or store
488 node's loaded or stored value type; may be updated if an i1-extended load or
489 store.
490 \param[out] was16aligned true if the base pointer had 16-byte alignment,
491 otherwise false. Can help to determine if the chunk needs to be rotated.
492
493 Both load and store lowering load a block of data aligned on a 16-byte
494 boundary. This is the common aligned load code shared between both.
495 */
Dan Gohman475871a2008-07-27 21:46:04 +0000496static SDValue
497AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Michel9de5d0d2008-01-11 02:53:15 +0000498 LSBaseSDNode *LSN,
499 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000500 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000501{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000502 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000503 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman475871a2008-07-27 21:46:04 +0000504 SDValue basePtr = LSN->getBasePtr();
505 SDValue chain = LSN->getChain();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000506
507 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000508 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000509
Gabor Greif93c53e52008-08-31 15:37:04 +0000510 if (Op1.getOpcode() == ISD::Constant
511 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000512 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000513
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000514 alignOffs = (int) CN->getZExtValue();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000515 prefSlotOffs = (int) (alignOffs & 0xf);
516
517 // Adjust the rotation amount to ensure that the final result ends up in
518 // the preferred slot:
519 prefSlotOffs -= vtm->prefslot_byte;
520 basePtr = basePtr.getOperand(0);
521
Scott Michel58c58182008-01-17 20:38:41 +0000522 // Loading from memory, can we adjust alignment?
523 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +0000524 SDValue APtr = basePtr.getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000525 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
526 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
527 alignment = GSDN->getGlobal()->getAlignment();
528 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000529 }
530 } else {
531 alignOffs = 0;
532 prefSlotOffs = -vtm->prefslot_byte;
533 }
Scott Michel203b2d62008-04-30 00:30:08 +0000534 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
535 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
536 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
537 prefSlotOffs = (int) (alignOffs & 0xf);
538 prefSlotOffs -= vtm->prefslot_byte;
539 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000540 } else {
541 alignOffs = 0;
542 prefSlotOffs = -vtm->prefslot_byte;
543 }
544
545 if (alignment == 16) {
546 // Realign the base pointer as a D-Form address:
547 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000548 basePtr = DAG.getNode(ISD::ADD, PtrVT,
549 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000550 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000551 }
552
553 // Emit the vector load:
554 was16aligned = true;
555 return DAG.getLoad(MVT::v16i8, chain, basePtr,
556 LSN->getSrcValue(), LSN->getSrcValueOffset(),
557 LSN->isVolatile(), 16);
558 }
559
560 // Unaligned load or we're using the "large memory" model, which means that
561 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000562 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greif93c53e52008-08-31 15:37:04 +0000563 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
564 DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000565 }
566
567 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000568 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000569 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000570 was16aligned = false;
571 return DAG.getLoad(MVT::v16i8, chain, basePtr,
572 LSN->getSrcValue(), LSN->getSrcValueOffset(),
573 LSN->isVolatile(), 16);
574}
575
Scott Michel266bc8f2007-12-04 22:23:35 +0000576/// Custom lower loads for CellSPU
577/*!
578 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
579 within a 16-byte block, we have to rotate to extract the requested element.
580 */
Dan Gohman475871a2008-07-27 21:46:04 +0000581static SDValue
582LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000583 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000584 SDValue the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000585 MVT VT = LN->getMemoryVT();
Gabor Greifba36cb52008-08-28 21:40:38 +0000586 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000587 ISD::LoadExtType ExtType = LN->getExtensionType();
588 unsigned alignment = LN->getAlignment();
Dan Gohman475871a2008-07-27 21:46:04 +0000589 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000590
Scott Michel266bc8f2007-12-04 22:23:35 +0000591 switch (LN->getAddressingMode()) {
592 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000593 int offset, rotamt;
594 bool was16aligned;
Dan Gohman475871a2008-07-27 21:46:04 +0000595 SDValue result =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000596 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000597
Gabor Greifba36cb52008-08-28 21:40:38 +0000598 if (result.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000599 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000600
601 the_chain = result.getValue(1);
602 // Rotate the chunk if necessary
603 if (rotamt < 0)
604 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000605 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000606 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
607
Scott Michel58c58182008-01-17 20:38:41 +0000608 Ops[0] = the_chain;
609 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000610 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000611 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
612 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000613 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000614 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000615 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000616 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000617 }
618
619 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
620 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000621 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000622
623 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
624 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000625 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000626
Scott Michel9de5d0d2008-01-11 02:53:15 +0000627 // Convert the loaded v16i8 vector to the appropriate vector type
628 // specified by the operand:
629 if (OpVT == VT) {
630 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000631 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000632 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000633 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000634
635 Ops[0] = the_chain;
636 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
637 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
638 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
639 the_chain = result.getValue(1);
640 } else {
641 // Handle the sign and zero-extending loads for i1 and i8:
642 unsigned NewOpC;
643
644 if (ExtType == ISD::SEXTLOAD) {
645 NewOpC = (OpVT == MVT::i1
646 ? SPUISD::EXTRACT_I1_SEXT
647 : SPUISD::EXTRACT_I8_SEXT);
648 } else {
649 assert(ExtType == ISD::ZEXTLOAD);
650 NewOpC = (OpVT == MVT::i1
651 ? SPUISD::EXTRACT_I1_ZEXT
652 : SPUISD::EXTRACT_I8_ZEXT);
653 }
654
655 result = DAG.getNode(NewOpC, OpVT, result);
656 }
657
658 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000659 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000660 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000661 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000662 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000663
Scott Michel58c58182008-01-17 20:38:41 +0000664 result = DAG.getNode(SPUISD::LDRESULT, retvts,
665 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000666 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000667 }
668 case ISD::PRE_INC:
669 case ISD::PRE_DEC:
670 case ISD::POST_INC:
671 case ISD::POST_DEC:
672 case ISD::LAST_INDEXED_MODE:
673 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
674 "UNINDEXED\n";
675 cerr << (unsigned) LN->getAddressingMode() << "\n";
676 abort();
677 /*NOTREACHED*/
678 }
679
Dan Gohman475871a2008-07-27 21:46:04 +0000680 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000681}
682
683/// Custom lower stores for CellSPU
684/*!
685 All CellSPU stores are aligned to 16-byte boundaries, so for elements
686 within a 16-byte block, we have to generate a shuffle to insert the
687 requested element into its place, then store the resulting block.
688 */
Dan Gohman475871a2008-07-27 21:46:04 +0000689static SDValue
690LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000691 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000692 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000693 MVT VT = Value.getValueType();
694 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
695 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000696 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000697
698 switch (SN->getAddressingMode()) {
699 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000700 int chunk_offset, slot_offset;
701 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000702
703 // The vector type we really want to load from the 16-byte chunk, except
704 // in the case of MVT::i1, which has to be v16i8.
Duncan Sands83ec4b62008-06-06 12:08:01 +0000705 MVT vecVT, stVecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000706
Scott Michel266bc8f2007-12-04 22:23:35 +0000707 if (StVT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000708 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
709 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000710
Dan Gohman475871a2008-07-27 21:46:04 +0000711 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000712 AlignedLoad(Op, DAG, ST, SN, alignment,
713 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000714
Gabor Greifba36cb52008-08-28 21:40:38 +0000715 if (alignLoadVec.getNode() == 0)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000716 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000717
Scott Michel9de5d0d2008-01-11 02:53:15 +0000718 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000719 SDValue basePtr = LN->getBasePtr();
720 SDValue the_chain = alignLoadVec.getValue(1);
721 SDValue theValue = SN->getValue();
722 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000723
724 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000725 && (theValue.getOpcode() == ISD::AssertZext
726 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000727 // Drill down and get the value for zero- and sign-extended
728 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000729 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000730 }
731
Scott Michel9de5d0d2008-01-11 02:53:15 +0000732 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000733
Dan Gohman475871a2008-07-27 21:46:04 +0000734 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
735 SDValue insertEltPtr;
736 SDValue insertEltOp;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000737
738 // If the base pointer is already a D-form address, then just create
739 // a new D-form address with a slot offset and the orignal base pointer.
740 // Otherwise generate a D-form address with the slot offset relative
741 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000742 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greifba36cb52008-08-28 21:40:38 +0000743 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michel497e8882008-01-11 21:01:19 +0000744 DEBUG(cerr << "\n");
745
Scott Michel053c1da2008-01-29 02:16:57 +0000746 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
747 (basePtr.getOpcode() == ISD::ADD
748 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000749 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000750 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000751 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000752 }
753
754 insertEltOp = DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000755 result = DAG.getNode(SPUISD::SHUFB, vecVT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000756 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue),
757 alignLoadVec,
758 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000759
Scott Michel9de5d0d2008-01-11 02:53:15 +0000760 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000761 LN->getSrcValue(), LN->getSrcValueOffset(),
762 LN->isVolatile(), LN->getAlignment());
763
764 return result;
765 /*UNREACHED*/
766 }
767 case ISD::PRE_INC:
768 case ISD::PRE_DEC:
769 case ISD::POST_INC:
770 case ISD::POST_DEC:
771 case ISD::LAST_INDEXED_MODE:
772 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
773 "UNINDEXED\n";
774 cerr << (unsigned) SN->getAddressingMode() << "\n";
775 abort();
776 /*NOTREACHED*/
777 }
778
Dan Gohman475871a2008-07-27 21:46:04 +0000779 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000780}
781
782/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000783static SDValue
784LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000785 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000786 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
787 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000788 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
789 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000790 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000791
792 if (TM.getRelocationModel() == Reloc::Static) {
793 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000794 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000795 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000796 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000797 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
798 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000799 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000800 }
801 }
802
803 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000804 "LowerConstantPool: Relocation model other than static"
805 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000806 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000807}
808
Dan Gohman475871a2008-07-27 21:46:04 +0000809static SDValue
810LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000811 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000812 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000813 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
814 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000815 const TargetMachine &TM = DAG.getTarget();
816
817 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000818 if (!ST->usingLargeMem()) {
819 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
820 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000821 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
822 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000823 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
824 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000825 }
826
827 assert(0 &&
828 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000829 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000830}
831
Dan Gohman475871a2008-07-27 21:46:04 +0000832static SDValue
833LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000834 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000835 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
836 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000837 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000838 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000839 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000840
Scott Michel266bc8f2007-12-04 22:23:35 +0000841 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000842 if (!ST->usingLargeMem()) {
843 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
844 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000845 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
846 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000847 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
848 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000849 } else {
850 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000851 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000852 abort();
853 /*NOTREACHED*/
854 }
855
Dan Gohman475871a2008-07-27 21:46:04 +0000856 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000857}
858
859//! Custom lower i64 integer constants
860/*!
861 This code inserts all of the necessary juggling that needs to occur to load
862 a 64-bit constant into a register.
863 */
Dan Gohman475871a2008-07-27 21:46:04 +0000864static SDValue
865LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000866 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000867 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000868
869 if (VT == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000870 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +0000871 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000872 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000873 } else {
874 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000875 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000876 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000877 abort();
878 /*NOTREACHED*/
879 }
880
Dan Gohman475871a2008-07-27 21:46:04 +0000881 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000882}
883
Nate Begemanccef5802008-02-14 18:43:04 +0000884//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000885static SDValue
886LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000887 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000888 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000889
890 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000891 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000892
Nate Begemanccef5802008-02-14 18:43:04 +0000893 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000894 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000895 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000896 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000897 }
898
Dan Gohman475871a2008-07-27 21:46:04 +0000899 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000900}
901
Scott Michel58c58182008-01-17 20:38:41 +0000902//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000903static SDValue
904LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000905{
Dan Gohman475871a2008-07-27 21:46:04 +0000906 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000907 MVT CondVT = Cond.getValueType();
908 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000909
910 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
911 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
912 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
913 Op.getOperand(0),
914 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
915 Op.getOperand(2));
916 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000917 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000918}
919
Dan Gohman475871a2008-07-27 21:46:04 +0000920static SDValue
921LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000922{
923 MachineFunction &MF = DAG.getMachineFunction();
924 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000925 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Micheld976c212008-10-30 01:51:48 +0000926 SmallVector<SDValue, 48> ArgValues;
Dan Gohman475871a2008-07-27 21:46:04 +0000927 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000928 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000929
930 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
931 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000932
Scott Michel266bc8f2007-12-04 22:23:35 +0000933 unsigned ArgOffset = SPUFrameInfo::minStackSize();
934 unsigned ArgRegIdx = 0;
935 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000936
Duncan Sands83ec4b62008-06-06 12:08:01 +0000937 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000938
Scott Michel266bc8f2007-12-04 22:23:35 +0000939 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000940 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
941 ArgNo != e; ++ArgNo) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000942 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
943 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Micheld976c212008-10-30 01:51:48 +0000944 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000945
Scott Micheld976c212008-10-30 01:51:48 +0000946 if (ArgRegIdx < NumArgRegs) {
947 const TargetRegisterClass *ArgRegClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000948
Scott Micheld976c212008-10-30 01:51:48 +0000949 switch (ObjectVT.getSimpleVT()) {
950 default: {
951 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
952 << ObjectVT.getMVTString()
953 << "\n";
954 abort();
955 }
956 case MVT::i8:
957 ArgRegClass = &SPU::R8CRegClass;
958 break;
959 case MVT::i16:
960 ArgRegClass = &SPU::R16CRegClass;
961 break;
962 case MVT::i32:
963 ArgRegClass = &SPU::R32CRegClass;
964 break;
965 case MVT::i64:
966 ArgRegClass = &SPU::R64CRegClass;
967 break;
968 case MVT::f32:
969 ArgRegClass = &SPU::R32FPRegClass;
970 break;
971 case MVT::f64:
972 ArgRegClass = &SPU::R64FPRegClass;
973 break;
974 case MVT::v2f64:
975 case MVT::v4f32:
976 case MVT::v2i64:
977 case MVT::v4i32:
978 case MVT::v8i16:
979 case MVT::v16i8:
980 ArgRegClass = &SPU::VECREGRegClass;
981 ++ArgRegIdx;
982 break;
983 }
984
985 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
986 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
987 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
988 ++ArgRegIdx;
989 } else {
990 // We need to load the argument to a virtual register if we determined
991 // above that we ran out of physical registers of the appropriate type
992 // or we're forced to do vararg
Chris Lattner9f72d1a2008-02-13 07:35:30 +0000993 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +0000994 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +0000995 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000996 ArgOffset += StackSlotSize;
997 }
Scott Michel5af8f0e2008-07-16 17:17:29 +0000998
Scott Michel266bc8f2007-12-04 22:23:35 +0000999 ArgValues.push_back(ArgVal);
Scott Micheld976c212008-10-30 01:51:48 +00001000 // Update the chain
1001 Root = ArgVal.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001002 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001003
Scott Micheld976c212008-10-30 01:51:48 +00001004 // vararg handling:
Scott Michel266bc8f2007-12-04 22:23:35 +00001005 if (isVarArg) {
Scott Micheld976c212008-10-30 01:51:48 +00001006 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1007 // We will spill (79-3)+1 registers to the stack
1008 SmallVector<SDValue, 79-3+1> MemOps;
1009
1010 // Create the frame slot
1011
Scott Michel266bc8f2007-12-04 22:23:35 +00001012 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Micheld976c212008-10-30 01:51:48 +00001013 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1014 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1015 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1016 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1017 Root = Store.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001018 MemOps.push_back(Store);
Scott Micheld976c212008-10-30 01:51:48 +00001019
1020 // Increment address by stack slot size for the next stored argument
1021 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001022 }
1023 if (!MemOps.empty())
Scott Micheld976c212008-10-30 01:51:48 +00001024 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001025 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001026
Scott Michel266bc8f2007-12-04 22:23:35 +00001027 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001028
Scott Michel266bc8f2007-12-04 22:23:35 +00001029 // Return the new list of results.
Gabor Greifba36cb52008-08-28 21:40:38 +00001030 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf9516202008-06-30 10:19:09 +00001031 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001032}
1033
1034/// isLSAAddress - Return the immediate to use if the specified
1035/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001036static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001037 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
1038 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001039
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001040 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001041 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1042 (Addr << 14 >> 14) != Addr)
1043 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001044
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001045 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001046}
1047
1048static
Dan Gohman475871a2008-07-27 21:46:04 +00001049SDValue
1050LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman095cc292008-09-13 01:54:27 +00001051 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1052 SDValue Chain = TheCall->getChain();
Dan Gohman095cc292008-09-13 01:54:27 +00001053 SDValue Callee = TheCall->getCallee();
1054 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001055 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1056 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1057 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1058
1059 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001060 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001061
Scott Michel266bc8f2007-12-04 22:23:35 +00001062 // Accumulate how many bytes are to be pushed on the stack, including the
1063 // linkage area, and parameter passing area. According to the SPU ABI,
1064 // we minimally need space for [LR] and [SP]
1065 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001066
Scott Michel266bc8f2007-12-04 22:23:35 +00001067 // Set up a copy of the stack pointer for use loading and storing any
1068 // arguments that may not fit in the registers available for argument
1069 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001070 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001071
Scott Michel266bc8f2007-12-04 22:23:35 +00001072 // Figure out which arguments are going to go in registers, and which in
1073 // memory.
1074 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1075 unsigned ArgRegIdx = 0;
1076
1077 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001078 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001079 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001080 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001081
1082 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001083 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001084
Scott Michel266bc8f2007-12-04 22:23:35 +00001085 // PtrOff will be used to store the current argument to the stack if a
1086 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001087 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001088 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1089
Duncan Sands83ec4b62008-06-06 12:08:01 +00001090 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001091 default: assert(0 && "Unexpected ValueType for argument!");
1092 case MVT::i32:
1093 case MVT::i64:
1094 case MVT::i128:
1095 if (ArgRegIdx != NumArgRegs) {
1096 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1097 } else {
1098 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001099 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001100 }
1101 break;
1102 case MVT::f32:
1103 case MVT::f64:
1104 if (ArgRegIdx != NumArgRegs) {
1105 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1106 } else {
1107 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001108 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001109 }
1110 break;
1111 case MVT::v4f32:
1112 case MVT::v4i32:
1113 case MVT::v8i16:
1114 case MVT::v16i8:
1115 if (ArgRegIdx != NumArgRegs) {
1116 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1117 } else {
1118 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001119 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001120 }
1121 break;
1122 }
1123 }
1124
1125 // Update number of stack bytes actually used, insert a call sequence start
1126 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnere563bbc2008-10-11 22:08:30 +00001127 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1128 true));
Scott Michel266bc8f2007-12-04 22:23:35 +00001129
1130 if (!MemOpChains.empty()) {
1131 // Adjust the stack pointer for the stack arguments.
1132 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1133 &MemOpChains[0], MemOpChains.size());
1134 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001135
Scott Michel266bc8f2007-12-04 22:23:35 +00001136 // Build a sequence of copy-to-reg nodes chained together with token chain
1137 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001138 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001139 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1140 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1141 InFlag);
1142 InFlag = Chain.getValue(1);
1143 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001144
Dan Gohman475871a2008-07-27 21:46:04 +00001145 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001146 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001147
Bill Wendling056292f2008-09-16 21:48:12 +00001148 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1149 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1150 // node so that legalize doesn't hack it.
Scott Michel266bc8f2007-12-04 22:23:35 +00001151 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1152 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001153 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001154 SDValue Zero = DAG.getConstant(0, PtrVT);
1155 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001156
Scott Michel9de5d0d2008-01-11 02:53:15 +00001157 if (!ST->usingLargeMem()) {
1158 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1159 // style calls, otherwise, external symbols are BRASL calls. This assumes
1160 // that declared/defined symbols are in the same compilation unit and can
1161 // be reached through PC-relative jumps.
1162 //
1163 // NOTE:
1164 // This may be an unsafe assumption for JIT and really large compilation
1165 // units.
1166 if (GV->isDeclaration()) {
1167 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1168 } else {
1169 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1170 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001171 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001172 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1173 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001174 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001175 }
Bill Wendling056292f2008-09-16 21:48:12 +00001176 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
1177 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001178 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001179 // If this is an absolute destination address that appears to be a legal
1180 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001181 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001182 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001183
1184 Ops.push_back(Chain);
1185 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001186
Scott Michel266bc8f2007-12-04 22:23:35 +00001187 // Add argument registers to the end of the list so that they are known live
1188 // into the call.
1189 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001190 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001191 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001192
Gabor Greifba36cb52008-08-28 21:40:38 +00001193 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001194 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001195 // Returns a chain and a flag for retval copy to use.
1196 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1197 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001198 InFlag = Chain.getValue(1);
1199
Chris Lattnere563bbc2008-10-11 22:08:30 +00001200 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1201 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001202 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001203 InFlag = Chain.getValue(1);
1204
Dan Gohman475871a2008-07-27 21:46:04 +00001205 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001206 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001207
Scott Michel266bc8f2007-12-04 22:23:35 +00001208 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001209 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001210 default: assert(0 && "Unexpected ret value!");
1211 case MVT::Other: break;
1212 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001213 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001214 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1215 ResultVals[0] = Chain.getValue(0);
1216 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1217 Chain.getValue(2)).getValue(1);
1218 ResultVals[1] = Chain.getValue(0);
1219 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001220 } else {
1221 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1222 ResultVals[0] = Chain.getValue(0);
1223 NumResults = 1;
1224 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001225 break;
1226 case MVT::i64:
1227 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1228 ResultVals[0] = Chain.getValue(0);
1229 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001230 break;
1231 case MVT::f32:
1232 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001233 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001234 InFlag).getValue(1);
1235 ResultVals[0] = Chain.getValue(0);
1236 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001237 break;
1238 case MVT::v2f64:
1239 case MVT::v4f32:
1240 case MVT::v4i32:
1241 case MVT::v8i16:
1242 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001243 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001244 InFlag).getValue(1);
1245 ResultVals[0] = Chain.getValue(0);
1246 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001247 break;
1248 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001249
Scott Michel266bc8f2007-12-04 22:23:35 +00001250 // If the function returns void, just return the chain.
1251 if (NumResults == 0)
1252 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001253
Scott Michel266bc8f2007-12-04 22:23:35 +00001254 // Otherwise, merge everything together with a MERGE_VALUES node.
1255 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001256 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001257 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001258}
1259
Dan Gohman475871a2008-07-27 21:46:04 +00001260static SDValue
1261LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001262 SmallVector<CCValAssign, 16> RVLocs;
1263 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1264 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1265 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001266 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001267
Scott Michel266bc8f2007-12-04 22:23:35 +00001268 // If this is the first return lowered for this function, add the regs to the
1269 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001270 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001271 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001272 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001273 }
1274
Dan Gohman475871a2008-07-27 21:46:04 +00001275 SDValue Chain = Op.getOperand(0);
1276 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001277
Scott Michel266bc8f2007-12-04 22:23:35 +00001278 // Copy the result values into the output registers.
1279 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1280 CCValAssign &VA = RVLocs[i];
1281 assert(VA.isRegLoc() && "Can only return in registers!");
1282 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1283 Flag = Chain.getValue(1);
1284 }
1285
Gabor Greifba36cb52008-08-28 21:40:38 +00001286 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001287 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1288 else
1289 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1290}
1291
1292
1293//===----------------------------------------------------------------------===//
1294// Vector related lowering:
1295//===----------------------------------------------------------------------===//
1296
1297static ConstantSDNode *
1298getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001299 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001300
Scott Michel266bc8f2007-12-04 22:23:35 +00001301 // Check to see if this buildvec has a single non-undef value in its elements.
1302 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1303 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001304 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001305 OpVal = N->getOperand(i);
1306 else if (OpVal != N->getOperand(i))
1307 return 0;
1308 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001309
Gabor Greifba36cb52008-08-28 21:40:38 +00001310 if (OpVal.getNode() != 0) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001311 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1312 return CN;
1313 }
1314 }
1315
1316 return 0; // All UNDEF: use implicit def.; not Constant node
1317}
1318
1319/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1320/// and the value fits into an unsigned 18-bit constant, and if so, return the
1321/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001322SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001323 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001324 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001325 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001326 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001327 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001328 uint32_t upper = uint32_t(UValue >> 32);
1329 uint32_t lower = uint32_t(UValue);
1330 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001331 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001332 Value = Value >> 32;
1333 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001334 if (Value <= 0x3ffff)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001335 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001336 }
1337
Dan Gohman475871a2008-07-27 21:46:04 +00001338 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001339}
1340
1341/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1342/// and the value fits into a signed 16-bit constant, and if so, return the
1343/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001344SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001345 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001346 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001347 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001348 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001349 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001350 uint32_t upper = uint32_t(UValue >> 32);
1351 uint32_t lower = uint32_t(UValue);
1352 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001353 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001354 Value = Value >> 32;
1355 }
Scott Michelad2715e2008-03-05 23:02:02 +00001356 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001357 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001358 }
1359 }
1360
Dan Gohman475871a2008-07-27 21:46:04 +00001361 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001362}
1363
1364/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1365/// and the value fits into a signed 10-bit constant, and if so, return the
1366/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001367SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001368 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001369 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001370 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001371 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001372 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001373 uint32_t upper = uint32_t(UValue >> 32);
1374 uint32_t lower = uint32_t(UValue);
1375 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001376 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001377 Value = Value >> 32;
1378 }
Scott Michelad2715e2008-03-05 23:02:02 +00001379 if (isS10Constant(Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001380 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001381 }
1382
Dan Gohman475871a2008-07-27 21:46:04 +00001383 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001384}
1385
1386/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1387/// and the value fits into a signed 8-bit constant, and if so, return the
1388/// constant.
1389///
1390/// @note: The incoming vector is v16i8 because that's the only way we can load
1391/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1392/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001393SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001394 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001395 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001396 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001397 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001398 && Value <= 0xffff /* truncated from uint64_t */
1399 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001400 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001401 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001402 && (Value & 0xff) == Value)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001403 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001404 }
1405
Dan Gohman475871a2008-07-27 21:46:04 +00001406 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001407}
1408
1409/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1410/// and the value fits into a signed 16-bit constant, and if so, return the
1411/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001412SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001413 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001414 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001415 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001416 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001417 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1418 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001419 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001420 }
1421
Dan Gohman475871a2008-07-27 21:46:04 +00001422 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001423}
1424
1425/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001426SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001427 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001428 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001429 }
1430
Dan Gohman475871a2008-07-27 21:46:04 +00001431 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001432}
1433
1434/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001435SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001436 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001437 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001438 }
1439
Dan Gohman475871a2008-07-27 21:46:04 +00001440 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001441}
1442
1443// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001444// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001445// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1446// zero. Return true if this is not an array of constants, false if it is.
1447//
1448static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1449 uint64_t UndefBits[2]) {
1450 // Start with zero'd results.
1451 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001452
Duncan Sands83ec4b62008-06-06 12:08:01 +00001453 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001454 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001455 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001456
Scott Michel266bc8f2007-12-04 22:23:35 +00001457 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1458 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1459
1460 uint64_t EltBits = 0;
1461 if (OpVal.getOpcode() == ISD::UNDEF) {
1462 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1463 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1464 continue;
1465 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001466 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00001467 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
1468 const APFloat &apf = CN->getValueAPF();
1469 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001470 ? FloatToBits(apf.convertToFloat())
1471 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001472 } else {
1473 // Nonconstant element.
1474 return true;
1475 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001476
Scott Michel266bc8f2007-12-04 22:23:35 +00001477 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1478 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001479
1480 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001481 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1482 return false;
1483}
1484
1485/// If this is a splat (repetition) of a value across the whole vector, return
1486/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001487/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001488/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001489static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001490 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001491 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001492 uint64_t &SplatBits, uint64_t &SplatUndef,
1493 int &SplatSize) {
1494 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1495 // the same as the lower 64-bits, ignoring undefs.
1496 uint64_t Bits64 = Bits128[0] | Bits128[1];
1497 uint64_t Undef64 = Undef128[0] & Undef128[1];
1498 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1499 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1500 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1501 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1502
1503 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1504 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001505
Scott Michel266bc8f2007-12-04 22:23:35 +00001506 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1507 // undefs.
1508 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001509 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001510
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001511 // If the top 16-bits are different than the lower 16-bits, ignoring
1512 // undefs, we have an i32 splat.
1513 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1514 if (MinSplatBits < 16) {
1515 // If the top 8-bits are different than the lower 8-bits, ignoring
1516 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001517 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1518 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001519 // Otherwise, we have an 8-bit splat.
1520 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1521 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1522 SplatSize = 1;
1523 return true;
1524 }
1525 } else {
1526 SplatBits = Bits16;
1527 SplatUndef = Undef16;
1528 SplatSize = 2;
1529 return true;
1530 }
1531 }
1532 } else {
1533 SplatBits = Bits32;
1534 SplatUndef = Undef32;
1535 SplatSize = 4;
1536 return true;
1537 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001538 }
1539 } else {
1540 SplatBits = Bits128[0];
1541 SplatUndef = Undef128[0];
1542 SplatSize = 8;
1543 return true;
1544 }
1545 }
1546
1547 return false; // Can't be a splat if two pieces don't match.
1548}
1549
1550// If this is a case we can't handle, return null and let the default
1551// expansion code take care of it. If we CAN select this case, and if it
1552// selects to a single instruction, return Op. Otherwise, if we can codegen
1553// this case more efficiently than a constant pool load, lower it to the
1554// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001555static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001556 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001557 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001558 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001559 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001560 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001561 uint64_t VectorBits[2];
1562 uint64_t UndefBits[2];
1563 uint64_t SplatBits, SplatUndef;
1564 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001565 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001566 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001567 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001568 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001569 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001570
Duncan Sands83ec4b62008-06-06 12:08:01 +00001571 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001572 default:
1573 case MVT::v4f32: {
1574 uint32_t Value32 = SplatBits;
1575 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001576 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001577 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001578 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001579 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001580 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001581 break;
1582 }
1583 case MVT::v2f64: {
1584 uint64_t f64val = SplatBits;
1585 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001586 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001587 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001588 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001589 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001590 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001591 break;
1592 }
1593 case MVT::v16i8: {
1594 // 8-bit constants have to be expanded to 16-bits
1595 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001596 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001597 for (int i = 0; i < 8; ++i)
1598 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1599 return DAG.getNode(ISD::BIT_CONVERT, VT,
1600 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1601 }
1602 case MVT::v8i16: {
1603 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001604 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001605 Value16 = (unsigned short) (SplatBits & 0xffff);
1606 else
1607 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001608 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1609 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001610 for (int i = 0; i < 8; ++i) Ops[i] = T;
1611 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1612 }
1613 case MVT::v4i32: {
1614 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001615 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001616 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1617 }
1618 case MVT::v2i64: {
1619 uint64_t val = SplatBits;
1620 uint32_t upper = uint32_t(val >> 32);
1621 uint32_t lower = uint32_t(val);
1622
Scott Michel4cb8bd82008-03-06 04:02:54 +00001623 if (upper == lower) {
1624 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001625 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001626 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001627 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001628 SDValue LO32;
1629 SDValue HI32;
1630 SmallVector<SDValue, 16> ShufBytes;
1631 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001632 bool upper_special, lower_special;
1633
1634 // NOTE: This code creates common-case shuffle masks that can be easily
1635 // detected as common expressions. It is not attempting to create highly
1636 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1637
1638 // Detect if the upper or lower half is a special shuffle mask pattern:
1639 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1640 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1641
1642 // Create lower vector if not a special pattern
1643 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001644 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001645 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1646 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1647 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001648 }
1649
1650 // Create upper vector if not a special pattern
1651 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001652 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001653 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1654 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1655 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001656 }
1657
1658 // If either upper or lower are special, then the two input operands are
1659 // the same (basically, one of them is a "don't care")
1660 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001661 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001662 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001663 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001664 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001665 // Unhappy situation... both upper and lower are special, so punt with
1666 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001667 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001668 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001669 Zero, Zero);
1670 }
1671
1672 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001673 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001674 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001675 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001676 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001677 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001678 process_upper = (upper_special && (i & 1) == 0);
1679 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001680
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001681 if (process_upper || process_lower) {
1682 if ((process_upper && upper == 0)
1683 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001684 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001685 else if ((process_upper && upper == 0xffffffff)
1686 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001687 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001688 else if ((process_upper && upper == 0x80000000)
1689 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001690 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001691 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001692 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001693 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001694
1695 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001696 }
1697
1698 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001699 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001700 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001701 }
1702 }
1703 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001704
Dan Gohman475871a2008-07-27 21:46:04 +00001705 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001706}
1707
1708/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1709/// which the Cell can operate. The code inspects V3 to ascertain whether the
1710/// permutation vector, V3, is monotonically increasing with one "exception"
1711/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1712/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1713/// In either case, the net result is going to eventually invoke SHUFB to
1714/// permute/shuffle the bytes from V1 and V2.
1715/// \note
1716/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1717/// control word for byte/halfword/word insertion. This takes care of a single
1718/// element move from V2 into V1.
1719/// \note
1720/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001721static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1722 SDValue V1 = Op.getOperand(0);
1723 SDValue V2 = Op.getOperand(1);
1724 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001725
Scott Michel266bc8f2007-12-04 22:23:35 +00001726 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001727
Scott Michel266bc8f2007-12-04 22:23:35 +00001728 // If we have a single element being moved from V1 to V2, this can be handled
1729 // using the C*[DX] compute mask instructions, but the vector elements have
1730 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001731 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001732 unsigned EltsFromV2 = 0;
1733 unsigned V2Elt = 0;
1734 unsigned V2EltIdx0 = 0;
1735 unsigned CurrElt = 0;
1736 bool monotonic = true;
1737 if (EltVT == MVT::i8)
1738 V2EltIdx0 = 16;
1739 else if (EltVT == MVT::i16)
1740 V2EltIdx0 = 8;
1741 else if (EltVT == MVT::i32)
1742 V2EltIdx0 = 4;
1743 else
1744 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1745
1746 for (unsigned i = 0, e = PermMask.getNumOperands();
1747 EltsFromV2 <= 1 && monotonic && i != e;
1748 ++i) {
1749 unsigned SrcElt;
1750 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1751 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001752 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001753 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001754
1755 if (SrcElt >= V2EltIdx0) {
1756 ++EltsFromV2;
1757 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1758 } else if (CurrElt != SrcElt) {
1759 monotonic = false;
1760 }
1761
1762 ++CurrElt;
1763 }
1764
1765 if (EltsFromV2 == 1 && monotonic) {
1766 // Compute mask and shuffle
1767 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001768 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1769 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001770 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001771 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001772 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001773 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1774 // Copy register's contents as index in INSERT_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001775 SDValue ShufMaskOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001776 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001777 DAG.getTargetConstant(V2Elt, MVT::i32),
1778 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001779 // Use shuffle mask in SHUFB synthetic instruction:
1780 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1781 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001782 // Convert the SHUFFLE_VECTOR mask's input element units to the
1783 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001784 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001785
Dan Gohman475871a2008-07-27 21:46:04 +00001786 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001787 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1788 unsigned SrcElt;
1789 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001790 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001791 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001792 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001793
Scott Michela59d4692008-02-23 18:41:37 +00001794 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001795 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1796 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001797 }
1798 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001799
Dan Gohman475871a2008-07-27 21:46:04 +00001800 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001801 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001802 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1803 }
1804}
1805
Dan Gohman475871a2008-07-27 21:46:04 +00001806static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1807 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001808
Gabor Greifba36cb52008-08-28 21:40:38 +00001809 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001810 // For a constant, build the appropriate constant vector, which will
1811 // eventually simplify to a vector register load.
1812
Gabor Greifba36cb52008-08-28 21:40:38 +00001813 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001814 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001815 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001816 size_t n_copies;
1817
1818 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001819 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001820 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001821 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001822 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1823 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1824 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1825 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1826 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1827 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1828 }
1829
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001830 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001831 for (size_t j = 0; j < n_copies; ++j)
1832 ConstVecValues.push_back(CValue);
1833
1834 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001835 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001836 } else {
1837 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001838 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001839 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1840 case MVT::i8:
1841 case MVT::i16:
1842 case MVT::i32:
1843 case MVT::i64:
1844 case MVT::f32:
1845 case MVT::f64:
1846 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1847 }
1848 }
1849
Dan Gohman475871a2008-07-27 21:46:04 +00001850 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001851}
1852
Dan Gohman475871a2008-07-27 21:46:04 +00001853static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001854 switch (Op.getValueType().getSimpleVT()) {
1855 default:
1856 cerr << "CellSPU: Unknown vector multiplication, got "
1857 << Op.getValueType().getMVTString()
1858 << "\n";
1859 abort();
1860 /*NOTREACHED*/
1861
Scott Michel266bc8f2007-12-04 22:23:35 +00001862 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001863 SDValue rA = Op.getOperand(0);
1864 SDValue rB = Op.getOperand(1);
1865 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1866 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1867 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1868 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001869
1870 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1871 break;
1872 }
1873
1874 // Multiply two v8i16 vectors (pipeline friendly version):
1875 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1876 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1877 // c) Use SELB to select upper and lower halves from the intermediate results
1878 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001879 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001880 // dual-issue. This code does manage to do this, even if it's a little on
1881 // the wacky side
1882 case MVT::v8i16: {
1883 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001884 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001885 SDValue Chain = Op.getOperand(0);
1886 SDValue rA = Op.getOperand(0);
1887 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001888 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1889 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001890
Dan Gohman475871a2008-07-27 21:46:04 +00001891 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001892 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001893 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001894 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001895
Dan Gohman475871a2008-07-27 21:46:04 +00001896 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001897 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001898 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001899
Dan Gohman475871a2008-07-27 21:46:04 +00001900 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001901 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001902 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001903
1904 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001905 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1906 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1907 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1908 HHProd_v4i32,
1909 DAG.getConstant(16, MVT::i16))),
1910 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001911 }
1912
1913 // This M00sE is N@stI! (apologies to Monty Python)
1914 //
1915 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1916 // is to break it all apart, sign extend, and reassemble the various
1917 // intermediate products.
1918 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001919 SDValue rA = Op.getOperand(0);
1920 SDValue rB = Op.getOperand(1);
1921 SDValue c8 = DAG.getConstant(8, MVT::i32);
1922 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001923
Dan Gohman475871a2008-07-27 21:46:04 +00001924 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001925 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001926 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1927 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001928
Dan Gohman475871a2008-07-27 21:46:04 +00001929 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001930
Dan Gohman475871a2008-07-27 21:46:04 +00001931 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001932
Dan Gohman475871a2008-07-27 21:46:04 +00001933 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001934 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001935 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001936
Dan Gohman475871a2008-07-27 21:46:04 +00001937 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001938 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001939
Dan Gohman475871a2008-07-27 21:46:04 +00001940 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001941 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1942 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1943 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001944
Dan Gohman475871a2008-07-27 21:46:04 +00001945 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001946
Dan Gohman475871a2008-07-27 21:46:04 +00001947 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001948 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00001949 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001950 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1951 LoProdMask, LoProdMask,
1952 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001953
Dan Gohman475871a2008-07-27 21:46:04 +00001954 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001955 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001956 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001957
Dan Gohman475871a2008-07-27 21:46:04 +00001958 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001959 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001960 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001961
Dan Gohman475871a2008-07-27 21:46:04 +00001962 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001963 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001964 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1965 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00001966
Dan Gohman475871a2008-07-27 21:46:04 +00001967 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001968 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001969 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001970 DAG.getNode(SPUISD::VEC_SRA,
1971 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001972 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001973 DAG.getNode(SPUISD::VEC_SRA,
1974 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001975
Dan Gohman475871a2008-07-27 21:46:04 +00001976 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00001977 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1978 HLProd,
1979 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
1980 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00001981
Dan Gohman475871a2008-07-27 21:46:04 +00001982 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00001983 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001984
1985 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001986 DAG.getNode(ISD::OR, MVT::v4i32,
1987 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00001988 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001989 }
1990
Dan Gohman475871a2008-07-27 21:46:04 +00001991 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001992}
1993
Dan Gohman475871a2008-07-27 21:46:04 +00001994static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001995 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001996 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00001997
Dan Gohman475871a2008-07-27 21:46:04 +00001998 SDValue A = Op.getOperand(0);
1999 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002000 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002001
2002 unsigned VRegBR, VRegC;
2003
2004 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002005 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2006 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002007 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002008 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2009 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002010 }
2011 // TODO: make sure we're feeding FPInterp the right arguments
2012 // Right now: fi B, frest(B)
2013
2014 // Computes BRcpl =
2015 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002016 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002017 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2018 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002019 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002020
Scott Michel266bc8f2007-12-04 22:23:35 +00002021 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002022 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002023 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002024 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002025 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002026 // What's the Chain variable do? It's magic!
2027 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002028
2029 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002030 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002031 DAG.getNode(ISD::FMUL, VT,
2032 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002033 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002034 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002035 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002036}
2037
Dan Gohman475871a2008-07-27 21:46:04 +00002038static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002039 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002040 SDValue N = Op.getOperand(0);
2041 SDValue Elt = Op.getOperand(1);
2042 SDValue ShufMask[16];
Scott Michel266bc8f2007-12-04 22:23:35 +00002043 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
2044
2045 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2046
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002047 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002048
2049 // sanity checks:
2050 if (VT == MVT::i8 && EltNo >= 16)
2051 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2052 else if (VT == MVT::i16 && EltNo >= 8)
2053 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2054 else if (VT == MVT::i32 && EltNo >= 4)
2055 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2056 else if (VT == MVT::i64 && EltNo >= 2)
2057 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2058
2059 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2060 // i32 and i64: Element 0 is the preferred slot
2061 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2062 }
2063
2064 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002065 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002066 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002067
Duncan Sands83ec4b62008-06-06 12:08:01 +00002068 switch (VT.getSimpleVT()) {
2069 default:
2070 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002071 case MVT::i8: {
2072 prefslot_begin = prefslot_end = 3;
2073 break;
2074 }
2075 case MVT::i16: {
2076 prefslot_begin = 2; prefslot_end = 3;
2077 break;
2078 }
2079 case MVT::i32: {
2080 prefslot_begin = 0; prefslot_end = 3;
2081 break;
2082 }
2083 case MVT::i64: {
2084 prefslot_begin = 0; prefslot_end = 7;
2085 break;
2086 }
2087 }
2088
Scott Michel0e5665b2007-12-19 21:17:42 +00002089 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002090 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002091
Scott Michel266bc8f2007-12-04 22:23:35 +00002092 for (int i = 0; i < 16; ++i) {
2093 // zero fill uppper part of preferred slot, don't care about the
2094 // other slots:
2095 unsigned int mask_val;
2096
2097 if (i <= prefslot_end) {
2098 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002099 ((i < prefslot_begin)
2100 ? 0x80
2101 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002102
Scott Michel0e5665b2007-12-19 21:17:42 +00002103 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002104 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002105 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2106 }
2107
Dan Gohman475871a2008-07-27 21:46:04 +00002108 SDValue ShufMaskVec =
Scott Michel266bc8f2007-12-04 22:23:35 +00002109 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002110 &ShufMask[0],
2111 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002112
2113 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002114 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2115 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002116
Scott Michel266bc8f2007-12-04 22:23:35 +00002117}
2118
Dan Gohman475871a2008-07-27 21:46:04 +00002119static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2120 SDValue VecOp = Op.getOperand(0);
2121 SDValue ValOp = Op.getOperand(1);
2122 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002123 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002124
2125 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2126 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2127
Duncan Sands83ec4b62008-06-06 12:08:01 +00002128 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002129 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002130 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002131
Dan Gohman475871a2008-07-27 21:46:04 +00002132 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002133 DAG.getNode(SPUISD::SHUFB, VT,
2134 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2135 VecOp,
2136 DAG.getNode(SPUISD::INSERT_MASK, VT,
2137 DAG.getNode(ISD::ADD, PtrVT,
2138 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002139 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002140 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002141
2142 return result;
2143}
2144
Dan Gohman475871a2008-07-27 21:46:04 +00002145static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002146{
Dan Gohman475871a2008-07-27 21:46:04 +00002147 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002148
2149 assert(Op.getValueType() == MVT::i8);
2150 switch (Opc) {
2151 default:
2152 assert(0 && "Unhandled i8 math operator");
2153 /*NOTREACHED*/
2154 break;
2155 case ISD::SUB: {
2156 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2157 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002158 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002159 N0 = (N0.getOpcode() != ISD::Constant
2160 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002161 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2162 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002163 N1 = (N1.getOpcode() != ISD::Constant
2164 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002165 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2166 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002167 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002168 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002169 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002170 case ISD::ROTR:
2171 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002172 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002173 unsigned N1Opc;
2174 N0 = (N0.getOpcode() != ISD::Constant
2175 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002176 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2177 MVT::i16));
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002178 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greif93c53e52008-08-31 15:37:04 +00002179 ? ISD::ZERO_EXTEND
2180 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002181 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002182 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002183 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002184 MVT::i32));
Dan Gohman475871a2008-07-27 21:46:04 +00002185 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002186 DAG.getNode(ISD::OR, MVT::i16, N0,
2187 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002188 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002189 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002190 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2191 }
2192 case ISD::SRL:
2193 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002194 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002195 unsigned N1Opc;
2196 N0 = (N0.getOpcode() != ISD::Constant
2197 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002198 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2199 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002200 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2201 ? ISD::ZERO_EXTEND
2202 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002203 N1 = (N1.getOpcode() != ISD::Constant
2204 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002205 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2206 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002207 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002208 DAG.getNode(Opc, MVT::i16, N0, N1));
2209 }
2210 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002211 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002212 unsigned N1Opc;
2213 N0 = (N0.getOpcode() != ISD::Constant
2214 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002215 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2216 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002217 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2218 ? ISD::SIGN_EXTEND
2219 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002220 N1 = (N1.getOpcode() != ISD::Constant
2221 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002222 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2223 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002224 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002225 DAG.getNode(Opc, MVT::i16, N0, N1));
2226 }
2227 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002228 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002229 unsigned N1Opc;
2230 N0 = (N0.getOpcode() != ISD::Constant
2231 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002232 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2233 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002234 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002235 N1 = (N1.getOpcode() != ISD::Constant
2236 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002237 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2238 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002239 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002240 DAG.getNode(Opc, MVT::i16, N0, N1));
2241 break;
2242 }
2243 }
2244
Dan Gohman475871a2008-07-27 21:46:04 +00002245 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002246}
2247
Dan Gohman475871a2008-07-27 21:46:04 +00002248static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002249{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002250 MVT VT = Op.getValueType();
2251 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002252
Dan Gohman475871a2008-07-27 21:46:04 +00002253 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002254
2255 switch (Opc) {
2256 case ISD::ZERO_EXTEND:
2257 case ISD::SIGN_EXTEND:
2258 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002259 MVT Op0VT = Op0.getValueType();
2260 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002261
2262 assert(Op0VT == MVT::i32
2263 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002264 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002265
2266 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2267 ? SPUISD::ROTBYTES_RIGHT_S
2268 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002269 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002270 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2271
2272 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2273 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2274 DAG.getNode(NewOpc, Op0VecVT,
2275 PromoteScalar,
2276 DAG.getConstant(4, MVT::i32))));
2277 }
2278
Scott Michel8bf61e82008-06-02 22:18:03 +00002279 case ISD::ADD: {
2280 // Turn operands into vectors to satisfy type checking (shufb works on
2281 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002282 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002283 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002284 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002285 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002286 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002287
2288 // Create the shuffle mask for "rotating" the borrow up one register slot
2289 // once the borrow is generated.
2290 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2291 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2292 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2293 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2294
Dan Gohman475871a2008-07-27 21:46:04 +00002295 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002296 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002297 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002298 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2299 CarryGen, CarryGen,
2300 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2301 &ShufBytes[0], ShufBytes.size()));
2302
2303 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2304 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2305 Op0, Op1, ShiftedCarry));
2306 }
2307
2308 case ISD::SUB: {
2309 // Turn operands into vectors to satisfy type checking (shufb works on
2310 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002311 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002312 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002313 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002314 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002315 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002316
2317 // Create the shuffle mask for "rotating" the borrow up one register slot
2318 // once the borrow is generated.
2319 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2320 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2321 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2322 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2323
Dan Gohman475871a2008-07-27 21:46:04 +00002324 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002325 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002326 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002327 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2328 BorrowGen, BorrowGen,
2329 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2330 &ShufBytes[0], ShufBytes.size()));
2331
2332 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2333 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2334 Op0, Op1, ShiftedBorrow));
2335 }
2336
Scott Michela59d4692008-02-23 18:41:37 +00002337 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002338 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002339 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002340 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2341 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002342 DAG.getNode(SPUISD::SELB, VecVT,
2343 Op0Vec,
2344 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002345 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002346 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002347 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002348 DAG.getNode(ISD::SRL, ShiftAmtVT,
2349 ShiftAmt,
2350 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002351 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002352 DAG.getNode(ISD::AND, ShiftAmtVT,
2353 ShiftAmt,
2354 DAG.getConstant(7, ShiftAmtVT));
2355
2356 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2357 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2358 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2359 MaskLower, ShiftAmtBytes),
2360 ShiftAmtBits));
2361 }
2362
2363 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002364 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002365 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002366 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002367 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002368 DAG.getNode(ISD::SRL, ShiftAmtVT,
2369 ShiftAmt,
2370 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002371 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002372 DAG.getNode(ISD::AND, ShiftAmtVT,
2373 ShiftAmt,
2374 DAG.getConstant(7, ShiftAmtVT));
2375
2376 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2377 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2378 Op0, ShiftAmtBytes),
2379 ShiftAmtBits);
2380 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002381
2382 case ISD::SRA: {
2383 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002384 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002385 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002386 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002387 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002388
2389 // Negate variable shift amounts
2390 if (!isa<ConstantSDNode>(ShiftAmt)) {
2391 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2392 DAG.getConstant(0, ShiftVT), ShiftAmt);
2393 }
2394
Dan Gohman475871a2008-07-27 21:46:04 +00002395 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002396 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2397 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2398 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2399 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002400 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002401 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002402 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002403 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2404 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002405 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002406 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2407 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002408 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002409 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2410 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002411 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002412 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2413 RotateLeftBytes, ShiftAmt);
2414
2415 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2416 RotateLeftBits);
2417 }
Scott Michela59d4692008-02-23 18:41:37 +00002418 }
2419
Dan Gohman475871a2008-07-27 21:46:04 +00002420 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002421}
2422
Scott Michel266bc8f2007-12-04 22:23:35 +00002423//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002424static SDValue
2425LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2426 SDValue ConstVec;
2427 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002428 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002429
2430 ConstVec = Op.getOperand(0);
2431 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002432 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2433 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002434 ConstVec = ConstVec.getOperand(0);
2435 } else {
2436 ConstVec = Op.getOperand(1);
2437 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002438 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002439 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002440 }
2441 }
2442 }
2443
Gabor Greifba36cb52008-08-28 21:40:38 +00002444 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002445 uint64_t VectorBits[2];
2446 uint64_t UndefBits[2];
2447 uint64_t SplatBits, SplatUndef;
2448 int SplatSize;
2449
Gabor Greifba36cb52008-08-28 21:40:38 +00002450 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002451 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002452 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002453 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002454 SDValue tcVec[16];
2455 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002456 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2457
2458 // Turn the BUILD_VECTOR into a set of target constants:
2459 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002460 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002461
Gabor Greifba36cb52008-08-28 21:40:38 +00002462 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002463 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002464 }
2465 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002466 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2467 // lowered. Return the operation, rather than a null SDValue.
2468 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002469}
2470
2471//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002472static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002473 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002474 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002475 default:
2476 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002477 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002478 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002479 abort();
2480 /*NOTREACHED*/
2481
2482 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002483 SDValue rA = Op.getOperand(0);
2484 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002485
2486 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002487 DAG.getNode(ISD::ADD, MVT::i32,
2488 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2489 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2490 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002491 }
2492 }
2493
Dan Gohman475871a2008-07-27 21:46:04 +00002494 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002495}
2496
2497//! Custom lowering for CTPOP (count population)
2498/*!
2499 Custom lowering code that counts the number ones in the input
2500 operand. SPU has such an instruction, but it counts the number of
2501 ones per byte, which then have to be accumulated.
2502*/
Dan Gohman475871a2008-07-27 21:46:04 +00002503static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002504 MVT VT = Op.getValueType();
2505 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002506
Duncan Sands83ec4b62008-06-06 12:08:01 +00002507 switch (VT.getSimpleVT()) {
2508 default:
2509 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002510 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002511 SDValue N = Op.getOperand(0);
2512 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002513
Dan Gohman475871a2008-07-27 21:46:04 +00002514 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2515 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002516
2517 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2518 }
2519
2520 case MVT::i16: {
2521 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002522 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002523
Chris Lattner84bc5422007-12-31 04:13:23 +00002524 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002525
Dan Gohman475871a2008-07-27 21:46:04 +00002526 SDValue N = Op.getOperand(0);
2527 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2528 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002529 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002530
Dan Gohman475871a2008-07-27 21:46:04 +00002531 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2532 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002533
2534 // CNTB_result becomes the chain to which all of the virtual registers
2535 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002536 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002537 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002538
Dan Gohman475871a2008-07-27 21:46:04 +00002539 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002540 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2541
Dan Gohman475871a2008-07-27 21:46:04 +00002542 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002543
2544 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002545 DAG.getNode(ISD::ADD, MVT::i16,
2546 DAG.getNode(ISD::SRL, MVT::i16,
2547 Tmp1, Shift1),
2548 Tmp1),
2549 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002550 }
2551
2552 case MVT::i32: {
2553 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002554 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002555
Chris Lattner84bc5422007-12-31 04:13:23 +00002556 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2557 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002558
Dan Gohman475871a2008-07-27 21:46:04 +00002559 SDValue N = Op.getOperand(0);
2560 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2561 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2562 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2563 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002564
Dan Gohman475871a2008-07-27 21:46:04 +00002565 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2566 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002567
2568 // CNTB_result becomes the chain to which all of the virtual registers
2569 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002570 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002571 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002572
Dan Gohman475871a2008-07-27 21:46:04 +00002573 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002574 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2575
Dan Gohman475871a2008-07-27 21:46:04 +00002576 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002577 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002578 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002579
Dan Gohman475871a2008-07-27 21:46:04 +00002580 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002581 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002582 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002583
Dan Gohman475871a2008-07-27 21:46:04 +00002584 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002585 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2586
Dan Gohman475871a2008-07-27 21:46:04 +00002587 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002588 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002589 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2590 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002591 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002592 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002593 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002594
2595 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2596 }
2597
2598 case MVT::i64:
2599 break;
2600 }
2601
Dan Gohman475871a2008-07-27 21:46:04 +00002602 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002603}
2604
2605/// LowerOperation - Provide custom lowering hooks for some operations.
2606///
Dan Gohman475871a2008-07-27 21:46:04 +00002607SDValue
2608SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002609{
Scott Michela59d4692008-02-23 18:41:37 +00002610 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002611 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002612
2613 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002614 default: {
2615 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002616 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002617 cerr << "*Op.getNode():\n";
2618 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002619 abort();
2620 }
2621 case ISD::LOAD:
2622 case ISD::SEXTLOAD:
2623 case ISD::ZEXTLOAD:
2624 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2625 case ISD::STORE:
2626 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2627 case ISD::ConstantPool:
2628 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2629 case ISD::GlobalAddress:
2630 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2631 case ISD::JumpTable:
2632 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2633 case ISD::Constant:
2634 return LowerConstant(Op, DAG);
2635 case ISD::ConstantFP:
2636 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002637 case ISD::BRCOND:
2638 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002639 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002640 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002641 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002642 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002643 case ISD::RET:
2644 return LowerRET(Op, DAG, getTargetMachine());
2645
Scott Michela59d4692008-02-23 18:41:37 +00002646
2647 // i8, i64 math ops:
2648 case ISD::ZERO_EXTEND:
2649 case ISD::SIGN_EXTEND:
2650 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002651 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002652 case ISD::SUB:
2653 case ISD::ROTR:
2654 case ISD::ROTL:
2655 case ISD::SRL:
2656 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002657 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002658 if (VT == MVT::i8)
2659 return LowerI8Math(Op, DAG, Opc);
2660 else if (VT == MVT::i64)
2661 return LowerI64Math(Op, DAG, Opc);
2662 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002663 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002664
2665 // Vector-related lowering.
2666 case ISD::BUILD_VECTOR:
2667 return LowerBUILD_VECTOR(Op, DAG);
2668 case ISD::SCALAR_TO_VECTOR:
2669 return LowerSCALAR_TO_VECTOR(Op, DAG);
2670 case ISD::VECTOR_SHUFFLE:
2671 return LowerVECTOR_SHUFFLE(Op, DAG);
2672 case ISD::EXTRACT_VECTOR_ELT:
2673 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2674 case ISD::INSERT_VECTOR_ELT:
2675 return LowerINSERT_VECTOR_ELT(Op, DAG);
2676
2677 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2678 case ISD::AND:
2679 case ISD::OR:
2680 case ISD::XOR:
2681 return LowerByteImmed(Op, DAG);
2682
2683 // Vector and i8 multiply:
2684 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002685 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002686 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002687 else if (VT == MVT::i8)
2688 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002689 else
Scott Michela59d4692008-02-23 18:41:37 +00002690 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002691
2692 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002693 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002694 return LowerFDIVf32(Op, DAG);
2695// else if (Op.getValueType() == MVT::f64)
2696// return LowerFDIVf64(Op, DAG);
2697 else
2698 assert(0 && "Calling FDIV on unsupported MVT");
2699
2700 case ISD::CTPOP:
2701 return LowerCTPOP(Op, DAG);
2702 }
2703
Dan Gohman475871a2008-07-27 21:46:04 +00002704 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002705}
2706
2707//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002708// Target Optimization Hooks
2709//===----------------------------------------------------------------------===//
2710
Dan Gohman475871a2008-07-27 21:46:04 +00002711SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002712SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2713{
2714#if 0
2715 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002716#endif
2717 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002718 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002719 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2720 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002721
2722 switch (N->getOpcode()) {
2723 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002724 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002725 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002726
Scott Michel8bf61e82008-06-02 22:18:03 +00002727 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002728 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002729 if (Op01.getOpcode() == ISD::Constant
2730 || Op01.getOpcode() == ISD::TargetConstant) {
2731 // (add <const>, (SPUindirect <arg>, <const>)) ->
2732 // (SPUindirect <arg>, <const + const>)
2733 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2734 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002735 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002736 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002737 Op0.getValueType());
2738
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002739 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2740 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002741 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002742 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002743 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2744 Op0.getOperand(0), combinedConst);
2745 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002746 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002747 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002748 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002749 if (Op11.getOpcode() == ISD::Constant
2750 || Op11.getOpcode() == ISD::TargetConstant) {
2751 // (add (SPUindirect <arg>, <const>), <const>) ->
2752 // (SPUindirect <arg>, <const + const>)
2753 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2754 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002755 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002756 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002757 Op0.getValueType());
2758
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002759 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2760 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002761 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002762 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002763
2764 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2765 Op1.getOperand(0), combinedConst);
2766 }
2767 }
Scott Michela59d4692008-02-23 18:41:37 +00002768 break;
2769 }
2770 case ISD::SIGN_EXTEND:
2771 case ISD::ZERO_EXTEND:
2772 case ISD::ANY_EXTEND: {
2773 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2774 N->getValueType(0) == Op0.getValueType()) {
2775 // (any_extend (SPUextract_elt0 <arg>)) ->
2776 // (SPUextract_elt0 <arg>)
2777 // Types must match, however...
2778 DEBUG(cerr << "Replace: ");
2779 DEBUG(N->dump(&DAG));
2780 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002781 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002782 DEBUG(cerr << "\n");
2783
2784 return Op0;
2785 }
2786 break;
2787 }
2788 case SPUISD::IndirectAddr: {
2789 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2790 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002791 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002792 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2793 // (SPUaform <addr>, 0)
2794
2795 DEBUG(cerr << "Replace: ");
2796 DEBUG(N->dump(&DAG));
2797 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002798 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002799 DEBUG(cerr << "\n");
2800
2801 return Op0;
2802 }
2803 }
2804 break;
2805 }
2806 case SPUISD::SHLQUAD_L_BITS:
2807 case SPUISD::SHLQUAD_L_BYTES:
2808 case SPUISD::VEC_SHL:
2809 case SPUISD::VEC_SRL:
2810 case SPUISD::VEC_SRA:
2811 case SPUISD::ROTQUAD_RZ_BYTES:
2812 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002813 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002814
2815 if (isa<ConstantSDNode>(Op1)) {
2816 // Kill degenerate vector shifts:
2817 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2818
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002819 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002820 Result = Op0;
2821 }
2822 }
2823 break;
2824 }
2825 case SPUISD::PROMOTE_SCALAR: {
2826 switch (Op0.getOpcode()) {
2827 default:
2828 break;
2829 case ISD::ANY_EXTEND:
2830 case ISD::ZERO_EXTEND:
2831 case ISD::SIGN_EXTEND: {
2832 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2833 // <arg>
2834 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002835 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002836 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00002837 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002838 if (Op000.getValueType() == N->getValueType(0)) {
2839 Result = Op000;
2840 }
2841 }
2842 break;
2843 }
2844 case SPUISD::EXTRACT_ELT0: {
2845 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2846 // <arg>
2847 Result = Op0.getOperand(0);
2848 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002849 }
Scott Michela59d4692008-02-23 18:41:37 +00002850 }
2851 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002852 }
2853 }
Scott Michel58c58182008-01-17 20:38:41 +00002854 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002855#if 1
Gabor Greifba36cb52008-08-28 21:40:38 +00002856 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00002857 DEBUG(cerr << "\nReplace.SPU: ");
2858 DEBUG(N->dump(&DAG));
2859 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002860 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002861 DEBUG(cerr << "\n");
2862 }
2863#endif
2864
2865 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002866}
2867
2868//===----------------------------------------------------------------------===//
2869// Inline Assembly Support
2870//===----------------------------------------------------------------------===//
2871
2872/// getConstraintType - Given a constraint letter, return the type of
2873/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002874SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002875SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2876 if (ConstraintLetter.size() == 1) {
2877 switch (ConstraintLetter[0]) {
2878 default: break;
2879 case 'b':
2880 case 'r':
2881 case 'f':
2882 case 'v':
2883 case 'y':
2884 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002885 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002886 }
2887 return TargetLowering::getConstraintType(ConstraintLetter);
2888}
2889
Scott Michel5af8f0e2008-07-16 17:17:29 +00002890std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002891SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002892 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002893{
2894 if (Constraint.size() == 1) {
2895 // GCC RS6000 Constraint Letters
2896 switch (Constraint[0]) {
2897 case 'b': // R1-R31
2898 case 'r': // R0-R31
2899 if (VT == MVT::i64)
2900 return std::make_pair(0U, SPU::R64CRegisterClass);
2901 return std::make_pair(0U, SPU::R32CRegisterClass);
2902 case 'f':
2903 if (VT == MVT::f32)
2904 return std::make_pair(0U, SPU::R32FPRegisterClass);
2905 else if (VT == MVT::f64)
2906 return std::make_pair(0U, SPU::R64FPRegisterClass);
2907 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002908 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002909 return std::make_pair(0U, SPU::GPRCRegisterClass);
2910 }
2911 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002912
Scott Michel266bc8f2007-12-04 22:23:35 +00002913 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2914}
2915
Scott Michela59d4692008-02-23 18:41:37 +00002916//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002917void
Dan Gohman475871a2008-07-27 21:46:04 +00002918SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002919 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002920 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002921 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002922 const SelectionDAG &DAG,
2923 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002924#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002925 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002926#endif
Scott Michela59d4692008-02-23 18:41:37 +00002927
2928 switch (Op.getOpcode()) {
2929 default:
2930 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2931 break;
2932
2933#if 0
2934 case CALL:
2935 case SHUFB:
2936 case INSERT_MASK:
2937 case CNTB:
2938#endif
2939
2940 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00002941 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002942 MVT Op0VT = Op0.getValueType();
2943 unsigned Op0VTBits = Op0VT.getSizeInBits();
2944 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002945 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2946 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002947 break;
2948 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002949
Scott Michela59d4692008-02-23 18:41:37 +00002950 case SPUISD::LDRESULT:
2951 case SPUISD::EXTRACT_ELT0:
2952 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002953 MVT OpVT = Op.getValueType();
2954 unsigned OpVTBits = OpVT.getSizeInBits();
2955 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002956 KnownZero |= APInt(OpVTBits, ~InMask, false);
2957 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002958 break;
2959 }
2960
2961#if 0
2962 case EXTRACT_I1_ZEXT:
2963 case EXTRACT_I1_SEXT:
2964 case EXTRACT_I8_ZEXT:
2965 case EXTRACT_I8_SEXT:
2966 case MPY:
2967 case MPYU:
2968 case MPYH:
2969 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00002970 case SPUISD::SHLQUAD_L_BITS:
2971 case SPUISD::SHLQUAD_L_BYTES:
2972 case SPUISD::VEC_SHL:
2973 case SPUISD::VEC_SRL:
2974 case SPUISD::VEC_SRA:
2975 case SPUISD::VEC_ROTL:
2976 case SPUISD::VEC_ROTR:
2977 case SPUISD::ROTQUAD_RZ_BYTES:
2978 case SPUISD::ROTQUAD_RZ_BITS:
2979 case SPUISD::ROTBYTES_RIGHT_S:
2980 case SPUISD::ROTBYTES_LEFT:
2981 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00002982 case SPUISD::SELECT_MASK:
2983 case SPUISD::SELB:
2984 case SPUISD::FPInterp:
2985 case SPUISD::FPRecipEst:
2986 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00002987#endif
2988 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002989}
2990
Scott Michel203b2d62008-04-30 00:30:08 +00002991// LowerAsmOperandForConstraint
2992void
Dan Gohman475871a2008-07-27 21:46:04 +00002993SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00002994 char ConstraintLetter,
Evan Chengda43bcf2008-09-24 00:05:32 +00002995 bool hasMemory,
Dan Gohman475871a2008-07-27 21:46:04 +00002996 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00002997 SelectionDAG &DAG) const {
2998 // Default, for the time being, to the base class handler
Evan Chengda43bcf2008-09-24 00:05:32 +00002999 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3000 Ops, DAG);
Scott Michel203b2d62008-04-30 00:30:08 +00003001}
3002
Scott Michel266bc8f2007-12-04 22:23:35 +00003003/// isLegalAddressImmediate - Return true if the integer value can be used
3004/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003005bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3006 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003007 // SPU's addresses are 256K:
3008 return (V > -(1 << 18) && V < (1 << 18) - 1);
3009}
3010
3011bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003012 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003013}
Dan Gohman6520e202008-10-18 02:06:02 +00003014
3015bool
3016SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3017 // The SPU target isn't yet aware of offsets.
3018 return false;
3019}