blob: 4b2a909b8f77dea2874b3b3a800d8656bd4a6355 [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);
Scott Michel719b0e12008-11-19 17:45:08 +0000137 setTruncStoreAction(MVT::i8, MVT::i1, Promote);
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:
Scott Michel719b0e12008-11-19 17:45:08 +0000162 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel266bc8f2007-12-04 22:23:35 +0000163 ++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.
Scott Michel719b0e12008-11-19 17:45:08 +0000705 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
706 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000707
Dan Gohman475871a2008-07-27 21:46:04 +0000708 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000709 AlignedLoad(Op, DAG, ST, SN, alignment,
710 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000711
Gabor Greifba36cb52008-08-28 21:40:38 +0000712 if (alignLoadVec.getNode() == 0)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000713 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000714
Scott Michel9de5d0d2008-01-11 02:53:15 +0000715 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000716 SDValue basePtr = LN->getBasePtr();
717 SDValue the_chain = alignLoadVec.getValue(1);
718 SDValue theValue = SN->getValue();
719 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000720
721 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000722 && (theValue.getOpcode() == ISD::AssertZext
723 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000724 // Drill down and get the value for zero- and sign-extended
725 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000726 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000727 }
728
Scott Michel9de5d0d2008-01-11 02:53:15 +0000729 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000730
Dan Gohman475871a2008-07-27 21:46:04 +0000731 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
732 SDValue insertEltPtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000733
734 // If the base pointer is already a D-form address, then just create
735 // a new D-form address with a slot offset and the orignal base pointer.
736 // Otherwise generate a D-form address with the slot offset relative
737 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000738 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greifba36cb52008-08-28 21:40:38 +0000739 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michel497e8882008-01-11 21:01:19 +0000740 DEBUG(cerr << "\n");
741
Scott Michel053c1da2008-01-29 02:16:57 +0000742 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
743 (basePtr.getOpcode() == ISD::ADD
744 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000745 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000746 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000747 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000748 }
749
Scott Michel430a5552008-11-19 15:24:16 +0000750 SDValue insertEltOp =
751 DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michel719b0e12008-11-19 17:45:08 +0000752 SDValue vectorizeOp =
753 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michel430a5552008-11-19 15:24:16 +0000754
755 result = DAG.getNode(SPUISD::SHUFB, vecVT, vectorizeOp, alignLoadVec,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000756 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000757
Scott Michel9de5d0d2008-01-11 02:53:15 +0000758 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000759 LN->getSrcValue(), LN->getSrcValueOffset(),
760 LN->isVolatile(), LN->getAlignment());
761
Scott Michel719b0e12008-11-19 17:45:08 +0000762#if 0 && defined(NDEBUG)
Scott Michel430a5552008-11-19 15:24:16 +0000763 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
764 const SDValue &currentRoot = DAG.getRoot();
765
766 DAG.setRoot(result);
767 cerr << "------- CellSPU:LowerStore result:\n";
768 DAG.dump();
769 cerr << "-------\n";
770 DAG.setRoot(currentRoot);
771 }
772#endif
773
Scott Michel266bc8f2007-12-04 22:23:35 +0000774 return result;
775 /*UNREACHED*/
776 }
777 case ISD::PRE_INC:
778 case ISD::PRE_DEC:
779 case ISD::POST_INC:
780 case ISD::POST_DEC:
781 case ISD::LAST_INDEXED_MODE:
782 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
783 "UNINDEXED\n";
784 cerr << (unsigned) SN->getAddressingMode() << "\n";
785 abort();
786 /*NOTREACHED*/
787 }
788
Dan Gohman475871a2008-07-27 21:46:04 +0000789 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000790}
791
792/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000793static SDValue
794LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000795 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000796 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
797 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000798 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
799 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000800 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000801
802 if (TM.getRelocationModel() == Reloc::Static) {
803 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000804 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000805 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000806 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000807 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
808 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000809 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000810 }
811 }
812
813 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000814 "LowerConstantPool: Relocation model other than static"
815 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000816 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000817}
818
Dan Gohman475871a2008-07-27 21:46:04 +0000819static SDValue
820LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000821 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000822 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000823 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
824 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000825 const TargetMachine &TM = DAG.getTarget();
826
827 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000828 if (!ST->usingLargeMem()) {
829 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
830 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000831 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
832 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000833 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
834 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000835 }
836
837 assert(0 &&
838 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000839 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000840}
841
Dan Gohman475871a2008-07-27 21:46:04 +0000842static SDValue
843LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000844 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000845 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
846 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000847 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000848 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000849 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000850
Scott Michel266bc8f2007-12-04 22:23:35 +0000851 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000852 if (!ST->usingLargeMem()) {
853 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
854 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000855 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
856 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000857 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
858 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000859 } else {
860 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000861 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000862 abort();
863 /*NOTREACHED*/
864 }
865
Dan Gohman475871a2008-07-27 21:46:04 +0000866 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000867}
868
869//! Custom lower i64 integer constants
870/*!
871 This code inserts all of the necessary juggling that needs to occur to load
872 a 64-bit constant into a register.
873 */
Dan Gohman475871a2008-07-27 21:46:04 +0000874static SDValue
875LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000876 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000877 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000878
879 if (VT == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000880 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +0000881 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000882 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000883 } else {
884 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000885 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000886 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000887 abort();
888 /*NOTREACHED*/
889 }
890
Dan Gohman475871a2008-07-27 21:46:04 +0000891 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000892}
893
Nate Begemanccef5802008-02-14 18:43:04 +0000894//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000895static SDValue
896LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000897 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000898 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000899
900 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000901 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000902
Nate Begemanccef5802008-02-14 18:43:04 +0000903 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000904 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000905 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000906 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000907 }
908
Dan Gohman475871a2008-07-27 21:46:04 +0000909 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000910}
911
Scott Michel58c58182008-01-17 20:38:41 +0000912//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000913static SDValue
914LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000915{
Dan Gohman475871a2008-07-27 21:46:04 +0000916 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000917 MVT CondVT = Cond.getValueType();
918 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000919
920 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
921 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
922 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
923 Op.getOperand(0),
924 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
925 Op.getOperand(2));
926 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000927 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000928}
929
Dan Gohman475871a2008-07-27 21:46:04 +0000930static SDValue
931LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000932{
933 MachineFunction &MF = DAG.getMachineFunction();
934 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000935 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Micheld976c212008-10-30 01:51:48 +0000936 SmallVector<SDValue, 48> ArgValues;
Dan Gohman475871a2008-07-27 21:46:04 +0000937 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000938 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000939
940 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
941 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000942
Scott Michel266bc8f2007-12-04 22:23:35 +0000943 unsigned ArgOffset = SPUFrameInfo::minStackSize();
944 unsigned ArgRegIdx = 0;
945 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000946
Duncan Sands83ec4b62008-06-06 12:08:01 +0000947 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000948
Scott Michel266bc8f2007-12-04 22:23:35 +0000949 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000950 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
951 ArgNo != e; ++ArgNo) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000952 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
953 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Micheld976c212008-10-30 01:51:48 +0000954 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000955
Scott Micheld976c212008-10-30 01:51:48 +0000956 if (ArgRegIdx < NumArgRegs) {
957 const TargetRegisterClass *ArgRegClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000958
Scott Micheld976c212008-10-30 01:51:48 +0000959 switch (ObjectVT.getSimpleVT()) {
960 default: {
961 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
962 << ObjectVT.getMVTString()
963 << "\n";
964 abort();
965 }
966 case MVT::i8:
967 ArgRegClass = &SPU::R8CRegClass;
968 break;
969 case MVT::i16:
970 ArgRegClass = &SPU::R16CRegClass;
971 break;
972 case MVT::i32:
973 ArgRegClass = &SPU::R32CRegClass;
974 break;
975 case MVT::i64:
976 ArgRegClass = &SPU::R64CRegClass;
977 break;
978 case MVT::f32:
979 ArgRegClass = &SPU::R32FPRegClass;
980 break;
981 case MVT::f64:
982 ArgRegClass = &SPU::R64FPRegClass;
983 break;
984 case MVT::v2f64:
985 case MVT::v4f32:
986 case MVT::v2i64:
987 case MVT::v4i32:
988 case MVT::v8i16:
989 case MVT::v16i8:
990 ArgRegClass = &SPU::VECREGRegClass;
Scott Micheld976c212008-10-30 01:51:48 +0000991 break;
992 }
993
994 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
995 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
996 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
997 ++ArgRegIdx;
998 } else {
999 // We need to load the argument to a virtual register if we determined
1000 // above that we ran out of physical registers of the appropriate type
1001 // or we're forced to do vararg
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001002 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001003 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001004 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001005 ArgOffset += StackSlotSize;
1006 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001007
Scott Michel266bc8f2007-12-04 22:23:35 +00001008 ArgValues.push_back(ArgVal);
Scott Micheld976c212008-10-30 01:51:48 +00001009 // Update the chain
1010 Root = ArgVal.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001011 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001012
Scott Micheld976c212008-10-30 01:51:48 +00001013 // vararg handling:
Scott Michel266bc8f2007-12-04 22:23:35 +00001014 if (isVarArg) {
Scott Micheld976c212008-10-30 01:51:48 +00001015 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1016 // We will spill (79-3)+1 registers to the stack
1017 SmallVector<SDValue, 79-3+1> MemOps;
1018
1019 // Create the frame slot
1020
Scott Michel266bc8f2007-12-04 22:23:35 +00001021 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Micheld976c212008-10-30 01:51:48 +00001022 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1023 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1024 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1025 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1026 Root = Store.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001027 MemOps.push_back(Store);
Scott Micheld976c212008-10-30 01:51:48 +00001028
1029 // Increment address by stack slot size for the next stored argument
1030 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001031 }
1032 if (!MemOps.empty())
Scott Micheld976c212008-10-30 01:51:48 +00001033 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001034 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001035
Scott Michel266bc8f2007-12-04 22:23:35 +00001036 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001037
Scott Michel266bc8f2007-12-04 22:23:35 +00001038 // Return the new list of results.
Gabor Greifba36cb52008-08-28 21:40:38 +00001039 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf9516202008-06-30 10:19:09 +00001040 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001041}
1042
1043/// isLSAAddress - Return the immediate to use if the specified
1044/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001045static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001046 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +00001047 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001048
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001049 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001050 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1051 (Addr << 14 >> 14) != Addr)
1052 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001053
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001054 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001055}
1056
1057static
Dan Gohman475871a2008-07-27 21:46:04 +00001058SDValue
1059LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman095cc292008-09-13 01:54:27 +00001060 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1061 SDValue Chain = TheCall->getChain();
Dan Gohman095cc292008-09-13 01:54:27 +00001062 SDValue Callee = TheCall->getCallee();
1063 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001064 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1065 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1066 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1067
1068 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001069 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001070
Scott Michel266bc8f2007-12-04 22:23:35 +00001071 // Accumulate how many bytes are to be pushed on the stack, including the
1072 // linkage area, and parameter passing area. According to the SPU ABI,
1073 // we minimally need space for [LR] and [SP]
1074 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001075
Scott Michel266bc8f2007-12-04 22:23:35 +00001076 // Set up a copy of the stack pointer for use loading and storing any
1077 // arguments that may not fit in the registers available for argument
1078 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001079 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001080
Scott Michel266bc8f2007-12-04 22:23:35 +00001081 // Figure out which arguments are going to go in registers, and which in
1082 // memory.
1083 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1084 unsigned ArgRegIdx = 0;
1085
1086 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001087 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001088 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001089 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001090
1091 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001092 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001093
Scott Michel266bc8f2007-12-04 22:23:35 +00001094 // PtrOff will be used to store the current argument to the stack if a
1095 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001096 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001097 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1098
Duncan Sands83ec4b62008-06-06 12:08:01 +00001099 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001100 default: assert(0 && "Unexpected ValueType for argument!");
1101 case MVT::i32:
1102 case MVT::i64:
1103 case MVT::i128:
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::f32:
1112 case MVT::f64:
1113 if (ArgRegIdx != NumArgRegs) {
1114 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1115 } else {
1116 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001117 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001118 }
1119 break;
1120 case MVT::v4f32:
1121 case MVT::v4i32:
1122 case MVT::v8i16:
1123 case MVT::v16i8:
1124 if (ArgRegIdx != NumArgRegs) {
1125 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1126 } else {
1127 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001128 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001129 }
1130 break;
1131 }
1132 }
1133
1134 // Update number of stack bytes actually used, insert a call sequence start
1135 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnere563bbc2008-10-11 22:08:30 +00001136 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1137 true));
Scott Michel266bc8f2007-12-04 22:23:35 +00001138
1139 if (!MemOpChains.empty()) {
1140 // Adjust the stack pointer for the stack arguments.
1141 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1142 &MemOpChains[0], MemOpChains.size());
1143 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001144
Scott Michel266bc8f2007-12-04 22:23:35 +00001145 // Build a sequence of copy-to-reg nodes chained together with token chain
1146 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001147 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001148 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1149 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1150 InFlag);
1151 InFlag = Chain.getValue(1);
1152 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001153
Dan Gohman475871a2008-07-27 21:46:04 +00001154 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001155 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001156
Bill Wendling056292f2008-09-16 21:48:12 +00001157 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1158 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1159 // node so that legalize doesn't hack it.
Scott Michel19fd42a2008-11-11 03:06:06 +00001160 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001161 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001162 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001163 SDValue Zero = DAG.getConstant(0, PtrVT);
1164 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001165
Scott Michel9de5d0d2008-01-11 02:53:15 +00001166 if (!ST->usingLargeMem()) {
1167 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1168 // style calls, otherwise, external symbols are BRASL calls. This assumes
1169 // that declared/defined symbols are in the same compilation unit and can
1170 // be reached through PC-relative jumps.
1171 //
1172 // NOTE:
1173 // This may be an unsafe assumption for JIT and really large compilation
1174 // units.
1175 if (GV->isDeclaration()) {
1176 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1177 } else {
1178 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1179 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001180 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001181 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1182 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001183 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001184 }
Scott Michel19fd42a2008-11-11 03:06:06 +00001185 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendling056292f2008-09-16 21:48:12 +00001186 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001187 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001188 // If this is an absolute destination address that appears to be a legal
1189 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001190 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001191 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001192
1193 Ops.push_back(Chain);
1194 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001195
Scott Michel266bc8f2007-12-04 22:23:35 +00001196 // Add argument registers to the end of the list so that they are known live
1197 // into the call.
1198 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001199 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001200 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001201
Gabor Greifba36cb52008-08-28 21:40:38 +00001202 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001203 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001204 // Returns a chain and a flag for retval copy to use.
1205 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1206 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001207 InFlag = Chain.getValue(1);
1208
Chris Lattnere563bbc2008-10-11 22:08:30 +00001209 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1210 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001211 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001212 InFlag = Chain.getValue(1);
1213
Dan Gohman475871a2008-07-27 21:46:04 +00001214 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001215 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001216
Scott Michel266bc8f2007-12-04 22:23:35 +00001217 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001218 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001219 default: assert(0 && "Unexpected ret value!");
1220 case MVT::Other: break;
1221 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001222 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001223 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1224 ResultVals[0] = Chain.getValue(0);
1225 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1226 Chain.getValue(2)).getValue(1);
1227 ResultVals[1] = Chain.getValue(0);
1228 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001229 } else {
1230 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1231 ResultVals[0] = Chain.getValue(0);
1232 NumResults = 1;
1233 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001234 break;
1235 case MVT::i64:
1236 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1237 ResultVals[0] = Chain.getValue(0);
1238 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001239 break;
1240 case MVT::f32:
1241 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001242 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001243 InFlag).getValue(1);
1244 ResultVals[0] = Chain.getValue(0);
1245 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001246 break;
1247 case MVT::v2f64:
1248 case MVT::v4f32:
1249 case MVT::v4i32:
1250 case MVT::v8i16:
1251 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001252 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001253 InFlag).getValue(1);
1254 ResultVals[0] = Chain.getValue(0);
1255 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001256 break;
1257 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001258
Scott Michel266bc8f2007-12-04 22:23:35 +00001259 // If the function returns void, just return the chain.
1260 if (NumResults == 0)
1261 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001262
Scott Michel266bc8f2007-12-04 22:23:35 +00001263 // Otherwise, merge everything together with a MERGE_VALUES node.
1264 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001265 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001266 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001267}
1268
Dan Gohman475871a2008-07-27 21:46:04 +00001269static SDValue
1270LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001271 SmallVector<CCValAssign, 16> RVLocs;
1272 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1273 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1274 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001275 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001276
Scott Michel266bc8f2007-12-04 22:23:35 +00001277 // If this is the first return lowered for this function, add the regs to the
1278 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001279 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001280 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001281 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001282 }
1283
Dan Gohman475871a2008-07-27 21:46:04 +00001284 SDValue Chain = Op.getOperand(0);
1285 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001286
Scott Michel266bc8f2007-12-04 22:23:35 +00001287 // Copy the result values into the output registers.
1288 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1289 CCValAssign &VA = RVLocs[i];
1290 assert(VA.isRegLoc() && "Can only return in registers!");
1291 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1292 Flag = Chain.getValue(1);
1293 }
1294
Gabor Greifba36cb52008-08-28 21:40:38 +00001295 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001296 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1297 else
1298 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1299}
1300
1301
1302//===----------------------------------------------------------------------===//
1303// Vector related lowering:
1304//===----------------------------------------------------------------------===//
1305
1306static ConstantSDNode *
1307getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001308 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001309
Scott Michel266bc8f2007-12-04 22:23:35 +00001310 // Check to see if this buildvec has a single non-undef value in its elements.
1311 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1312 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001313 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001314 OpVal = N->getOperand(i);
1315 else if (OpVal != N->getOperand(i))
1316 return 0;
1317 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001318
Gabor Greifba36cb52008-08-28 21:40:38 +00001319 if (OpVal.getNode() != 0) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001320 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001321 return CN;
1322 }
1323 }
1324
1325 return 0; // All UNDEF: use implicit def.; not Constant node
1326}
1327
1328/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1329/// and the value fits into an unsigned 18-bit constant, and if so, return the
1330/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001331SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001332 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001333 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001334 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001335 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001336 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001337 uint32_t upper = uint32_t(UValue >> 32);
1338 uint32_t lower = uint32_t(UValue);
1339 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001340 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001341 Value = Value >> 32;
1342 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001343 if (Value <= 0x3ffff)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001344 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001345 }
1346
Dan Gohman475871a2008-07-27 21:46:04 +00001347 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001348}
1349
1350/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1351/// and the value fits into a signed 16-bit constant, and if so, return the
1352/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001353SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001354 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001355 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001356 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001357 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001358 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001359 uint32_t upper = uint32_t(UValue >> 32);
1360 uint32_t lower = uint32_t(UValue);
1361 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001362 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001363 Value = Value >> 32;
1364 }
Scott Michelad2715e2008-03-05 23:02:02 +00001365 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001366 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001367 }
1368 }
1369
Dan Gohman475871a2008-07-27 21:46:04 +00001370 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001371}
1372
1373/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1374/// and the value fits into a signed 10-bit constant, and if so, return the
1375/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001376SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001377 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001378 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001379 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001380 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001381 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001382 uint32_t upper = uint32_t(UValue >> 32);
1383 uint32_t lower = uint32_t(UValue);
1384 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001385 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001386 Value = Value >> 32;
1387 }
Scott Michelad2715e2008-03-05 23:02:02 +00001388 if (isS10Constant(Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001389 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001390 }
1391
Dan Gohman475871a2008-07-27 21:46:04 +00001392 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001393}
1394
1395/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1396/// and the value fits into a signed 8-bit constant, and if so, return the
1397/// constant.
1398///
1399/// @note: The incoming vector is v16i8 because that's the only way we can load
1400/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1401/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001402SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001403 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001404 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001405 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001406 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001407 && Value <= 0xffff /* truncated from uint64_t */
1408 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001409 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001410 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001411 && (Value & 0xff) == Value)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001412 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001413 }
1414
Dan Gohman475871a2008-07-27 21:46:04 +00001415 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001416}
1417
1418/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1419/// and the value fits into a signed 16-bit constant, and if so, return the
1420/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001421SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001422 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001423 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001424 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001425 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001426 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1427 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001428 return DAG.getTargetConstant(Value >> 16, ValueType);
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 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001435SDValue SPU::get_v4i32_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::i32);
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/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001444SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001445 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001446 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001447 }
1448
Dan Gohman475871a2008-07-27 21:46:04 +00001449 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001450}
1451
1452// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001453// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001454// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1455// zero. Return true if this is not an array of constants, false if it is.
1456//
1457static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1458 uint64_t UndefBits[2]) {
1459 // Start with zero'd results.
1460 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001461
Duncan Sands83ec4b62008-06-06 12:08:01 +00001462 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001463 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001464 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001465
Scott Michel266bc8f2007-12-04 22:23:35 +00001466 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1467 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1468
1469 uint64_t EltBits = 0;
1470 if (OpVal.getOpcode() == ISD::UNDEF) {
1471 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1472 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1473 continue;
Scott Michel19fd42a2008-11-11 03:06:06 +00001474 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001475 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel19fd42a2008-11-11 03:06:06 +00001476 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001477 const APFloat &apf = CN->getValueAPF();
1478 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001479 ? FloatToBits(apf.convertToFloat())
1480 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001481 } else {
1482 // Nonconstant element.
1483 return true;
1484 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001485
Scott Michel266bc8f2007-12-04 22:23:35 +00001486 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1487 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001488
1489 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001490 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1491 return false;
1492}
1493
1494/// If this is a splat (repetition) of a value across the whole vector, return
1495/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001496/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001497/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001498static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001499 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001500 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001501 uint64_t &SplatBits, uint64_t &SplatUndef,
1502 int &SplatSize) {
1503 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1504 // the same as the lower 64-bits, ignoring undefs.
1505 uint64_t Bits64 = Bits128[0] | Bits128[1];
1506 uint64_t Undef64 = Undef128[0] & Undef128[1];
1507 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1508 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1509 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1510 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1511
1512 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1513 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001514
Scott Michel266bc8f2007-12-04 22:23:35 +00001515 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1516 // undefs.
1517 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001518 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001519
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001520 // If the top 16-bits are different than the lower 16-bits, ignoring
1521 // undefs, we have an i32 splat.
1522 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1523 if (MinSplatBits < 16) {
1524 // If the top 8-bits are different than the lower 8-bits, ignoring
1525 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001526 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1527 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001528 // Otherwise, we have an 8-bit splat.
1529 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1530 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1531 SplatSize = 1;
1532 return true;
1533 }
1534 } else {
1535 SplatBits = Bits16;
1536 SplatUndef = Undef16;
1537 SplatSize = 2;
1538 return true;
1539 }
1540 }
1541 } else {
1542 SplatBits = Bits32;
1543 SplatUndef = Undef32;
1544 SplatSize = 4;
1545 return true;
1546 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001547 }
1548 } else {
1549 SplatBits = Bits128[0];
1550 SplatUndef = Undef128[0];
1551 SplatSize = 8;
1552 return true;
1553 }
1554 }
1555
1556 return false; // Can't be a splat if two pieces don't match.
1557}
1558
1559// If this is a case we can't handle, return null and let the default
1560// expansion code take care of it. If we CAN select this case, and if it
1561// selects to a single instruction, return Op. Otherwise, if we can codegen
1562// this case more efficiently than a constant pool load, lower it to the
1563// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001564static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001565 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001566 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001567 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001568 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001569 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001570 uint64_t VectorBits[2];
1571 uint64_t UndefBits[2];
1572 uint64_t SplatBits, SplatUndef;
1573 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001574 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001575 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001576 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001577 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001578 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001579
Duncan Sands83ec4b62008-06-06 12:08:01 +00001580 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001581 default:
1582 case MVT::v4f32: {
1583 uint32_t Value32 = SplatBits;
1584 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001585 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001586 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001587 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001588 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001589 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001590 break;
1591 }
1592 case MVT::v2f64: {
1593 uint64_t f64val = SplatBits;
1594 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001595 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001596 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001597 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001598 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001599 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001600 break;
1601 }
1602 case MVT::v16i8: {
1603 // 8-bit constants have to be expanded to 16-bits
1604 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001605 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001606 for (int i = 0; i < 8; ++i)
1607 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1608 return DAG.getNode(ISD::BIT_CONVERT, VT,
1609 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1610 }
1611 case MVT::v8i16: {
1612 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001613 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001614 Value16 = (unsigned short) (SplatBits & 0xffff);
1615 else
1616 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001617 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1618 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001619 for (int i = 0; i < 8; ++i) Ops[i] = T;
1620 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1621 }
1622 case MVT::v4i32: {
1623 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001624 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001625 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1626 }
1627 case MVT::v2i64: {
1628 uint64_t val = SplatBits;
1629 uint32_t upper = uint32_t(val >> 32);
1630 uint32_t lower = uint32_t(val);
1631
Scott Michel4cb8bd82008-03-06 04:02:54 +00001632 if (upper == lower) {
1633 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001634 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001635 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001636 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001637 SDValue LO32;
1638 SDValue HI32;
1639 SmallVector<SDValue, 16> ShufBytes;
1640 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001641 bool upper_special, lower_special;
1642
1643 // NOTE: This code creates common-case shuffle masks that can be easily
1644 // detected as common expressions. It is not attempting to create highly
1645 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1646
1647 // Detect if the upper or lower half is a special shuffle mask pattern:
1648 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1649 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1650
1651 // Create lower vector if not a special pattern
1652 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001653 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001654 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1655 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1656 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001657 }
1658
1659 // Create upper vector if not a special pattern
1660 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001661 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001662 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1663 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1664 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001665 }
1666
1667 // If either upper or lower are special, then the two input operands are
1668 // the same (basically, one of them is a "don't care")
1669 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001670 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001671 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001672 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001673 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001674 // Unhappy situation... both upper and lower are special, so punt with
1675 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001676 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001677 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001678 Zero, Zero);
1679 }
1680
1681 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001682 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001683 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001684 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001685 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001686 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001687 process_upper = (upper_special && (i & 1) == 0);
1688 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001689
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001690 if (process_upper || process_lower) {
1691 if ((process_upper && upper == 0)
1692 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001693 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001694 else if ((process_upper && upper == 0xffffffff)
1695 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001696 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001697 else if ((process_upper && upper == 0x80000000)
1698 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001699 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001700 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001701 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001702 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001703
1704 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001705 }
1706
1707 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001708 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001709 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001710 }
1711 }
1712 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001713
Dan Gohman475871a2008-07-27 21:46:04 +00001714 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001715}
1716
1717/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1718/// which the Cell can operate. The code inspects V3 to ascertain whether the
1719/// permutation vector, V3, is monotonically increasing with one "exception"
1720/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1721/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1722/// In either case, the net result is going to eventually invoke SHUFB to
1723/// permute/shuffle the bytes from V1 and V2.
1724/// \note
1725/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1726/// control word for byte/halfword/word insertion. This takes care of a single
1727/// element move from V2 into V1.
1728/// \note
1729/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001730static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1731 SDValue V1 = Op.getOperand(0);
1732 SDValue V2 = Op.getOperand(1);
1733 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001734
Scott Michel266bc8f2007-12-04 22:23:35 +00001735 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001736
Scott Michel266bc8f2007-12-04 22:23:35 +00001737 // If we have a single element being moved from V1 to V2, this can be handled
1738 // using the C*[DX] compute mask instructions, but the vector elements have
1739 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001740 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001741 unsigned EltsFromV2 = 0;
1742 unsigned V2Elt = 0;
1743 unsigned V2EltIdx0 = 0;
1744 unsigned CurrElt = 0;
1745 bool monotonic = true;
1746 if (EltVT == MVT::i8)
1747 V2EltIdx0 = 16;
1748 else if (EltVT == MVT::i16)
1749 V2EltIdx0 = 8;
1750 else if (EltVT == MVT::i32)
1751 V2EltIdx0 = 4;
1752 else
1753 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1754
1755 for (unsigned i = 0, e = PermMask.getNumOperands();
1756 EltsFromV2 <= 1 && monotonic && i != e;
1757 ++i) {
1758 unsigned SrcElt;
1759 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1760 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001761 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001762 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001763
1764 if (SrcElt >= V2EltIdx0) {
1765 ++EltsFromV2;
1766 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1767 } else if (CurrElt != SrcElt) {
1768 monotonic = false;
1769 }
1770
1771 ++CurrElt;
1772 }
1773
1774 if (EltsFromV2 == 1 && monotonic) {
1775 // Compute mask and shuffle
1776 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001777 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1778 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001779 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001780 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001781 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001782 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1783 // Copy register's contents as index in INSERT_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001784 SDValue ShufMaskOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001785 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001786 DAG.getTargetConstant(V2Elt, MVT::i32),
1787 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001788 // Use shuffle mask in SHUFB synthetic instruction:
1789 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1790 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001791 // Convert the SHUFFLE_VECTOR mask's input element units to the
1792 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001793 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001794
Dan Gohman475871a2008-07-27 21:46:04 +00001795 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001796 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1797 unsigned SrcElt;
1798 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001799 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001800 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001801 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001802
Scott Michela59d4692008-02-23 18:41:37 +00001803 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001804 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1805 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001806 }
1807 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001808
Dan Gohman475871a2008-07-27 21:46:04 +00001809 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001810 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001811 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1812 }
1813}
1814
Dan Gohman475871a2008-07-27 21:46:04 +00001815static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1816 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001817
Gabor Greifba36cb52008-08-28 21:40:38 +00001818 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001819 // For a constant, build the appropriate constant vector, which will
1820 // eventually simplify to a vector register load.
1821
Gabor Greifba36cb52008-08-28 21:40:38 +00001822 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001823 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001824 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001825 size_t n_copies;
1826
1827 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001828 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001829 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001830 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001831 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1832 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1833 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1834 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1835 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1836 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1837 }
1838
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001839 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001840 for (size_t j = 0; j < n_copies; ++j)
1841 ConstVecValues.push_back(CValue);
1842
1843 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001844 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001845 } else {
1846 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001847 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001848 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1849 case MVT::i8:
1850 case MVT::i16:
1851 case MVT::i32:
1852 case MVT::i64:
1853 case MVT::f32:
1854 case MVT::f64:
1855 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1856 }
1857 }
1858
Dan Gohman475871a2008-07-27 21:46:04 +00001859 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001860}
1861
Dan Gohman475871a2008-07-27 21:46:04 +00001862static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001863 switch (Op.getValueType().getSimpleVT()) {
1864 default:
1865 cerr << "CellSPU: Unknown vector multiplication, got "
1866 << Op.getValueType().getMVTString()
1867 << "\n";
1868 abort();
1869 /*NOTREACHED*/
1870
Scott Michel266bc8f2007-12-04 22:23:35 +00001871 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001872 SDValue rA = Op.getOperand(0);
1873 SDValue rB = Op.getOperand(1);
1874 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1875 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1876 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1877 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001878
1879 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1880 break;
1881 }
1882
1883 // Multiply two v8i16 vectors (pipeline friendly version):
1884 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1885 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1886 // c) Use SELB to select upper and lower halves from the intermediate results
1887 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001888 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001889 // dual-issue. This code does manage to do this, even if it's a little on
1890 // the wacky side
1891 case MVT::v8i16: {
1892 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001893 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001894 SDValue Chain = Op.getOperand(0);
1895 SDValue rA = Op.getOperand(0);
1896 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001897 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1898 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001899
Dan Gohman475871a2008-07-27 21:46:04 +00001900 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001901 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001902 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001903 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001904
Dan Gohman475871a2008-07-27 21:46:04 +00001905 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001906 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001907 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001908
Dan Gohman475871a2008-07-27 21:46:04 +00001909 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001910 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001911 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001912
1913 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001914 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1915 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1916 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1917 HHProd_v4i32,
1918 DAG.getConstant(16, MVT::i16))),
1919 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001920 }
1921
1922 // This M00sE is N@stI! (apologies to Monty Python)
1923 //
1924 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1925 // is to break it all apart, sign extend, and reassemble the various
1926 // intermediate products.
1927 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001928 SDValue rA = Op.getOperand(0);
1929 SDValue rB = Op.getOperand(1);
1930 SDValue c8 = DAG.getConstant(8, MVT::i32);
1931 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001932
Dan Gohman475871a2008-07-27 21:46:04 +00001933 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001934 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001935 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1936 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001937
Dan Gohman475871a2008-07-27 21:46:04 +00001938 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001939
Dan Gohman475871a2008-07-27 21:46:04 +00001940 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001941
Dan Gohman475871a2008-07-27 21:46:04 +00001942 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001943 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001944 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001945
Dan Gohman475871a2008-07-27 21:46:04 +00001946 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001947 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001948
Dan Gohman475871a2008-07-27 21:46:04 +00001949 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001950 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1951 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1952 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001953
Dan Gohman475871a2008-07-27 21:46:04 +00001954 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001955
Dan Gohman475871a2008-07-27 21:46:04 +00001956 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001957 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00001958 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001959 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1960 LoProdMask, LoProdMask,
1961 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001962
Dan Gohman475871a2008-07-27 21:46:04 +00001963 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001964 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001965 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001966
Dan Gohman475871a2008-07-27 21:46:04 +00001967 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001968 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001969 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001970
Dan Gohman475871a2008-07-27 21:46:04 +00001971 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001972 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001973 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1974 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00001975
Dan Gohman475871a2008-07-27 21:46:04 +00001976 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001977 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001978 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001979 DAG.getNode(SPUISD::VEC_SRA,
1980 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001981 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001982 DAG.getNode(SPUISD::VEC_SRA,
1983 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001984
Dan Gohman475871a2008-07-27 21:46:04 +00001985 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00001986 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1987 HLProd,
1988 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
1989 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00001990
Dan Gohman475871a2008-07-27 21:46:04 +00001991 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00001992 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001993
1994 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001995 DAG.getNode(ISD::OR, MVT::v4i32,
1996 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00001997 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001998 }
1999
Dan Gohman475871a2008-07-27 21:46:04 +00002000 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002001}
2002
Dan Gohman475871a2008-07-27 21:46:04 +00002003static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002004 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002005 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002006
Dan Gohman475871a2008-07-27 21:46:04 +00002007 SDValue A = Op.getOperand(0);
2008 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002009 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002010
2011 unsigned VRegBR, VRegC;
2012
2013 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002014 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2015 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002016 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002017 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2018 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002019 }
2020 // TODO: make sure we're feeding FPInterp the right arguments
2021 // Right now: fi B, frest(B)
2022
2023 // Computes BRcpl =
2024 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002025 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002026 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2027 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002028 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002029
Scott Michel266bc8f2007-12-04 22:23:35 +00002030 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002031 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002032 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002033 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002034 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002035 // What's the Chain variable do? It's magic!
2036 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002037
2038 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002039 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002040 DAG.getNode(ISD::FMUL, VT,
2041 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002042 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002043 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002044 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002045}
2046
Dan Gohman475871a2008-07-27 21:46:04 +00002047static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002048 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002049 SDValue N = Op.getOperand(0);
2050 SDValue Elt = Op.getOperand(1);
2051 SDValue ShufMask[16];
Scott Michel19fd42a2008-11-11 03:06:06 +00002052 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
Scott Michel266bc8f2007-12-04 22:23:35 +00002053
2054 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2055
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002056 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002057
2058 // sanity checks:
2059 if (VT == MVT::i8 && EltNo >= 16)
2060 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2061 else if (VT == MVT::i16 && EltNo >= 8)
2062 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2063 else if (VT == MVT::i32 && EltNo >= 4)
2064 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2065 else if (VT == MVT::i64 && EltNo >= 2)
2066 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2067
2068 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2069 // i32 and i64: Element 0 is the preferred slot
2070 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2071 }
2072
2073 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002074 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002075 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002076
Duncan Sands83ec4b62008-06-06 12:08:01 +00002077 switch (VT.getSimpleVT()) {
2078 default:
2079 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002080 case MVT::i8: {
2081 prefslot_begin = prefslot_end = 3;
2082 break;
2083 }
2084 case MVT::i16: {
2085 prefslot_begin = 2; prefslot_end = 3;
2086 break;
2087 }
Scott Michel73ce1c52008-11-10 23:43:06 +00002088 case MVT::i32:
2089 case MVT::f32: {
Scott Michel266bc8f2007-12-04 22:23:35 +00002090 prefslot_begin = 0; prefslot_end = 3;
2091 break;
2092 }
Scott Michel73ce1c52008-11-10 23:43:06 +00002093 case MVT::i64:
2094 case MVT::f64: {
Scott Michel266bc8f2007-12-04 22:23:35 +00002095 prefslot_begin = 0; prefslot_end = 7;
2096 break;
2097 }
2098 }
2099
Scott Michel0e5665b2007-12-19 21:17:42 +00002100 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002101 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002102
Scott Michel266bc8f2007-12-04 22:23:35 +00002103 for (int i = 0; i < 16; ++i) {
2104 // zero fill uppper part of preferred slot, don't care about the
2105 // other slots:
2106 unsigned int mask_val;
2107
2108 if (i <= prefslot_end) {
2109 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002110 ((i < prefslot_begin)
2111 ? 0x80
2112 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002113
Scott Michel0e5665b2007-12-19 21:17:42 +00002114 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002115 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002116 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2117 }
2118
Dan Gohman475871a2008-07-27 21:46:04 +00002119 SDValue ShufMaskVec =
Scott Michel266bc8f2007-12-04 22:23:35 +00002120 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002121 &ShufMask[0],
2122 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002123
2124 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002125 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2126 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002127
Scott Michel266bc8f2007-12-04 22:23:35 +00002128}
2129
Dan Gohman475871a2008-07-27 21:46:04 +00002130static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2131 SDValue VecOp = Op.getOperand(0);
2132 SDValue ValOp = Op.getOperand(1);
2133 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002134 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002135
2136 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2137 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2138
Duncan Sands83ec4b62008-06-06 12:08:01 +00002139 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002140 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002141 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002142
Dan Gohman475871a2008-07-27 21:46:04 +00002143 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002144 DAG.getNode(SPUISD::SHUFB, VT,
2145 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2146 VecOp,
2147 DAG.getNode(SPUISD::INSERT_MASK, VT,
2148 DAG.getNode(ISD::ADD, PtrVT,
2149 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002150 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002151 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002152
2153 return result;
2154}
2155
Dan Gohman475871a2008-07-27 21:46:04 +00002156static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002157{
Dan Gohman475871a2008-07-27 21:46:04 +00002158 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002159
2160 assert(Op.getValueType() == MVT::i8);
2161 switch (Opc) {
2162 default:
2163 assert(0 && "Unhandled i8 math operator");
2164 /*NOTREACHED*/
2165 break;
2166 case ISD::SUB: {
2167 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2168 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002169 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002170 N0 = (N0.getOpcode() != ISD::Constant
2171 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002172 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2173 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002174 N1 = (N1.getOpcode() != ISD::Constant
2175 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002176 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2177 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002178 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002179 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002180 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002181 case ISD::ROTR:
2182 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002183 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002184 unsigned N1Opc;
2185 N0 = (N0.getOpcode() != ISD::Constant
2186 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002187 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2188 MVT::i16));
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002189 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greif93c53e52008-08-31 15:37:04 +00002190 ? ISD::ZERO_EXTEND
2191 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002192 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002193 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002194 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002195 MVT::i32));
Dan Gohman475871a2008-07-27 21:46:04 +00002196 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002197 DAG.getNode(ISD::OR, MVT::i16, N0,
2198 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002199 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002200 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002201 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2202 }
2203 case ISD::SRL:
2204 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002205 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002206 unsigned N1Opc;
2207 N0 = (N0.getOpcode() != ISD::Constant
2208 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002209 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2210 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002211 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2212 ? ISD::ZERO_EXTEND
2213 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002214 N1 = (N1.getOpcode() != ISD::Constant
2215 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002216 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2217 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002218 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002219 DAG.getNode(Opc, MVT::i16, N0, N1));
2220 }
2221 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002222 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002223 unsigned N1Opc;
2224 N0 = (N0.getOpcode() != ISD::Constant
2225 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002226 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2227 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002228 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2229 ? ISD::SIGN_EXTEND
2230 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002231 N1 = (N1.getOpcode() != ISD::Constant
2232 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002233 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2234 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002235 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002236 DAG.getNode(Opc, MVT::i16, N0, N1));
2237 }
2238 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002239 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002240 unsigned N1Opc;
2241 N0 = (N0.getOpcode() != ISD::Constant
2242 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002243 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2244 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002245 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002246 N1 = (N1.getOpcode() != ISD::Constant
2247 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002248 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2249 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002250 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002251 DAG.getNode(Opc, MVT::i16, N0, N1));
2252 break;
2253 }
2254 }
2255
Dan Gohman475871a2008-07-27 21:46:04 +00002256 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002257}
2258
Dan Gohman475871a2008-07-27 21:46:04 +00002259static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002260{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002261 MVT VT = Op.getValueType();
2262 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002263
Dan Gohman475871a2008-07-27 21:46:04 +00002264 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002265
2266 switch (Opc) {
2267 case ISD::ZERO_EXTEND:
2268 case ISD::SIGN_EXTEND:
2269 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002270 MVT Op0VT = Op0.getValueType();
2271 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002272
2273 assert(Op0VT == MVT::i32
2274 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002275 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002276
2277 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2278 ? SPUISD::ROTBYTES_RIGHT_S
2279 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002280 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002281 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2282
2283 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2284 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2285 DAG.getNode(NewOpc, Op0VecVT,
2286 PromoteScalar,
2287 DAG.getConstant(4, MVT::i32))));
2288 }
2289
Scott Michel8bf61e82008-06-02 22:18:03 +00002290 case ISD::ADD: {
2291 // Turn operands into vectors to satisfy type checking (shufb works on
2292 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002293 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002294 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002295 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002296 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002297 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002298
2299 // Create the shuffle mask for "rotating" the borrow up one register slot
2300 // once the borrow is generated.
2301 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2302 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2303 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2304 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2305
Dan Gohman475871a2008-07-27 21:46:04 +00002306 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002307 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002308 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002309 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2310 CarryGen, CarryGen,
2311 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2312 &ShufBytes[0], ShufBytes.size()));
2313
2314 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2315 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2316 Op0, Op1, ShiftedCarry));
2317 }
2318
2319 case ISD::SUB: {
2320 // Turn operands into vectors to satisfy type checking (shufb works on
2321 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002322 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002323 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002324 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002325 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002326 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002327
2328 // Create the shuffle mask for "rotating" the borrow up one register slot
2329 // once the borrow is generated.
2330 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2331 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2332 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2333 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2334
Dan Gohman475871a2008-07-27 21:46:04 +00002335 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002336 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002337 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002338 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2339 BorrowGen, BorrowGen,
2340 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2341 &ShufBytes[0], ShufBytes.size()));
2342
2343 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2344 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2345 Op0, Op1, ShiftedBorrow));
2346 }
2347
Scott Michela59d4692008-02-23 18:41:37 +00002348 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002349 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002350 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002351 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2352 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002353 DAG.getNode(SPUISD::SELB, VecVT,
2354 Op0Vec,
2355 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002356 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002357 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002358 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002359 DAG.getNode(ISD::SRL, ShiftAmtVT,
2360 ShiftAmt,
2361 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002362 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002363 DAG.getNode(ISD::AND, ShiftAmtVT,
2364 ShiftAmt,
2365 DAG.getConstant(7, ShiftAmtVT));
2366
2367 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2368 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2369 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2370 MaskLower, ShiftAmtBytes),
2371 ShiftAmtBits));
2372 }
2373
2374 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002375 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002376 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002377 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002378 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002379 DAG.getNode(ISD::SRL, ShiftAmtVT,
2380 ShiftAmt,
2381 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002382 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002383 DAG.getNode(ISD::AND, ShiftAmtVT,
2384 ShiftAmt,
2385 DAG.getConstant(7, ShiftAmtVT));
2386
2387 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2388 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2389 Op0, ShiftAmtBytes),
2390 ShiftAmtBits);
2391 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002392
2393 case ISD::SRA: {
2394 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002395 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002396 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002397 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002398 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002399
2400 // Negate variable shift amounts
2401 if (!isa<ConstantSDNode>(ShiftAmt)) {
2402 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2403 DAG.getConstant(0, ShiftVT), ShiftAmt);
2404 }
2405
Dan Gohman475871a2008-07-27 21:46:04 +00002406 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002407 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2408 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2409 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2410 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002411 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002412 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002413 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002414 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2415 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002416 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002417 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2418 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002419 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002420 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2421 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002422 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002423 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2424 RotateLeftBytes, ShiftAmt);
2425
2426 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2427 RotateLeftBits);
2428 }
Scott Michela59d4692008-02-23 18:41:37 +00002429 }
2430
Dan Gohman475871a2008-07-27 21:46:04 +00002431 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002432}
2433
Scott Michel266bc8f2007-12-04 22:23:35 +00002434//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002435static SDValue
2436LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2437 SDValue ConstVec;
2438 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002439 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002440
2441 ConstVec = Op.getOperand(0);
2442 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002443 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2444 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002445 ConstVec = ConstVec.getOperand(0);
2446 } else {
2447 ConstVec = Op.getOperand(1);
2448 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002449 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002450 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002451 }
2452 }
2453 }
2454
Gabor Greifba36cb52008-08-28 21:40:38 +00002455 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002456 uint64_t VectorBits[2];
2457 uint64_t UndefBits[2];
2458 uint64_t SplatBits, SplatUndef;
2459 int SplatSize;
2460
Gabor Greifba36cb52008-08-28 21:40:38 +00002461 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002462 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002463 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002464 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002465 SDValue tcVec[16];
2466 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002467 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2468
2469 // Turn the BUILD_VECTOR into a set of target constants:
2470 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002471 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002472
Gabor Greifba36cb52008-08-28 21:40:38 +00002473 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002474 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002475 }
2476 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002477 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2478 // lowered. Return the operation, rather than a null SDValue.
2479 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002480}
2481
2482//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002483static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002484 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002485 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002486 default:
2487 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002488 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002489 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002490 abort();
2491 /*NOTREACHED*/
2492
2493 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002494 SDValue rA = Op.getOperand(0);
2495 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002496
2497 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002498 DAG.getNode(ISD::ADD, MVT::i32,
2499 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2500 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2501 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002502 }
2503 }
2504
Dan Gohman475871a2008-07-27 21:46:04 +00002505 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002506}
2507
2508//! Custom lowering for CTPOP (count population)
2509/*!
2510 Custom lowering code that counts the number ones in the input
2511 operand. SPU has such an instruction, but it counts the number of
2512 ones per byte, which then have to be accumulated.
2513*/
Dan Gohman475871a2008-07-27 21:46:04 +00002514static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002515 MVT VT = Op.getValueType();
2516 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002517
Duncan Sands83ec4b62008-06-06 12:08:01 +00002518 switch (VT.getSimpleVT()) {
2519 default:
2520 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002521 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002522 SDValue N = Op.getOperand(0);
2523 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002524
Dan Gohman475871a2008-07-27 21:46:04 +00002525 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2526 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002527
2528 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2529 }
2530
2531 case MVT::i16: {
2532 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002533 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002534
Chris Lattner84bc5422007-12-31 04:13:23 +00002535 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002536
Dan Gohman475871a2008-07-27 21:46:04 +00002537 SDValue N = Op.getOperand(0);
2538 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2539 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002540 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002541
Dan Gohman475871a2008-07-27 21:46:04 +00002542 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2543 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002544
2545 // CNTB_result becomes the chain to which all of the virtual registers
2546 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002547 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002548 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002549
Dan Gohman475871a2008-07-27 21:46:04 +00002550 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002551 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2552
Dan Gohman475871a2008-07-27 21:46:04 +00002553 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002554
2555 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002556 DAG.getNode(ISD::ADD, MVT::i16,
2557 DAG.getNode(ISD::SRL, MVT::i16,
2558 Tmp1, Shift1),
2559 Tmp1),
2560 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002561 }
2562
2563 case MVT::i32: {
2564 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002565 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002566
Chris Lattner84bc5422007-12-31 04:13:23 +00002567 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2568 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002569
Dan Gohman475871a2008-07-27 21:46:04 +00002570 SDValue N = Op.getOperand(0);
2571 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2572 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2573 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2574 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002575
Dan Gohman475871a2008-07-27 21:46:04 +00002576 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2577 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002578
2579 // CNTB_result becomes the chain to which all of the virtual registers
2580 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002581 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002582 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002583
Dan Gohman475871a2008-07-27 21:46:04 +00002584 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002585 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2586
Dan Gohman475871a2008-07-27 21:46:04 +00002587 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002588 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002589 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002590
Dan Gohman475871a2008-07-27 21:46:04 +00002591 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002592 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002593 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002594
Dan Gohman475871a2008-07-27 21:46:04 +00002595 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002596 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2597
Dan Gohman475871a2008-07-27 21:46:04 +00002598 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002599 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002600 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2601 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002602 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002603 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002604 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002605
2606 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2607 }
2608
2609 case MVT::i64:
2610 break;
2611 }
2612
Dan Gohman475871a2008-07-27 21:46:04 +00002613 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002614}
2615
2616/// LowerOperation - Provide custom lowering hooks for some operations.
2617///
Dan Gohman475871a2008-07-27 21:46:04 +00002618SDValue
2619SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002620{
Scott Michela59d4692008-02-23 18:41:37 +00002621 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002622 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002623
2624 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002625 default: {
2626 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002627 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002628 cerr << "*Op.getNode():\n";
2629 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002630 abort();
2631 }
2632 case ISD::LOAD:
2633 case ISD::SEXTLOAD:
2634 case ISD::ZEXTLOAD:
2635 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2636 case ISD::STORE:
2637 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2638 case ISD::ConstantPool:
2639 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2640 case ISD::GlobalAddress:
2641 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2642 case ISD::JumpTable:
2643 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2644 case ISD::Constant:
2645 return LowerConstant(Op, DAG);
2646 case ISD::ConstantFP:
2647 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002648 case ISD::BRCOND:
2649 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002650 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002651 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002652 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002653 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002654 case ISD::RET:
2655 return LowerRET(Op, DAG, getTargetMachine());
2656
Scott Michela59d4692008-02-23 18:41:37 +00002657
2658 // i8, i64 math ops:
2659 case ISD::ZERO_EXTEND:
2660 case ISD::SIGN_EXTEND:
2661 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002662 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002663 case ISD::SUB:
2664 case ISD::ROTR:
2665 case ISD::ROTL:
2666 case ISD::SRL:
2667 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002668 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002669 if (VT == MVT::i8)
2670 return LowerI8Math(Op, DAG, Opc);
2671 else if (VT == MVT::i64)
2672 return LowerI64Math(Op, DAG, Opc);
2673 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002674 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002675
2676 // Vector-related lowering.
2677 case ISD::BUILD_VECTOR:
2678 return LowerBUILD_VECTOR(Op, DAG);
2679 case ISD::SCALAR_TO_VECTOR:
2680 return LowerSCALAR_TO_VECTOR(Op, DAG);
2681 case ISD::VECTOR_SHUFFLE:
2682 return LowerVECTOR_SHUFFLE(Op, DAG);
2683 case ISD::EXTRACT_VECTOR_ELT:
2684 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2685 case ISD::INSERT_VECTOR_ELT:
2686 return LowerINSERT_VECTOR_ELT(Op, DAG);
2687
2688 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2689 case ISD::AND:
2690 case ISD::OR:
2691 case ISD::XOR:
2692 return LowerByteImmed(Op, DAG);
2693
2694 // Vector and i8 multiply:
2695 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002696 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002697 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002698 else if (VT == MVT::i8)
2699 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002700 else
Scott Michela59d4692008-02-23 18:41:37 +00002701 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002702
2703 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002704 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002705 return LowerFDIVf32(Op, DAG);
2706// else if (Op.getValueType() == MVT::f64)
2707// return LowerFDIVf64(Op, DAG);
2708 else
2709 assert(0 && "Calling FDIV on unsupported MVT");
2710
2711 case ISD::CTPOP:
2712 return LowerCTPOP(Op, DAG);
2713 }
2714
Dan Gohman475871a2008-07-27 21:46:04 +00002715 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002716}
2717
Scott Michel73ce1c52008-11-10 23:43:06 +00002718SDNode *SPUTargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG)
2719{
2720#if 0
2721 unsigned Opc = (unsigned) N->getOpcode();
2722 MVT OpVT = N->getValueType(0);
2723
2724 switch (Opc) {
2725 default: {
2726 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2727 cerr << "Op.getOpcode() = " << Opc << "\n";
2728 cerr << "*Op.getNode():\n";
2729 N->dump();
2730 abort();
2731 /*NOTREACHED*/
2732 }
2733 }
2734#endif
2735
2736 /* Otherwise, return unchanged */
2737 return 0;
2738}
2739
Scott Michel266bc8f2007-12-04 22:23:35 +00002740//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002741// Target Optimization Hooks
2742//===----------------------------------------------------------------------===//
2743
Dan Gohman475871a2008-07-27 21:46:04 +00002744SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002745SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2746{
2747#if 0
2748 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002749#endif
2750 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002751 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002752 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2753 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002754
2755 switch (N->getOpcode()) {
2756 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002757 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002758 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002759
Scott Michel8bf61e82008-06-02 22:18:03 +00002760 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002761 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002762 if (Op01.getOpcode() == ISD::Constant
2763 || Op01.getOpcode() == ISD::TargetConstant) {
2764 // (add <const>, (SPUindirect <arg>, <const>)) ->
2765 // (SPUindirect <arg>, <const + const>)
2766 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2767 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002768 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002769 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002770 Op0.getValueType());
2771
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002772 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2773 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002774 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002775 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002776 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2777 Op0.getOperand(0), combinedConst);
2778 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002779 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002780 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002781 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002782 if (Op11.getOpcode() == ISD::Constant
2783 || Op11.getOpcode() == ISD::TargetConstant) {
2784 // (add (SPUindirect <arg>, <const>), <const>) ->
2785 // (SPUindirect <arg>, <const + const>)
2786 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2787 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002788 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002789 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002790 Op0.getValueType());
2791
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002792 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2793 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002794 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002795 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002796
2797 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2798 Op1.getOperand(0), combinedConst);
2799 }
2800 }
Scott Michela59d4692008-02-23 18:41:37 +00002801 break;
2802 }
2803 case ISD::SIGN_EXTEND:
2804 case ISD::ZERO_EXTEND:
2805 case ISD::ANY_EXTEND: {
2806 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2807 N->getValueType(0) == Op0.getValueType()) {
2808 // (any_extend (SPUextract_elt0 <arg>)) ->
2809 // (SPUextract_elt0 <arg>)
2810 // Types must match, however...
2811 DEBUG(cerr << "Replace: ");
2812 DEBUG(N->dump(&DAG));
2813 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002814 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002815 DEBUG(cerr << "\n");
2816
2817 return Op0;
2818 }
2819 break;
2820 }
2821 case SPUISD::IndirectAddr: {
2822 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2823 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002824 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002825 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2826 // (SPUaform <addr>, 0)
2827
2828 DEBUG(cerr << "Replace: ");
2829 DEBUG(N->dump(&DAG));
2830 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002831 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002832 DEBUG(cerr << "\n");
2833
2834 return Op0;
2835 }
2836 }
2837 break;
2838 }
2839 case SPUISD::SHLQUAD_L_BITS:
2840 case SPUISD::SHLQUAD_L_BYTES:
2841 case SPUISD::VEC_SHL:
2842 case SPUISD::VEC_SRL:
2843 case SPUISD::VEC_SRA:
2844 case SPUISD::ROTQUAD_RZ_BYTES:
2845 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002846 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002847
2848 if (isa<ConstantSDNode>(Op1)) {
2849 // Kill degenerate vector shifts:
2850 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2851
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002852 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002853 Result = Op0;
2854 }
2855 }
2856 break;
2857 }
2858 case SPUISD::PROMOTE_SCALAR: {
2859 switch (Op0.getOpcode()) {
2860 default:
2861 break;
2862 case ISD::ANY_EXTEND:
2863 case ISD::ZERO_EXTEND:
2864 case ISD::SIGN_EXTEND: {
2865 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2866 // <arg>
2867 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002868 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002869 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00002870 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002871 if (Op000.getValueType() == N->getValueType(0)) {
2872 Result = Op000;
2873 }
2874 }
2875 break;
2876 }
2877 case SPUISD::EXTRACT_ELT0: {
2878 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2879 // <arg>
2880 Result = Op0.getOperand(0);
2881 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002882 }
Scott Michela59d4692008-02-23 18:41:37 +00002883 }
2884 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002885 }
2886 }
Scott Michel58c58182008-01-17 20:38:41 +00002887 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002888#if 1
Gabor Greifba36cb52008-08-28 21:40:38 +00002889 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00002890 DEBUG(cerr << "\nReplace.SPU: ");
2891 DEBUG(N->dump(&DAG));
2892 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002893 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002894 DEBUG(cerr << "\n");
2895 }
2896#endif
2897
2898 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002899}
2900
2901//===----------------------------------------------------------------------===//
2902// Inline Assembly Support
2903//===----------------------------------------------------------------------===//
2904
2905/// getConstraintType - Given a constraint letter, return the type of
2906/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002907SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002908SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2909 if (ConstraintLetter.size() == 1) {
2910 switch (ConstraintLetter[0]) {
2911 default: break;
2912 case 'b':
2913 case 'r':
2914 case 'f':
2915 case 'v':
2916 case 'y':
2917 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002918 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002919 }
2920 return TargetLowering::getConstraintType(ConstraintLetter);
2921}
2922
Scott Michel5af8f0e2008-07-16 17:17:29 +00002923std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002924SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002925 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002926{
2927 if (Constraint.size() == 1) {
2928 // GCC RS6000 Constraint Letters
2929 switch (Constraint[0]) {
2930 case 'b': // R1-R31
2931 case 'r': // R0-R31
2932 if (VT == MVT::i64)
2933 return std::make_pair(0U, SPU::R64CRegisterClass);
2934 return std::make_pair(0U, SPU::R32CRegisterClass);
2935 case 'f':
2936 if (VT == MVT::f32)
2937 return std::make_pair(0U, SPU::R32FPRegisterClass);
2938 else if (VT == MVT::f64)
2939 return std::make_pair(0U, SPU::R64FPRegisterClass);
2940 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002941 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002942 return std::make_pair(0U, SPU::GPRCRegisterClass);
2943 }
2944 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002945
Scott Michel266bc8f2007-12-04 22:23:35 +00002946 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2947}
2948
Scott Michela59d4692008-02-23 18:41:37 +00002949//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002950void
Dan Gohman475871a2008-07-27 21:46:04 +00002951SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002952 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002953 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002954 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002955 const SelectionDAG &DAG,
2956 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002957#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002958 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002959#endif
Scott Michela59d4692008-02-23 18:41:37 +00002960
2961 switch (Op.getOpcode()) {
2962 default:
2963 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2964 break;
2965
2966#if 0
2967 case CALL:
2968 case SHUFB:
2969 case INSERT_MASK:
2970 case CNTB:
2971#endif
2972
2973 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00002974 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002975 MVT Op0VT = Op0.getValueType();
2976 unsigned Op0VTBits = Op0VT.getSizeInBits();
2977 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002978 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2979 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002980 break;
2981 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002982
Scott Michela59d4692008-02-23 18:41:37 +00002983 case SPUISD::LDRESULT:
2984 case SPUISD::EXTRACT_ELT0:
2985 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002986 MVT OpVT = Op.getValueType();
2987 unsigned OpVTBits = OpVT.getSizeInBits();
2988 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002989 KnownZero |= APInt(OpVTBits, ~InMask, false);
2990 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002991 break;
2992 }
2993
2994#if 0
2995 case EXTRACT_I1_ZEXT:
2996 case EXTRACT_I1_SEXT:
2997 case EXTRACT_I8_ZEXT:
2998 case EXTRACT_I8_SEXT:
2999 case MPY:
3000 case MPYU:
3001 case MPYH:
3002 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003003 case SPUISD::SHLQUAD_L_BITS:
3004 case SPUISD::SHLQUAD_L_BYTES:
3005 case SPUISD::VEC_SHL:
3006 case SPUISD::VEC_SRL:
3007 case SPUISD::VEC_SRA:
3008 case SPUISD::VEC_ROTL:
3009 case SPUISD::VEC_ROTR:
3010 case SPUISD::ROTQUAD_RZ_BYTES:
3011 case SPUISD::ROTQUAD_RZ_BITS:
3012 case SPUISD::ROTBYTES_RIGHT_S:
3013 case SPUISD::ROTBYTES_LEFT:
3014 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003015 case SPUISD::SELECT_MASK:
3016 case SPUISD::SELB:
3017 case SPUISD::FPInterp:
3018 case SPUISD::FPRecipEst:
3019 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003020#endif
3021 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003022}
3023
Scott Michel203b2d62008-04-30 00:30:08 +00003024// LowerAsmOperandForConstraint
3025void
Dan Gohman475871a2008-07-27 21:46:04 +00003026SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003027 char ConstraintLetter,
Evan Chengda43bcf2008-09-24 00:05:32 +00003028 bool hasMemory,
Dan Gohman475871a2008-07-27 21:46:04 +00003029 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003030 SelectionDAG &DAG) const {
3031 // Default, for the time being, to the base class handler
Evan Chengda43bcf2008-09-24 00:05:32 +00003032 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3033 Ops, DAG);
Scott Michel203b2d62008-04-30 00:30:08 +00003034}
3035
Scott Michel266bc8f2007-12-04 22:23:35 +00003036/// isLegalAddressImmediate - Return true if the integer value can be used
3037/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003038bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3039 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003040 // SPU's addresses are 256K:
3041 return (V > -(1 << 18) && V < (1 << 18) - 1);
3042}
3043
3044bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003045 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003046}
Dan Gohman6520e202008-10-18 02:06:02 +00003047
3048bool
3049SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3050 // The SPU target isn't yet aware of offsets.
3051 return false;
3052}