blob: ab64aae9262dd680ddec5f8c1e5ebc2bbcec0c0c [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:
Scott Michel58c58182008-01-17 20:38:41 +0000134 setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +0000135 setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote);
136 setLoadXAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Chris Lattnerddf89562008-01-17 19:59:44 +0000137 setTruncStoreAction(MVT::i8, MVT::i1, Custom);
138 setTruncStoreAction(MVT::i16, MVT::i1, Custom);
139 setTruncStoreAction(MVT::i32, MVT::i1, Custom);
140 setTruncStoreAction(MVT::i64, MVT::i1, Custom);
141 setTruncStoreAction(MVT::i128, MVT::i1, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000142
143 setLoadXAction(ISD::EXTLOAD, MVT::i8, Custom);
144 setLoadXAction(ISD::SEXTLOAD, MVT::i8, Custom);
145 setLoadXAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Chris Lattnerddf89562008-01-17 19:59:44 +0000146 setTruncStoreAction(MVT::i8 , MVT::i8, Custom);
147 setTruncStoreAction(MVT::i16 , MVT::i8, Custom);
148 setTruncStoreAction(MVT::i32 , MVT::i8, Custom);
149 setTruncStoreAction(MVT::i64 , MVT::i8, Custom);
150 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000151
Scott Michel266bc8f2007-12-04 22:23:35 +0000152 setLoadXAction(ISD::EXTLOAD, MVT::i16, Custom);
153 setLoadXAction(ISD::SEXTLOAD, MVT::i16, Custom);
154 setLoadXAction(ISD::ZEXTLOAD, MVT::i16, Custom);
155
156 // SPU constant load actions are custom lowered:
157 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begemanccef5802008-02-14 18:43:04 +0000158 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000159 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
160
161 // SPU's loads and stores have to be custom lowered:
162 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
163 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000164 MVT VT = (MVT::SimpleValueType)sctype;
165
166 setOperationAction(ISD::LOAD, VT, Custom);
167 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000168 }
169
Scott Michel58c58182008-01-17 20:38:41 +0000170 // Custom lower BRCOND for i1, i8 to "promote" the result to
171 // i32 and i16, respectively.
172 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000173
174 // Expand the jumptable branches
175 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
176 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000177 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000178
179 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000180 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
181
Scott Michel266bc8f2007-12-04 22:23:35 +0000182 // PowerPC has no SREM/UREM instructions
183 setOperationAction(ISD::SREM, MVT::i32, Expand);
184 setOperationAction(ISD::UREM, MVT::i32, Expand);
185 setOperationAction(ISD::SREM, MVT::i64, Expand);
186 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000187
Scott Michel266bc8f2007-12-04 22:23:35 +0000188 // We don't support sin/cos/sqrt/fmod
189 setOperationAction(ISD::FSIN , MVT::f64, Expand);
190 setOperationAction(ISD::FCOS , MVT::f64, Expand);
191 setOperationAction(ISD::FREM , MVT::f64, Expand);
192 setOperationAction(ISD::FSIN , MVT::f32, Expand);
193 setOperationAction(ISD::FCOS , MVT::f32, Expand);
194 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000195
Scott Michel266bc8f2007-12-04 22:23:35 +0000196 // If we're enabling GP optimizations, use hardware square root
197 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
198 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000199
Scott Michel266bc8f2007-12-04 22:23:35 +0000200 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
201 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
202
203 // SPU can do rotate right and left, so legalize it... but customize for i8
204 // because instructions don't exist.
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();
463 if (VT.isInteger())
Scott Michel405fba12008-03-10 23:49:09 +0000464 return VT;
465 else
466 return MVT::i32;
Scott Michel78c47fa2008-03-10 16:58:52 +0000467}
468
Scott Michel266bc8f2007-12-04 22:23:35 +0000469//===----------------------------------------------------------------------===//
470// Calling convention code:
471//===----------------------------------------------------------------------===//
472
473#include "SPUGenCallingConv.inc"
474
475//===----------------------------------------------------------------------===//
476// LowerOperation implementation
477//===----------------------------------------------------------------------===//
478
Scott Michel9de5d0d2008-01-11 02:53:15 +0000479/// Aligned load common code for CellSPU
480/*!
481 \param[in] Op The SelectionDAG load or store operand
482 \param[in] DAG The selection DAG
483 \param[in] ST CellSPU subtarget information structure
484 \param[in,out] alignment Caller initializes this to the load or store node's
485 value from getAlignment(), may be updated while generating the aligned load
486 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
487 offset (divisible by 16, modulo 16 == 0)
488 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
489 offset of the preferred slot (modulo 16 != 0)
490 \param[in,out] VT Caller initializes this value type to the the load or store
491 node's loaded or stored value type; may be updated if an i1-extended load or
492 store.
493 \param[out] was16aligned true if the base pointer had 16-byte alignment,
494 otherwise false. Can help to determine if the chunk needs to be rotated.
495
496 Both load and store lowering load a block of data aligned on a 16-byte
497 boundary. This is the common aligned load code shared between both.
498 */
Dan Gohman475871a2008-07-27 21:46:04 +0000499static SDValue
500AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Michel9de5d0d2008-01-11 02:53:15 +0000501 LSBaseSDNode *LSN,
502 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000503 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000504{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000505 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000506 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman475871a2008-07-27 21:46:04 +0000507 SDValue basePtr = LSN->getBasePtr();
508 SDValue chain = LSN->getChain();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000509
510 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000511 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000512
Gabor Greif93c53e52008-08-31 15:37:04 +0000513 if (Op1.getOpcode() == ISD::Constant
514 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000515 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000516
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000517 alignOffs = (int) CN->getZExtValue();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000518 prefSlotOffs = (int) (alignOffs & 0xf);
519
520 // Adjust the rotation amount to ensure that the final result ends up in
521 // the preferred slot:
522 prefSlotOffs -= vtm->prefslot_byte;
523 basePtr = basePtr.getOperand(0);
524
Scott Michel58c58182008-01-17 20:38:41 +0000525 // Loading from memory, can we adjust alignment?
526 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +0000527 SDValue APtr = basePtr.getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000528 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
529 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
530 alignment = GSDN->getGlobal()->getAlignment();
531 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000532 }
533 } else {
534 alignOffs = 0;
535 prefSlotOffs = -vtm->prefslot_byte;
536 }
Scott Michel203b2d62008-04-30 00:30:08 +0000537 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
538 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
539 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
540 prefSlotOffs = (int) (alignOffs & 0xf);
541 prefSlotOffs -= vtm->prefslot_byte;
542 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000543 } else {
544 alignOffs = 0;
545 prefSlotOffs = -vtm->prefslot_byte;
546 }
547
548 if (alignment == 16) {
549 // Realign the base pointer as a D-Form address:
550 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000551 basePtr = DAG.getNode(ISD::ADD, PtrVT,
552 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000553 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000554 }
555
556 // Emit the vector load:
557 was16aligned = true;
558 return DAG.getLoad(MVT::v16i8, chain, basePtr,
559 LSN->getSrcValue(), LSN->getSrcValueOffset(),
560 LSN->isVolatile(), 16);
561 }
562
563 // Unaligned load or we're using the "large memory" model, which means that
564 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000565 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greif93c53e52008-08-31 15:37:04 +0000566 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
567 DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000568 }
569
570 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000571 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000572 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000573 was16aligned = false;
574 return DAG.getLoad(MVT::v16i8, chain, basePtr,
575 LSN->getSrcValue(), LSN->getSrcValueOffset(),
576 LSN->isVolatile(), 16);
577}
578
Scott Michel266bc8f2007-12-04 22:23:35 +0000579/// Custom lower loads for CellSPU
580/*!
581 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
582 within a 16-byte block, we have to rotate to extract the requested element.
583 */
Dan Gohman475871a2008-07-27 21:46:04 +0000584static SDValue
585LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000586 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000587 SDValue the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000588 MVT VT = LN->getMemoryVT();
Gabor Greifba36cb52008-08-28 21:40:38 +0000589 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000590 ISD::LoadExtType ExtType = LN->getExtensionType();
591 unsigned alignment = LN->getAlignment();
Dan Gohman475871a2008-07-27 21:46:04 +0000592 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000593
Scott Michel266bc8f2007-12-04 22:23:35 +0000594 switch (LN->getAddressingMode()) {
595 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000596 int offset, rotamt;
597 bool was16aligned;
Dan Gohman475871a2008-07-27 21:46:04 +0000598 SDValue result =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000599 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000600
Gabor Greifba36cb52008-08-28 21:40:38 +0000601 if (result.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000602 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000603
604 the_chain = result.getValue(1);
605 // Rotate the chunk if necessary
606 if (rotamt < 0)
607 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000608 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000609 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
610
Scott Michel58c58182008-01-17 20:38:41 +0000611 Ops[0] = the_chain;
612 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000613 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000614 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
615 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000616 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000617 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000618 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000619 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000620 }
621
622 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
623 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000624 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000625
626 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
627 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000628 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000629
Scott Michel9de5d0d2008-01-11 02:53:15 +0000630 // Convert the loaded v16i8 vector to the appropriate vector type
631 // specified by the operand:
632 if (OpVT == VT) {
633 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000634 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000635 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000636 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000637
638 Ops[0] = the_chain;
639 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
640 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
641 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
642 the_chain = result.getValue(1);
643 } else {
644 // Handle the sign and zero-extending loads for i1 and i8:
645 unsigned NewOpC;
646
647 if (ExtType == ISD::SEXTLOAD) {
648 NewOpC = (OpVT == MVT::i1
649 ? SPUISD::EXTRACT_I1_SEXT
650 : SPUISD::EXTRACT_I8_SEXT);
651 } else {
652 assert(ExtType == ISD::ZEXTLOAD);
653 NewOpC = (OpVT == MVT::i1
654 ? SPUISD::EXTRACT_I1_ZEXT
655 : SPUISD::EXTRACT_I8_ZEXT);
656 }
657
658 result = DAG.getNode(NewOpC, OpVT, result);
659 }
660
661 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000662 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000663 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000664 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000665 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000666
Scott Michel58c58182008-01-17 20:38:41 +0000667 result = DAG.getNode(SPUISD::LDRESULT, retvts,
668 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000669 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000670 }
671 case ISD::PRE_INC:
672 case ISD::PRE_DEC:
673 case ISD::POST_INC:
674 case ISD::POST_DEC:
675 case ISD::LAST_INDEXED_MODE:
676 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
677 "UNINDEXED\n";
678 cerr << (unsigned) LN->getAddressingMode() << "\n";
679 abort();
680 /*NOTREACHED*/
681 }
682
Dan Gohman475871a2008-07-27 21:46:04 +0000683 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000684}
685
686/// Custom lower stores for CellSPU
687/*!
688 All CellSPU stores are aligned to 16-byte boundaries, so for elements
689 within a 16-byte block, we have to generate a shuffle to insert the
690 requested element into its place, then store the resulting block.
691 */
Dan Gohman475871a2008-07-27 21:46:04 +0000692static SDValue
693LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000694 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000695 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000696 MVT VT = Value.getValueType();
697 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
698 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000699 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000700
701 switch (SN->getAddressingMode()) {
702 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000703 int chunk_offset, slot_offset;
704 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000705
706 // The vector type we really want to load from the 16-byte chunk, except
707 // in the case of MVT::i1, which has to be v16i8.
Duncan Sands83ec4b62008-06-06 12:08:01 +0000708 MVT vecVT, stVecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000709
Scott Michel266bc8f2007-12-04 22:23:35 +0000710 if (StVT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000711 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
712 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000713
Dan Gohman475871a2008-07-27 21:46:04 +0000714 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000715 AlignedLoad(Op, DAG, ST, SN, alignment,
716 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000717
Gabor Greifba36cb52008-08-28 21:40:38 +0000718 if (alignLoadVec.getNode() == 0)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000719 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000720
Scott Michel9de5d0d2008-01-11 02:53:15 +0000721 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000722 SDValue basePtr = LN->getBasePtr();
723 SDValue the_chain = alignLoadVec.getValue(1);
724 SDValue theValue = SN->getValue();
725 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000726
727 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000728 && (theValue.getOpcode() == ISD::AssertZext
729 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000730 // Drill down and get the value for zero- and sign-extended
731 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000732 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000733 }
734
Scott Michel9de5d0d2008-01-11 02:53:15 +0000735 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000736
Dan Gohman475871a2008-07-27 21:46:04 +0000737 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
738 SDValue insertEltPtr;
739 SDValue insertEltOp;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000740
741 // If the base pointer is already a D-form address, then just create
742 // a new D-form address with a slot offset and the orignal base pointer.
743 // Otherwise generate a D-form address with the slot offset relative
744 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000745 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greifba36cb52008-08-28 21:40:38 +0000746 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michel497e8882008-01-11 21:01:19 +0000747 DEBUG(cerr << "\n");
748
Scott Michel053c1da2008-01-29 02:16:57 +0000749 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
750 (basePtr.getOpcode() == ISD::ADD
751 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000752 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000753 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000754 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000755 }
756
757 insertEltOp = DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000758 result = DAG.getNode(SPUISD::SHUFB, vecVT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000759 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue),
760 alignLoadVec,
761 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000762
Scott Michel9de5d0d2008-01-11 02:53:15 +0000763 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000764 LN->getSrcValue(), LN->getSrcValueOffset(),
765 LN->isVolatile(), LN->getAlignment());
766
767 return result;
768 /*UNREACHED*/
769 }
770 case ISD::PRE_INC:
771 case ISD::PRE_DEC:
772 case ISD::POST_INC:
773 case ISD::POST_DEC:
774 case ISD::LAST_INDEXED_MODE:
775 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
776 "UNINDEXED\n";
777 cerr << (unsigned) SN->getAddressingMode() << "\n";
778 abort();
779 /*NOTREACHED*/
780 }
781
Dan Gohman475871a2008-07-27 21:46:04 +0000782 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000783}
784
785/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000786static SDValue
787LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000788 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000789 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
790 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000791 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
792 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000793 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000794
795 if (TM.getRelocationModel() == Reloc::Static) {
796 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000797 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000798 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000799 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000800 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
801 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000802 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000803 }
804 }
805
806 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000807 "LowerConstantPool: Relocation model other than static"
808 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000809 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000810}
811
Dan Gohman475871a2008-07-27 21:46:04 +0000812static SDValue
813LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000814 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000815 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000816 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
817 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000818 const TargetMachine &TM = DAG.getTarget();
819
820 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000821 if (!ST->usingLargeMem()) {
822 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
823 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000824 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
825 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000826 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
827 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000828 }
829
830 assert(0 &&
831 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000832 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000833}
834
Dan Gohman475871a2008-07-27 21:46:04 +0000835static SDValue
836LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000837 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000838 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
839 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000840 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000841 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000842 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000843
Scott Michel266bc8f2007-12-04 22:23:35 +0000844 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000845 if (!ST->usingLargeMem()) {
846 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
847 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000848 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
849 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000850 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
851 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000852 } else {
853 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000854 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000855 abort();
856 /*NOTREACHED*/
857 }
858
Dan Gohman475871a2008-07-27 21:46:04 +0000859 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000860}
861
862//! Custom lower i64 integer constants
863/*!
864 This code inserts all of the necessary juggling that needs to occur to load
865 a 64-bit constant into a register.
866 */
Dan Gohman475871a2008-07-27 21:46:04 +0000867static SDValue
868LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000869 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000870 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000871
872 if (VT == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000873 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +0000874 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000875 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000876 } else {
877 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000878 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000879 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000880 abort();
881 /*NOTREACHED*/
882 }
883
Dan Gohman475871a2008-07-27 21:46:04 +0000884 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000885}
886
Nate Begemanccef5802008-02-14 18:43:04 +0000887//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000888static SDValue
889LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000890 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000891 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000892
893 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000894 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000895
Nate Begemanccef5802008-02-14 18:43:04 +0000896 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000897 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000898 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000899 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000900 }
901
Dan Gohman475871a2008-07-27 21:46:04 +0000902 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000903}
904
Scott Michel58c58182008-01-17 20:38:41 +0000905//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000906static SDValue
907LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000908{
Dan Gohman475871a2008-07-27 21:46:04 +0000909 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000910 MVT CondVT = Cond.getValueType();
911 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000912
913 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
914 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
915 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
916 Op.getOperand(0),
917 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
918 Op.getOperand(2));
919 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000920 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000921}
922
Dan Gohman475871a2008-07-27 21:46:04 +0000923static SDValue
924LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000925{
926 MachineFunction &MF = DAG.getMachineFunction();
927 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000928 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +0000929 SmallVector<SDValue, 8> ArgValues;
930 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000931 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000932
933 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
934 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000935
Scott Michel266bc8f2007-12-04 22:23:35 +0000936 unsigned ArgOffset = SPUFrameInfo::minStackSize();
937 unsigned ArgRegIdx = 0;
938 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000939
Duncan Sands83ec4b62008-06-06 12:08:01 +0000940 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000941
Scott Michel266bc8f2007-12-04 22:23:35 +0000942 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000943 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
944 ArgNo != e; ++ArgNo) {
Dan Gohman475871a2008-07-27 21:46:04 +0000945 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000946 bool needsLoad = false;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000947 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
948 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michel266bc8f2007-12-04 22:23:35 +0000949
Duncan Sands83ec4b62008-06-06 12:08:01 +0000950 switch (ObjectVT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000951 default: {
952 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000953 << ObjectVT.getMVTString()
Scott Michel266bc8f2007-12-04 22:23:35 +0000954 << "\n";
955 abort();
956 }
957 case MVT::i8:
958 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000959 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R8CRegClass);
960 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000961 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i8);
962 ++ArgRegIdx;
963 } else {
964 needsLoad = true;
965 }
966 break;
967 case MVT::i16:
968 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000969 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
970 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000971 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i16);
972 ++ArgRegIdx;
973 } else {
974 needsLoad = true;
975 }
976 break;
977 case MVT::i32:
978 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000979 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
980 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000981 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
982 ++ArgRegIdx;
983 } else {
984 needsLoad = true;
985 }
986 break;
987 case MVT::i64:
988 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000989 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64CRegClass);
990 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000991 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64);
992 ++ArgRegIdx;
993 } else {
994 needsLoad = true;
995 }
996 break;
997 case MVT::f32:
998 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000999 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
1000 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001001 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f32);
1002 ++ArgRegIdx;
1003 } else {
1004 needsLoad = true;
1005 }
1006 break;
1007 case MVT::f64:
1008 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001009 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64FPRegClass);
1010 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001011 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f64);
1012 ++ArgRegIdx;
1013 } else {
1014 needsLoad = true;
1015 }
1016 break;
1017 case MVT::v2f64:
1018 case MVT::v4f32:
Scott Michelad2715e2008-03-05 23:02:02 +00001019 case MVT::v2i64:
Scott Michel266bc8f2007-12-04 22:23:35 +00001020 case MVT::v4i32:
1021 case MVT::v8i16:
1022 case MVT::v16i8:
1023 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001024 unsigned VReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1025 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001026 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1027 ++ArgRegIdx;
1028 } else {
1029 needsLoad = true;
1030 }
1031 break;
1032 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001033
Scott Michel266bc8f2007-12-04 22:23:35 +00001034 // We need to load the argument to a virtual register if we determined above
1035 // that we ran out of physical registers of the appropriate type
1036 if (needsLoad) {
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001037 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001038 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001039 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001040 ArgOffset += StackSlotSize;
1041 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001042
Scott Michel266bc8f2007-12-04 22:23:35 +00001043 ArgValues.push_back(ArgVal);
1044 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001045
Scott Michel266bc8f2007-12-04 22:23:35 +00001046 // If the function takes variable number of arguments, make a frame index for
1047 // the start of the first vararg value... for expansion of llvm.va_start.
1048 if (isVarArg) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001049 VarArgsFrameIndex = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8,
Scott Michel266bc8f2007-12-04 22:23:35 +00001050 ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001051 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001052 // If this function is vararg, store any remaining integer argument regs to
1053 // their spots on the stack so that they may be loaded by deferencing the
1054 // result of va_next.
Dan Gohman475871a2008-07-27 21:46:04 +00001055 SmallVector<SDValue, 8> MemOps;
Scott Michel266bc8f2007-12-04 22:23:35 +00001056 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001057 unsigned VReg = RegInfo.createVirtualRegister(&SPU::GPRCRegClass);
1058 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Dan Gohman475871a2008-07-27 21:46:04 +00001059 SDValue Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
1060 SDValue Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001061 MemOps.push_back(Store);
1062 // Increment the address by four for the next argument to store
Dan Gohman475871a2008-07-27 21:46:04 +00001063 SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001064 FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
1065 }
1066 if (!MemOps.empty())
1067 Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
1068 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001069
Scott Michel266bc8f2007-12-04 22:23:35 +00001070 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001071
Scott Michel266bc8f2007-12-04 22:23:35 +00001072 // Return the new list of results.
Gabor Greifba36cb52008-08-28 21:40:38 +00001073 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf9516202008-06-30 10:19:09 +00001074 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001075}
1076
1077/// isLSAAddress - Return the immediate to use if the specified
1078/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001079static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001080 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
1081 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001082
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001083 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001084 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1085 (Addr << 14 >> 14) != Addr)
1086 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001087
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001088 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001089}
1090
1091static
Dan Gohman475871a2008-07-27 21:46:04 +00001092SDValue
1093LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman095cc292008-09-13 01:54:27 +00001094 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1095 SDValue Chain = TheCall->getChain();
Scott Michel266bc8f2007-12-04 22:23:35 +00001096#if 0
Dan Gohman095cc292008-09-13 01:54:27 +00001097 bool isVarArg = TheCall->isVarArg();
1098 bool isTailCall = TheCall->isTailCall();
Scott Michel266bc8f2007-12-04 22:23:35 +00001099#endif
Dan Gohman095cc292008-09-13 01:54:27 +00001100 SDValue Callee = TheCall->getCallee();
1101 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001102 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1103 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1104 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1105
1106 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001107 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001108
Scott Michel266bc8f2007-12-04 22:23:35 +00001109 // Accumulate how many bytes are to be pushed on the stack, including the
1110 // linkage area, and parameter passing area. According to the SPU ABI,
1111 // we minimally need space for [LR] and [SP]
1112 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001113
Scott Michel266bc8f2007-12-04 22:23:35 +00001114 // Set up a copy of the stack pointer for use loading and storing any
1115 // arguments that may not fit in the registers available for argument
1116 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001117 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001118
Scott Michel266bc8f2007-12-04 22:23:35 +00001119 // Figure out which arguments are going to go in registers, and which in
1120 // memory.
1121 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1122 unsigned ArgRegIdx = 0;
1123
1124 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001125 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001126 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001127 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001128
1129 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001130 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001131
Scott Michel266bc8f2007-12-04 22:23:35 +00001132 // PtrOff will be used to store the current argument to the stack if a
1133 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001134 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001135 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1136
Duncan Sands83ec4b62008-06-06 12:08:01 +00001137 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001138 default: assert(0 && "Unexpected ValueType for argument!");
1139 case MVT::i32:
1140 case MVT::i64:
1141 case MVT::i128:
1142 if (ArgRegIdx != NumArgRegs) {
1143 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1144 } else {
1145 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001146 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001147 }
1148 break;
1149 case MVT::f32:
1150 case MVT::f64:
1151 if (ArgRegIdx != NumArgRegs) {
1152 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1153 } else {
1154 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001155 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001156 }
1157 break;
1158 case MVT::v4f32:
1159 case MVT::v4i32:
1160 case MVT::v8i16:
1161 case MVT::v16i8:
1162 if (ArgRegIdx != NumArgRegs) {
1163 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1164 } else {
1165 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001166 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001167 }
1168 break;
1169 }
1170 }
1171
1172 // Update number of stack bytes actually used, insert a call sequence start
1173 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
1174 Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumStackBytes, PtrVT));
1175
1176 if (!MemOpChains.empty()) {
1177 // Adjust the stack pointer for the stack arguments.
1178 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1179 &MemOpChains[0], MemOpChains.size());
1180 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001181
Scott Michel266bc8f2007-12-04 22:23:35 +00001182 // Build a sequence of copy-to-reg nodes chained together with token chain
1183 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001184 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001185 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1186 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1187 InFlag);
1188 InFlag = Chain.getValue(1);
1189 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001190
Dan Gohman475871a2008-07-27 21:46:04 +00001191 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001192 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001193
Bill Wendling056292f2008-09-16 21:48:12 +00001194 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1195 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1196 // node so that legalize doesn't hack it.
Scott Michel266bc8f2007-12-04 22:23:35 +00001197 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1198 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001199 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001200 SDValue Zero = DAG.getConstant(0, PtrVT);
1201 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001202
Scott Michel9de5d0d2008-01-11 02:53:15 +00001203 if (!ST->usingLargeMem()) {
1204 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1205 // style calls, otherwise, external symbols are BRASL calls. This assumes
1206 // that declared/defined symbols are in the same compilation unit and can
1207 // be reached through PC-relative jumps.
1208 //
1209 // NOTE:
1210 // This may be an unsafe assumption for JIT and really large compilation
1211 // units.
1212 if (GV->isDeclaration()) {
1213 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1214 } else {
1215 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1216 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001217 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001218 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1219 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001220 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001221 }
Bill Wendling056292f2008-09-16 21:48:12 +00001222 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
1223 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001224 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001225 // If this is an absolute destination address that appears to be a legal
1226 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001227 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001228 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001229
1230 Ops.push_back(Chain);
1231 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001232
Scott Michel266bc8f2007-12-04 22:23:35 +00001233 // Add argument registers to the end of the list so that they are known live
1234 // into the call.
1235 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001236 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001237 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001238
Gabor Greifba36cb52008-08-28 21:40:38 +00001239 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001240 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001241 // Returns a chain and a flag for retval copy to use.
1242 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1243 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001244 InFlag = Chain.getValue(1);
1245
Evan Chengebaaa912008-02-05 22:44:06 +00001246 Chain = DAG.getCALLSEQ_END(Chain,
1247 DAG.getConstant(NumStackBytes, PtrVT),
1248 DAG.getConstant(0, PtrVT),
1249 InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001250 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001251 InFlag = Chain.getValue(1);
1252
Dan Gohman475871a2008-07-27 21:46:04 +00001253 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001254 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001255
Scott Michel266bc8f2007-12-04 22:23:35 +00001256 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001257 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001258 default: assert(0 && "Unexpected ret value!");
1259 case MVT::Other: break;
1260 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001261 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001262 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1263 ResultVals[0] = Chain.getValue(0);
1264 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1265 Chain.getValue(2)).getValue(1);
1266 ResultVals[1] = Chain.getValue(0);
1267 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001268 } else {
1269 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1270 ResultVals[0] = Chain.getValue(0);
1271 NumResults = 1;
1272 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001273 break;
1274 case MVT::i64:
1275 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1276 ResultVals[0] = Chain.getValue(0);
1277 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001278 break;
1279 case MVT::f32:
1280 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001281 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001282 InFlag).getValue(1);
1283 ResultVals[0] = Chain.getValue(0);
1284 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001285 break;
1286 case MVT::v2f64:
1287 case MVT::v4f32:
1288 case MVT::v4i32:
1289 case MVT::v8i16:
1290 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001291 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001292 InFlag).getValue(1);
1293 ResultVals[0] = Chain.getValue(0);
1294 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001295 break;
1296 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001297
Scott Michel266bc8f2007-12-04 22:23:35 +00001298 // If the function returns void, just return the chain.
1299 if (NumResults == 0)
1300 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001301
Scott Michel266bc8f2007-12-04 22:23:35 +00001302 // Otherwise, merge everything together with a MERGE_VALUES node.
1303 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001304 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001305 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001306}
1307
Dan Gohman475871a2008-07-27 21:46:04 +00001308static SDValue
1309LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001310 SmallVector<CCValAssign, 16> RVLocs;
1311 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1312 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1313 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001314 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001315
Scott Michel266bc8f2007-12-04 22:23:35 +00001316 // If this is the first return lowered for this function, add the regs to the
1317 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001318 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001319 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001320 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001321 }
1322
Dan Gohman475871a2008-07-27 21:46:04 +00001323 SDValue Chain = Op.getOperand(0);
1324 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001325
Scott Michel266bc8f2007-12-04 22:23:35 +00001326 // Copy the result values into the output registers.
1327 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1328 CCValAssign &VA = RVLocs[i];
1329 assert(VA.isRegLoc() && "Can only return in registers!");
1330 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1331 Flag = Chain.getValue(1);
1332 }
1333
Gabor Greifba36cb52008-08-28 21:40:38 +00001334 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001335 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1336 else
1337 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1338}
1339
1340
1341//===----------------------------------------------------------------------===//
1342// Vector related lowering:
1343//===----------------------------------------------------------------------===//
1344
1345static ConstantSDNode *
1346getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001347 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001348
Scott Michel266bc8f2007-12-04 22:23:35 +00001349 // Check to see if this buildvec has a single non-undef value in its elements.
1350 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1351 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001352 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001353 OpVal = N->getOperand(i);
1354 else if (OpVal != N->getOperand(i))
1355 return 0;
1356 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001357
Gabor Greifba36cb52008-08-28 21:40:38 +00001358 if (OpVal.getNode() != 0) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001359 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1360 return CN;
1361 }
1362 }
1363
1364 return 0; // All UNDEF: use implicit def.; not Constant node
1365}
1366
1367/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1368/// and the value fits into an unsigned 18-bit constant, and if so, return the
1369/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001370SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001371 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001372 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001373 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001374 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001375 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001376 uint32_t upper = uint32_t(UValue >> 32);
1377 uint32_t lower = uint32_t(UValue);
1378 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001379 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001380 Value = Value >> 32;
1381 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001382 if (Value <= 0x3ffff)
1383 return DAG.getConstant(Value, ValueType);
1384 }
1385
Dan Gohman475871a2008-07-27 21:46:04 +00001386 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001387}
1388
1389/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1390/// and the value fits into a signed 16-bit constant, and if so, return the
1391/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001392SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001393 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001394 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001395 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001396 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001397 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001398 uint32_t upper = uint32_t(UValue >> 32);
1399 uint32_t lower = uint32_t(UValue);
1400 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001401 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001402 Value = Value >> 32;
1403 }
Scott Michelad2715e2008-03-05 23:02:02 +00001404 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
1405 return DAG.getConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001406 }
1407 }
1408
Dan Gohman475871a2008-07-27 21:46:04 +00001409 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001410}
1411
1412/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1413/// and the value fits into a signed 10-bit constant, and if so, return the
1414/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001415SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001416 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001417 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001418 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001419 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001420 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001421 uint32_t upper = uint32_t(UValue >> 32);
1422 uint32_t lower = uint32_t(UValue);
1423 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001424 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001425 Value = Value >> 32;
1426 }
Scott Michelad2715e2008-03-05 23:02:02 +00001427 if (isS10Constant(Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001428 return DAG.getConstant(Value, ValueType);
1429 }
1430
Dan Gohman475871a2008-07-27 21:46:04 +00001431 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001432}
1433
1434/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1435/// and the value fits into a signed 8-bit constant, and if so, return the
1436/// constant.
1437///
1438/// @note: The incoming vector is v16i8 because that's the only way we can load
1439/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1440/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001441SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001442 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001443 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001444 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001445 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001446 && Value <= 0xffff /* truncated from uint64_t */
1447 && ((short) Value >> 8) == ((short) Value & 0xff))
Scott Michel266bc8f2007-12-04 22:23:35 +00001448 return DAG.getConstant(Value & 0xff, ValueType);
1449 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001450 && (Value & 0xff) == Value)
Scott Michel266bc8f2007-12-04 22:23:35 +00001451 return DAG.getConstant(Value, ValueType);
1452 }
1453
Dan Gohman475871a2008-07-27 21:46:04 +00001454 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001455}
1456
1457/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1458/// and the value fits into a signed 16-bit constant, and if so, return the
1459/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001460SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001461 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001462 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001463 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001464 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001465 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1466 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001467 return DAG.getConstant(Value >> 16, ValueType);
1468 }
1469
Dan Gohman475871a2008-07-27 21:46:04 +00001470 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001471}
1472
1473/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001474SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001475 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001476 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001477 }
1478
Dan Gohman475871a2008-07-27 21:46:04 +00001479 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001480}
1481
1482/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001483SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001484 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001485 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001486 }
1487
Dan Gohman475871a2008-07-27 21:46:04 +00001488 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001489}
1490
1491// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001492// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001493// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1494// zero. Return true if this is not an array of constants, false if it is.
1495//
1496static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1497 uint64_t UndefBits[2]) {
1498 // Start with zero'd results.
1499 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001500
Duncan Sands83ec4b62008-06-06 12:08:01 +00001501 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001502 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001503 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001504
Scott Michel266bc8f2007-12-04 22:23:35 +00001505 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1506 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1507
1508 uint64_t EltBits = 0;
1509 if (OpVal.getOpcode() == ISD::UNDEF) {
1510 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1511 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1512 continue;
1513 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001514 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00001515 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
1516 const APFloat &apf = CN->getValueAPF();
1517 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001518 ? FloatToBits(apf.convertToFloat())
1519 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001520 } else {
1521 // Nonconstant element.
1522 return true;
1523 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001524
Scott Michel266bc8f2007-12-04 22:23:35 +00001525 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1526 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001527
1528 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001529 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1530 return false;
1531}
1532
1533/// If this is a splat (repetition) of a value across the whole vector, return
1534/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001535/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001536/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001537static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001538 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001539 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001540 uint64_t &SplatBits, uint64_t &SplatUndef,
1541 int &SplatSize) {
1542 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1543 // the same as the lower 64-bits, ignoring undefs.
1544 uint64_t Bits64 = Bits128[0] | Bits128[1];
1545 uint64_t Undef64 = Undef128[0] & Undef128[1];
1546 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1547 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1548 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1549 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1550
1551 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1552 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001553
Scott Michel266bc8f2007-12-04 22:23:35 +00001554 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1555 // undefs.
1556 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001557 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001558
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001559 // If the top 16-bits are different than the lower 16-bits, ignoring
1560 // undefs, we have an i32 splat.
1561 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1562 if (MinSplatBits < 16) {
1563 // If the top 8-bits are different than the lower 8-bits, ignoring
1564 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001565 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1566 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001567 // Otherwise, we have an 8-bit splat.
1568 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1569 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1570 SplatSize = 1;
1571 return true;
1572 }
1573 } else {
1574 SplatBits = Bits16;
1575 SplatUndef = Undef16;
1576 SplatSize = 2;
1577 return true;
1578 }
1579 }
1580 } else {
1581 SplatBits = Bits32;
1582 SplatUndef = Undef32;
1583 SplatSize = 4;
1584 return true;
1585 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001586 }
1587 } else {
1588 SplatBits = Bits128[0];
1589 SplatUndef = Undef128[0];
1590 SplatSize = 8;
1591 return true;
1592 }
1593 }
1594
1595 return false; // Can't be a splat if two pieces don't match.
1596}
1597
1598// If this is a case we can't handle, return null and let the default
1599// expansion code take care of it. If we CAN select this case, and if it
1600// selects to a single instruction, return Op. Otherwise, if we can codegen
1601// this case more efficiently than a constant pool load, lower it to the
1602// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001603static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001604 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001605 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001606 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001607 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001608 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001609 uint64_t VectorBits[2];
1610 uint64_t UndefBits[2];
1611 uint64_t SplatBits, SplatUndef;
1612 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001613 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001614 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001615 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001616 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001617 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001618
Duncan Sands83ec4b62008-06-06 12:08:01 +00001619 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001620 default:
1621 case MVT::v4f32: {
1622 uint32_t Value32 = SplatBits;
1623 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001624 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001625 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001626 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001627 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001628 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001629 break;
1630 }
1631 case MVT::v2f64: {
1632 uint64_t f64val = SplatBits;
1633 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001634 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001635 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001636 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001637 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001638 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001639 break;
1640 }
1641 case MVT::v16i8: {
1642 // 8-bit constants have to be expanded to 16-bits
1643 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001644 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001645 for (int i = 0; i < 8; ++i)
1646 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1647 return DAG.getNode(ISD::BIT_CONVERT, VT,
1648 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1649 }
1650 case MVT::v8i16: {
1651 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001652 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001653 Value16 = (unsigned short) (SplatBits & 0xffff);
1654 else
1655 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001656 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1657 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001658 for (int i = 0; i < 8; ++i) Ops[i] = T;
1659 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1660 }
1661 case MVT::v4i32: {
1662 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001663 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001664 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1665 }
1666 case MVT::v2i64: {
1667 uint64_t val = SplatBits;
1668 uint32_t upper = uint32_t(val >> 32);
1669 uint32_t lower = uint32_t(val);
1670
Scott Michel4cb8bd82008-03-06 04:02:54 +00001671 if (upper == lower) {
1672 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001673 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001674 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001675 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001676 SDValue LO32;
1677 SDValue HI32;
1678 SmallVector<SDValue, 16> ShufBytes;
1679 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001680 bool upper_special, lower_special;
1681
1682 // NOTE: This code creates common-case shuffle masks that can be easily
1683 // detected as common expressions. It is not attempting to create highly
1684 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1685
1686 // Detect if the upper or lower half is a special shuffle mask pattern:
1687 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1688 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1689
1690 // Create lower vector if not a special pattern
1691 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001692 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001693 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1694 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1695 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001696 }
1697
1698 // Create upper vector if not a special pattern
1699 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001700 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001701 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1702 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1703 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001704 }
1705
1706 // If either upper or lower are special, then the two input operands are
1707 // the same (basically, one of them is a "don't care")
1708 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001709 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001710 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001711 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001712 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001713 // Unhappy situation... both upper and lower are special, so punt with
1714 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001715 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001716 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001717 Zero, Zero);
1718 }
1719
1720 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001721 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001722 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001723 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001724 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001725 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001726 process_upper = (upper_special && (i & 1) == 0);
1727 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001728
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001729 if (process_upper || process_lower) {
1730 if ((process_upper && upper == 0)
1731 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001732 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001733 else if ((process_upper && upper == 0xffffffff)
1734 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001735 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001736 else if ((process_upper && upper == 0x80000000)
1737 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001738 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001739 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001740 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001741 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001742
1743 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001744 }
1745
1746 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001747 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001748 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001749 }
1750 }
1751 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001752
Dan Gohman475871a2008-07-27 21:46:04 +00001753 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001754}
1755
1756/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1757/// which the Cell can operate. The code inspects V3 to ascertain whether the
1758/// permutation vector, V3, is monotonically increasing with one "exception"
1759/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1760/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1761/// In either case, the net result is going to eventually invoke SHUFB to
1762/// permute/shuffle the bytes from V1 and V2.
1763/// \note
1764/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1765/// control word for byte/halfword/word insertion. This takes care of a single
1766/// element move from V2 into V1.
1767/// \note
1768/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001769static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1770 SDValue V1 = Op.getOperand(0);
1771 SDValue V2 = Op.getOperand(1);
1772 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001773
Scott Michel266bc8f2007-12-04 22:23:35 +00001774 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001775
Scott Michel266bc8f2007-12-04 22:23:35 +00001776 // If we have a single element being moved from V1 to V2, this can be handled
1777 // using the C*[DX] compute mask instructions, but the vector elements have
1778 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001779 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001780 unsigned EltsFromV2 = 0;
1781 unsigned V2Elt = 0;
1782 unsigned V2EltIdx0 = 0;
1783 unsigned CurrElt = 0;
1784 bool monotonic = true;
1785 if (EltVT == MVT::i8)
1786 V2EltIdx0 = 16;
1787 else if (EltVT == MVT::i16)
1788 V2EltIdx0 = 8;
1789 else if (EltVT == MVT::i32)
1790 V2EltIdx0 = 4;
1791 else
1792 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1793
1794 for (unsigned i = 0, e = PermMask.getNumOperands();
1795 EltsFromV2 <= 1 && monotonic && i != e;
1796 ++i) {
1797 unsigned SrcElt;
1798 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1799 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 Michel266bc8f2007-12-04 22:23:35 +00001802
1803 if (SrcElt >= V2EltIdx0) {
1804 ++EltsFromV2;
1805 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1806 } else if (CurrElt != SrcElt) {
1807 monotonic = false;
1808 }
1809
1810 ++CurrElt;
1811 }
1812
1813 if (EltsFromV2 == 1 && monotonic) {
1814 // Compute mask and shuffle
1815 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001816 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1817 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001818 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001819 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001820 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001821 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1822 // Copy register's contents as index in INSERT_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001823 SDValue ShufMaskOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001824 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001825 DAG.getTargetConstant(V2Elt, MVT::i32),
1826 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001827 // Use shuffle mask in SHUFB synthetic instruction:
1828 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1829 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001830 // Convert the SHUFFLE_VECTOR mask's input element units to the
1831 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001832 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001833
Dan Gohman475871a2008-07-27 21:46:04 +00001834 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001835 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1836 unsigned SrcElt;
1837 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001838 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001839 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001840 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001841
Scott Michela59d4692008-02-23 18:41:37 +00001842 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001843 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1844 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001845 }
1846 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001847
Dan Gohman475871a2008-07-27 21:46:04 +00001848 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001849 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001850 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1851 }
1852}
1853
Dan Gohman475871a2008-07-27 21:46:04 +00001854static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1855 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001856
Gabor Greifba36cb52008-08-28 21:40:38 +00001857 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001858 // For a constant, build the appropriate constant vector, which will
1859 // eventually simplify to a vector register load.
1860
Gabor Greifba36cb52008-08-28 21:40:38 +00001861 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001862 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001863 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001864 size_t n_copies;
1865
1866 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001867 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001868 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001869 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001870 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1871 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1872 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1873 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1874 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1875 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1876 }
1877
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001878 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001879 for (size_t j = 0; j < n_copies; ++j)
1880 ConstVecValues.push_back(CValue);
1881
1882 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001883 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001884 } else {
1885 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001886 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001887 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1888 case MVT::i8:
1889 case MVT::i16:
1890 case MVT::i32:
1891 case MVT::i64:
1892 case MVT::f32:
1893 case MVT::f64:
1894 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1895 }
1896 }
1897
Dan Gohman475871a2008-07-27 21:46:04 +00001898 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001899}
1900
Dan Gohman475871a2008-07-27 21:46:04 +00001901static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001902 switch (Op.getValueType().getSimpleVT()) {
1903 default:
1904 cerr << "CellSPU: Unknown vector multiplication, got "
1905 << Op.getValueType().getMVTString()
1906 << "\n";
1907 abort();
1908 /*NOTREACHED*/
1909
Scott Michel266bc8f2007-12-04 22:23:35 +00001910 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001911 SDValue rA = Op.getOperand(0);
1912 SDValue rB = Op.getOperand(1);
1913 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1914 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1915 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1916 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001917
1918 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1919 break;
1920 }
1921
1922 // Multiply two v8i16 vectors (pipeline friendly version):
1923 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1924 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1925 // c) Use SELB to select upper and lower halves from the intermediate results
1926 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001927 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001928 // dual-issue. This code does manage to do this, even if it's a little on
1929 // the wacky side
1930 case MVT::v8i16: {
1931 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001932 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001933 SDValue Chain = Op.getOperand(0);
1934 SDValue rA = Op.getOperand(0);
1935 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001936 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1937 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001938
Dan Gohman475871a2008-07-27 21:46:04 +00001939 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001940 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001941 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001942 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001943
Dan Gohman475871a2008-07-27 21:46:04 +00001944 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001945 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001946 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001947
Dan Gohman475871a2008-07-27 21:46:04 +00001948 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001949 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001950 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001951
1952 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001953 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1954 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1955 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1956 HHProd_v4i32,
1957 DAG.getConstant(16, MVT::i16))),
1958 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001959 }
1960
1961 // This M00sE is N@stI! (apologies to Monty Python)
1962 //
1963 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1964 // is to break it all apart, sign extend, and reassemble the various
1965 // intermediate products.
1966 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001967 SDValue rA = Op.getOperand(0);
1968 SDValue rB = Op.getOperand(1);
1969 SDValue c8 = DAG.getConstant(8, MVT::i32);
1970 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001971
Dan Gohman475871a2008-07-27 21:46:04 +00001972 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001973 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001974 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1975 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001976
Dan Gohman475871a2008-07-27 21:46:04 +00001977 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001978
Dan Gohman475871a2008-07-27 21:46:04 +00001979 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001980
Dan Gohman475871a2008-07-27 21:46:04 +00001981 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001982 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001983 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001984
Dan Gohman475871a2008-07-27 21:46:04 +00001985 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001986 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001987
Dan Gohman475871a2008-07-27 21:46:04 +00001988 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001989 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1990 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1991 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001992
Dan Gohman475871a2008-07-27 21:46:04 +00001993 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001994
Dan Gohman475871a2008-07-27 21:46:04 +00001995 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001996 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00001997 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001998 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1999 LoProdMask, LoProdMask,
2000 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002001
Dan Gohman475871a2008-07-27 21:46:04 +00002002 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002003 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002004 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002005
Dan Gohman475871a2008-07-27 21:46:04 +00002006 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002007 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002008 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002009
Dan Gohman475871a2008-07-27 21:46:04 +00002010 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002011 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002012 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2013 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00002014
Dan Gohman475871a2008-07-27 21:46:04 +00002015 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002016 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002017 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002018 DAG.getNode(SPUISD::VEC_SRA,
2019 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002020 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002021 DAG.getNode(SPUISD::VEC_SRA,
2022 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002023
Dan Gohman475871a2008-07-27 21:46:04 +00002024 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00002025 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2026 HLProd,
2027 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2028 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002029
Dan Gohman475871a2008-07-27 21:46:04 +00002030 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002031 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002032
2033 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002034 DAG.getNode(ISD::OR, MVT::v4i32,
2035 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002036 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002037 }
2038
Dan Gohman475871a2008-07-27 21:46:04 +00002039 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002040}
2041
Dan Gohman475871a2008-07-27 21:46:04 +00002042static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002043 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002044 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002045
Dan Gohman475871a2008-07-27 21:46:04 +00002046 SDValue A = Op.getOperand(0);
2047 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002048 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002049
2050 unsigned VRegBR, VRegC;
2051
2052 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002053 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2054 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002055 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002056 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2057 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002058 }
2059 // TODO: make sure we're feeding FPInterp the right arguments
2060 // Right now: fi B, frest(B)
2061
2062 // Computes BRcpl =
2063 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002064 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002065 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2066 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002067 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002068
Scott Michel266bc8f2007-12-04 22:23:35 +00002069 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002070 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002071 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002072 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002073 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002074 // What's the Chain variable do? It's magic!
2075 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002076
2077 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002078 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002079 DAG.getNode(ISD::FMUL, VT,
2080 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002081 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002082 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002083 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002084}
2085
Dan Gohman475871a2008-07-27 21:46:04 +00002086static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002087 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002088 SDValue N = Op.getOperand(0);
2089 SDValue Elt = Op.getOperand(1);
2090 SDValue ShufMask[16];
Scott Michel266bc8f2007-12-04 22:23:35 +00002091 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
2092
2093 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2094
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002095 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002096
2097 // sanity checks:
2098 if (VT == MVT::i8 && EltNo >= 16)
2099 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2100 else if (VT == MVT::i16 && EltNo >= 8)
2101 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2102 else if (VT == MVT::i32 && EltNo >= 4)
2103 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2104 else if (VT == MVT::i64 && EltNo >= 2)
2105 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2106
2107 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2108 // i32 and i64: Element 0 is the preferred slot
2109 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2110 }
2111
2112 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002113 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002114 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002115
Duncan Sands83ec4b62008-06-06 12:08:01 +00002116 switch (VT.getSimpleVT()) {
2117 default:
2118 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002119 case MVT::i8: {
2120 prefslot_begin = prefslot_end = 3;
2121 break;
2122 }
2123 case MVT::i16: {
2124 prefslot_begin = 2; prefslot_end = 3;
2125 break;
2126 }
2127 case MVT::i32: {
2128 prefslot_begin = 0; prefslot_end = 3;
2129 break;
2130 }
2131 case MVT::i64: {
2132 prefslot_begin = 0; prefslot_end = 7;
2133 break;
2134 }
2135 }
2136
Scott Michel0e5665b2007-12-19 21:17:42 +00002137 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002138 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002139
Scott Michel266bc8f2007-12-04 22:23:35 +00002140 for (int i = 0; i < 16; ++i) {
2141 // zero fill uppper part of preferred slot, don't care about the
2142 // other slots:
2143 unsigned int mask_val;
2144
2145 if (i <= prefslot_end) {
2146 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002147 ((i < prefslot_begin)
2148 ? 0x80
2149 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002150
Scott Michel0e5665b2007-12-19 21:17:42 +00002151 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002152 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002153 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2154 }
2155
Dan Gohman475871a2008-07-27 21:46:04 +00002156 SDValue ShufMaskVec =
Scott Michel266bc8f2007-12-04 22:23:35 +00002157 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002158 &ShufMask[0],
2159 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002160
2161 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002162 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2163 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002164
Scott Michel266bc8f2007-12-04 22:23:35 +00002165}
2166
Dan Gohman475871a2008-07-27 21:46:04 +00002167static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2168 SDValue VecOp = Op.getOperand(0);
2169 SDValue ValOp = Op.getOperand(1);
2170 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002171 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002172
2173 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2174 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2175
Duncan Sands83ec4b62008-06-06 12:08:01 +00002176 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002177 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002178 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002179
Dan Gohman475871a2008-07-27 21:46:04 +00002180 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002181 DAG.getNode(SPUISD::SHUFB, VT,
2182 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2183 VecOp,
2184 DAG.getNode(SPUISD::INSERT_MASK, VT,
2185 DAG.getNode(ISD::ADD, PtrVT,
2186 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002187 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002188 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002189
2190 return result;
2191}
2192
Dan Gohman475871a2008-07-27 21:46:04 +00002193static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002194{
Dan Gohman475871a2008-07-27 21:46:04 +00002195 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002196
2197 assert(Op.getValueType() == MVT::i8);
2198 switch (Opc) {
2199 default:
2200 assert(0 && "Unhandled i8 math operator");
2201 /*NOTREACHED*/
2202 break;
2203 case ISD::SUB: {
2204 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2205 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002206 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002207 N0 = (N0.getOpcode() != ISD::Constant
2208 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002209 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2210 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002211 N1 = (N1.getOpcode() != ISD::Constant
2212 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002213 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2214 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002215 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002216 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002217 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002218 case ISD::ROTR:
2219 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002220 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002221 unsigned N1Opc;
2222 N0 = (N0.getOpcode() != ISD::Constant
2223 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002224 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2225 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002226 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2227 ? ISD::ZERO_EXTEND
2228 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002229 N1 = (N1.getOpcode() != ISD::Constant
2230 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002231 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2232 MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002233 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002234 DAG.getNode(ISD::OR, MVT::i16, N0,
2235 DAG.getNode(ISD::SHL, MVT::i16,
2236 N0, DAG.getConstant(8, MVT::i16)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002237 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002238 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2239 }
2240 case ISD::SRL:
2241 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002242 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002243 unsigned N1Opc;
2244 N0 = (N0.getOpcode() != ISD::Constant
2245 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002246 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2247 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002248 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2249 ? ISD::ZERO_EXTEND
2250 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002251 N1 = (N1.getOpcode() != ISD::Constant
2252 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002253 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2254 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002255 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002256 DAG.getNode(Opc, MVT::i16, N0, N1));
2257 }
2258 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002259 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002260 unsigned N1Opc;
2261 N0 = (N0.getOpcode() != ISD::Constant
2262 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002263 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2264 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002265 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2266 ? ISD::SIGN_EXTEND
2267 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002268 N1 = (N1.getOpcode() != ISD::Constant
2269 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002270 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2271 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002272 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002273 DAG.getNode(Opc, MVT::i16, N0, N1));
2274 }
2275 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002276 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002277 unsigned N1Opc;
2278 N0 = (N0.getOpcode() != ISD::Constant
2279 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002280 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2281 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002282 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002283 N1 = (N1.getOpcode() != ISD::Constant
2284 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002285 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2286 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002287 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002288 DAG.getNode(Opc, MVT::i16, N0, N1));
2289 break;
2290 }
2291 }
2292
Dan Gohman475871a2008-07-27 21:46:04 +00002293 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002294}
2295
Dan Gohman475871a2008-07-27 21:46:04 +00002296static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002297{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002298 MVT VT = Op.getValueType();
2299 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002300
Dan Gohman475871a2008-07-27 21:46:04 +00002301 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002302
2303 switch (Opc) {
2304 case ISD::ZERO_EXTEND:
2305 case ISD::SIGN_EXTEND:
2306 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002307 MVT Op0VT = Op0.getValueType();
2308 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002309
2310 assert(Op0VT == MVT::i32
2311 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002312 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002313
2314 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2315 ? SPUISD::ROTBYTES_RIGHT_S
2316 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002317 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002318 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2319
2320 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2321 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2322 DAG.getNode(NewOpc, Op0VecVT,
2323 PromoteScalar,
2324 DAG.getConstant(4, MVT::i32))));
2325 }
2326
Scott Michel8bf61e82008-06-02 22:18:03 +00002327 case ISD::ADD: {
2328 // Turn operands into vectors to satisfy type checking (shufb works on
2329 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002330 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002331 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002332 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002333 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002334 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002335
2336 // Create the shuffle mask for "rotating" the borrow up one register slot
2337 // once the borrow is generated.
2338 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2339 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2340 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2341 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2342
Dan Gohman475871a2008-07-27 21:46:04 +00002343 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002344 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002345 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002346 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2347 CarryGen, CarryGen,
2348 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2349 &ShufBytes[0], ShufBytes.size()));
2350
2351 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2352 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2353 Op0, Op1, ShiftedCarry));
2354 }
2355
2356 case ISD::SUB: {
2357 // Turn operands into vectors to satisfy type checking (shufb works on
2358 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002359 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002360 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002361 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002362 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002363 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002364
2365 // Create the shuffle mask for "rotating" the borrow up one register slot
2366 // once the borrow is generated.
2367 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2368 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2369 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2370 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2371
Dan Gohman475871a2008-07-27 21:46:04 +00002372 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002373 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002374 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002375 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2376 BorrowGen, BorrowGen,
2377 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2378 &ShufBytes[0], ShufBytes.size()));
2379
2380 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2381 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2382 Op0, Op1, ShiftedBorrow));
2383 }
2384
Scott Michela59d4692008-02-23 18:41:37 +00002385 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002386 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002387 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002388 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2389 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002390 DAG.getNode(SPUISD::SELB, VecVT,
2391 Op0Vec,
2392 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002393 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002394 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002395 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002396 DAG.getNode(ISD::SRL, ShiftAmtVT,
2397 ShiftAmt,
2398 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002399 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002400 DAG.getNode(ISD::AND, ShiftAmtVT,
2401 ShiftAmt,
2402 DAG.getConstant(7, ShiftAmtVT));
2403
2404 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2405 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2406 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2407 MaskLower, ShiftAmtBytes),
2408 ShiftAmtBits));
2409 }
2410
2411 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002412 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002413 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002414 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002415 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002416 DAG.getNode(ISD::SRL, ShiftAmtVT,
2417 ShiftAmt,
2418 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002419 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002420 DAG.getNode(ISD::AND, ShiftAmtVT,
2421 ShiftAmt,
2422 DAG.getConstant(7, ShiftAmtVT));
2423
2424 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2425 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2426 Op0, ShiftAmtBytes),
2427 ShiftAmtBits);
2428 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002429
2430 case ISD::SRA: {
2431 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002432 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002433 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002434 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002435 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002436
2437 // Negate variable shift amounts
2438 if (!isa<ConstantSDNode>(ShiftAmt)) {
2439 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2440 DAG.getConstant(0, ShiftVT), ShiftAmt);
2441 }
2442
Dan Gohman475871a2008-07-27 21:46:04 +00002443 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002444 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2445 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2446 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2447 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002448 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002449 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002450 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002451 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2452 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002453 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002454 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2455 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002456 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002457 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2458 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002459 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002460 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2461 RotateLeftBytes, ShiftAmt);
2462
2463 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2464 RotateLeftBits);
2465 }
Scott Michela59d4692008-02-23 18:41:37 +00002466 }
2467
Dan Gohman475871a2008-07-27 21:46:04 +00002468 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002469}
2470
Scott Michel266bc8f2007-12-04 22:23:35 +00002471//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002472static SDValue
2473LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2474 SDValue ConstVec;
2475 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002476 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002477
2478 ConstVec = Op.getOperand(0);
2479 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002480 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2481 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002482 ConstVec = ConstVec.getOperand(0);
2483 } else {
2484 ConstVec = Op.getOperand(1);
2485 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002486 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002487 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002488 }
2489 }
2490 }
2491
Gabor Greifba36cb52008-08-28 21:40:38 +00002492 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002493 uint64_t VectorBits[2];
2494 uint64_t UndefBits[2];
2495 uint64_t SplatBits, SplatUndef;
2496 int SplatSize;
2497
Gabor Greifba36cb52008-08-28 21:40:38 +00002498 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002499 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002500 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002501 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002502 SDValue tcVec[16];
2503 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002504 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2505
2506 // Turn the BUILD_VECTOR into a set of target constants:
2507 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002508 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002509
Gabor Greifba36cb52008-08-28 21:40:38 +00002510 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002511 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002512 }
2513 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002514 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2515 // lowered. Return the operation, rather than a null SDValue.
2516 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002517}
2518
2519//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002520static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002521 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002522 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002523 default:
2524 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002525 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002526 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002527 abort();
2528 /*NOTREACHED*/
2529
2530 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002531 SDValue rA = Op.getOperand(0);
2532 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002533
2534 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002535 DAG.getNode(ISD::ADD, MVT::i32,
2536 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2537 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2538 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002539 }
2540 }
2541
Dan Gohman475871a2008-07-27 21:46:04 +00002542 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002543}
2544
2545//! Custom lowering for CTPOP (count population)
2546/*!
2547 Custom lowering code that counts the number ones in the input
2548 operand. SPU has such an instruction, but it counts the number of
2549 ones per byte, which then have to be accumulated.
2550*/
Dan Gohman475871a2008-07-27 21:46:04 +00002551static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002552 MVT VT = Op.getValueType();
2553 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002554
Duncan Sands83ec4b62008-06-06 12:08:01 +00002555 switch (VT.getSimpleVT()) {
2556 default:
2557 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002558 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002559 SDValue N = Op.getOperand(0);
2560 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002561
Dan Gohman475871a2008-07-27 21:46:04 +00002562 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2563 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002564
2565 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2566 }
2567
2568 case MVT::i16: {
2569 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002570 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002571
Chris Lattner84bc5422007-12-31 04:13:23 +00002572 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002573
Dan Gohman475871a2008-07-27 21:46:04 +00002574 SDValue N = Op.getOperand(0);
2575 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2576 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
2577 SDValue Shift1 = DAG.getConstant(8, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002578
Dan Gohman475871a2008-07-27 21:46:04 +00002579 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2580 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002581
2582 // CNTB_result becomes the chain to which all of the virtual registers
2583 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002584 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002585 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002586
Dan Gohman475871a2008-07-27 21:46:04 +00002587 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002588 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2589
Dan Gohman475871a2008-07-27 21:46:04 +00002590 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002591
2592 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002593 DAG.getNode(ISD::ADD, MVT::i16,
2594 DAG.getNode(ISD::SRL, MVT::i16,
2595 Tmp1, Shift1),
2596 Tmp1),
2597 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002598 }
2599
2600 case MVT::i32: {
2601 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002602 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002603
Chris Lattner84bc5422007-12-31 04:13:23 +00002604 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2605 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002606
Dan Gohman475871a2008-07-27 21:46:04 +00002607 SDValue N = Op.getOperand(0);
2608 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2609 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2610 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2611 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002612
Dan Gohman475871a2008-07-27 21:46:04 +00002613 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2614 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002615
2616 // CNTB_result becomes the chain to which all of the virtual registers
2617 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002618 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002619 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002620
Dan Gohman475871a2008-07-27 21:46:04 +00002621 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002622 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2623
Dan Gohman475871a2008-07-27 21:46:04 +00002624 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002625 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002626 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002627
Dan Gohman475871a2008-07-27 21:46:04 +00002628 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002629 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002630 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002631
Dan Gohman475871a2008-07-27 21:46:04 +00002632 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002633 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2634
Dan Gohman475871a2008-07-27 21:46:04 +00002635 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002636 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002637 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2638 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002639 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002640 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002641 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002642
2643 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2644 }
2645
2646 case MVT::i64:
2647 break;
2648 }
2649
Dan Gohman475871a2008-07-27 21:46:04 +00002650 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002651}
2652
2653/// LowerOperation - Provide custom lowering hooks for some operations.
2654///
Dan Gohman475871a2008-07-27 21:46:04 +00002655SDValue
2656SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002657{
Scott Michela59d4692008-02-23 18:41:37 +00002658 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002659 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002660
2661 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002662 default: {
2663 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002664 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002665 cerr << "*Op.getNode():\n";
2666 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002667 abort();
2668 }
2669 case ISD::LOAD:
2670 case ISD::SEXTLOAD:
2671 case ISD::ZEXTLOAD:
2672 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2673 case ISD::STORE:
2674 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2675 case ISD::ConstantPool:
2676 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2677 case ISD::GlobalAddress:
2678 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2679 case ISD::JumpTable:
2680 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2681 case ISD::Constant:
2682 return LowerConstant(Op, DAG);
2683 case ISD::ConstantFP:
2684 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002685 case ISD::BRCOND:
2686 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002687 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002688 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002689 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002690 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002691 case ISD::RET:
2692 return LowerRET(Op, DAG, getTargetMachine());
2693
Scott Michela59d4692008-02-23 18:41:37 +00002694
2695 // i8, i64 math ops:
2696 case ISD::ZERO_EXTEND:
2697 case ISD::SIGN_EXTEND:
2698 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002699 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002700 case ISD::SUB:
2701 case ISD::ROTR:
2702 case ISD::ROTL:
2703 case ISD::SRL:
2704 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002705 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002706 if (VT == MVT::i8)
2707 return LowerI8Math(Op, DAG, Opc);
2708 else if (VT == MVT::i64)
2709 return LowerI64Math(Op, DAG, Opc);
2710 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002711 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002712
2713 // Vector-related lowering.
2714 case ISD::BUILD_VECTOR:
2715 return LowerBUILD_VECTOR(Op, DAG);
2716 case ISD::SCALAR_TO_VECTOR:
2717 return LowerSCALAR_TO_VECTOR(Op, DAG);
2718 case ISD::VECTOR_SHUFFLE:
2719 return LowerVECTOR_SHUFFLE(Op, DAG);
2720 case ISD::EXTRACT_VECTOR_ELT:
2721 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2722 case ISD::INSERT_VECTOR_ELT:
2723 return LowerINSERT_VECTOR_ELT(Op, DAG);
2724
2725 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2726 case ISD::AND:
2727 case ISD::OR:
2728 case ISD::XOR:
2729 return LowerByteImmed(Op, DAG);
2730
2731 // Vector and i8 multiply:
2732 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002733 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002734 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002735 else if (VT == MVT::i8)
2736 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002737 else
Scott Michela59d4692008-02-23 18:41:37 +00002738 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002739
2740 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002741 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002742 return LowerFDIVf32(Op, DAG);
2743// else if (Op.getValueType() == MVT::f64)
2744// return LowerFDIVf64(Op, DAG);
2745 else
2746 assert(0 && "Calling FDIV on unsupported MVT");
2747
2748 case ISD::CTPOP:
2749 return LowerCTPOP(Op, DAG);
2750 }
2751
Dan Gohman475871a2008-07-27 21:46:04 +00002752 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002753}
2754
2755//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002756// Target Optimization Hooks
2757//===----------------------------------------------------------------------===//
2758
Dan Gohman475871a2008-07-27 21:46:04 +00002759SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002760SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2761{
2762#if 0
2763 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002764#endif
2765 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002766 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002767 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2768 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002769
2770 switch (N->getOpcode()) {
2771 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002772 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002773 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002774
Scott Michel8bf61e82008-06-02 22:18:03 +00002775 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002776 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002777 if (Op01.getOpcode() == ISD::Constant
2778 || Op01.getOpcode() == ISD::TargetConstant) {
2779 // (add <const>, (SPUindirect <arg>, <const>)) ->
2780 // (SPUindirect <arg>, <const + const>)
2781 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2782 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002783 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002784 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002785 Op0.getValueType());
2786
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002787 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2788 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002789 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002790 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002791 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2792 Op0.getOperand(0), combinedConst);
2793 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002794 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002795 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002796 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002797 if (Op11.getOpcode() == ISD::Constant
2798 || Op11.getOpcode() == ISD::TargetConstant) {
2799 // (add (SPUindirect <arg>, <const>), <const>) ->
2800 // (SPUindirect <arg>, <const + const>)
2801 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2802 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002803 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002804 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002805 Op0.getValueType());
2806
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002807 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2808 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002809 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002810 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002811
2812 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2813 Op1.getOperand(0), combinedConst);
2814 }
2815 }
Scott Michela59d4692008-02-23 18:41:37 +00002816 break;
2817 }
2818 case ISD::SIGN_EXTEND:
2819 case ISD::ZERO_EXTEND:
2820 case ISD::ANY_EXTEND: {
2821 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2822 N->getValueType(0) == Op0.getValueType()) {
2823 // (any_extend (SPUextract_elt0 <arg>)) ->
2824 // (SPUextract_elt0 <arg>)
2825 // Types must match, however...
2826 DEBUG(cerr << "Replace: ");
2827 DEBUG(N->dump(&DAG));
2828 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002829 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002830 DEBUG(cerr << "\n");
2831
2832 return Op0;
2833 }
2834 break;
2835 }
2836 case SPUISD::IndirectAddr: {
2837 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2838 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002839 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002840 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2841 // (SPUaform <addr>, 0)
2842
2843 DEBUG(cerr << "Replace: ");
2844 DEBUG(N->dump(&DAG));
2845 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002846 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002847 DEBUG(cerr << "\n");
2848
2849 return Op0;
2850 }
2851 }
2852 break;
2853 }
2854 case SPUISD::SHLQUAD_L_BITS:
2855 case SPUISD::SHLQUAD_L_BYTES:
2856 case SPUISD::VEC_SHL:
2857 case SPUISD::VEC_SRL:
2858 case SPUISD::VEC_SRA:
2859 case SPUISD::ROTQUAD_RZ_BYTES:
2860 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002861 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002862
2863 if (isa<ConstantSDNode>(Op1)) {
2864 // Kill degenerate vector shifts:
2865 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2866
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002867 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002868 Result = Op0;
2869 }
2870 }
2871 break;
2872 }
2873 case SPUISD::PROMOTE_SCALAR: {
2874 switch (Op0.getOpcode()) {
2875 default:
2876 break;
2877 case ISD::ANY_EXTEND:
2878 case ISD::ZERO_EXTEND:
2879 case ISD::SIGN_EXTEND: {
2880 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2881 // <arg>
2882 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002883 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002884 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00002885 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002886 if (Op000.getValueType() == N->getValueType(0)) {
2887 Result = Op000;
2888 }
2889 }
2890 break;
2891 }
2892 case SPUISD::EXTRACT_ELT0: {
2893 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2894 // <arg>
2895 Result = Op0.getOperand(0);
2896 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002897 }
Scott Michela59d4692008-02-23 18:41:37 +00002898 }
2899 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002900 }
2901 }
Scott Michel58c58182008-01-17 20:38:41 +00002902 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002903#if 1
Gabor Greifba36cb52008-08-28 21:40:38 +00002904 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00002905 DEBUG(cerr << "\nReplace.SPU: ");
2906 DEBUG(N->dump(&DAG));
2907 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002908 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002909 DEBUG(cerr << "\n");
2910 }
2911#endif
2912
2913 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002914}
2915
2916//===----------------------------------------------------------------------===//
2917// Inline Assembly Support
2918//===----------------------------------------------------------------------===//
2919
2920/// getConstraintType - Given a constraint letter, return the type of
2921/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002922SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002923SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2924 if (ConstraintLetter.size() == 1) {
2925 switch (ConstraintLetter[0]) {
2926 default: break;
2927 case 'b':
2928 case 'r':
2929 case 'f':
2930 case 'v':
2931 case 'y':
2932 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002933 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002934 }
2935 return TargetLowering::getConstraintType(ConstraintLetter);
2936}
2937
Scott Michel5af8f0e2008-07-16 17:17:29 +00002938std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002939SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002940 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002941{
2942 if (Constraint.size() == 1) {
2943 // GCC RS6000 Constraint Letters
2944 switch (Constraint[0]) {
2945 case 'b': // R1-R31
2946 case 'r': // R0-R31
2947 if (VT == MVT::i64)
2948 return std::make_pair(0U, SPU::R64CRegisterClass);
2949 return std::make_pair(0U, SPU::R32CRegisterClass);
2950 case 'f':
2951 if (VT == MVT::f32)
2952 return std::make_pair(0U, SPU::R32FPRegisterClass);
2953 else if (VT == MVT::f64)
2954 return std::make_pair(0U, SPU::R64FPRegisterClass);
2955 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002956 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002957 return std::make_pair(0U, SPU::GPRCRegisterClass);
2958 }
2959 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002960
Scott Michel266bc8f2007-12-04 22:23:35 +00002961 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2962}
2963
Scott Michela59d4692008-02-23 18:41:37 +00002964//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002965void
Dan Gohman475871a2008-07-27 21:46:04 +00002966SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002967 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002968 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002969 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002970 const SelectionDAG &DAG,
2971 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002972#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002973 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002974#endif
Scott Michela59d4692008-02-23 18:41:37 +00002975
2976 switch (Op.getOpcode()) {
2977 default:
2978 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2979 break;
2980
2981#if 0
2982 case CALL:
2983 case SHUFB:
2984 case INSERT_MASK:
2985 case CNTB:
2986#endif
2987
2988 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00002989 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002990 MVT Op0VT = Op0.getValueType();
2991 unsigned Op0VTBits = Op0VT.getSizeInBits();
2992 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002993 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2994 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002995 break;
2996 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002997
Scott Michela59d4692008-02-23 18:41:37 +00002998 case SPUISD::LDRESULT:
2999 case SPUISD::EXTRACT_ELT0:
3000 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00003001 MVT OpVT = Op.getValueType();
3002 unsigned OpVTBits = OpVT.getSizeInBits();
3003 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003004 KnownZero |= APInt(OpVTBits, ~InMask, false);
3005 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003006 break;
3007 }
3008
3009#if 0
3010 case EXTRACT_I1_ZEXT:
3011 case EXTRACT_I1_SEXT:
3012 case EXTRACT_I8_ZEXT:
3013 case EXTRACT_I8_SEXT:
3014 case MPY:
3015 case MPYU:
3016 case MPYH:
3017 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003018 case SPUISD::SHLQUAD_L_BITS:
3019 case SPUISD::SHLQUAD_L_BYTES:
3020 case SPUISD::VEC_SHL:
3021 case SPUISD::VEC_SRL:
3022 case SPUISD::VEC_SRA:
3023 case SPUISD::VEC_ROTL:
3024 case SPUISD::VEC_ROTR:
3025 case SPUISD::ROTQUAD_RZ_BYTES:
3026 case SPUISD::ROTQUAD_RZ_BITS:
3027 case SPUISD::ROTBYTES_RIGHT_S:
3028 case SPUISD::ROTBYTES_LEFT:
3029 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003030 case SPUISD::SELECT_MASK:
3031 case SPUISD::SELB:
3032 case SPUISD::FPInterp:
3033 case SPUISD::FPRecipEst:
3034 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003035#endif
3036 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003037}
3038
Scott Michel203b2d62008-04-30 00:30:08 +00003039// LowerAsmOperandForConstraint
3040void
Dan Gohman475871a2008-07-27 21:46:04 +00003041SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003042 char ConstraintLetter,
Dan Gohman475871a2008-07-27 21:46:04 +00003043 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003044 SelectionDAG &DAG) const {
3045 // Default, for the time being, to the base class handler
3046 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, Ops, DAG);
3047}
3048
Scott Michel266bc8f2007-12-04 22:23:35 +00003049/// isLegalAddressImmediate - Return true if the integer value can be used
3050/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003051bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3052 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003053 // SPU's addresses are 256K:
3054 return (V > -(1 << 18) && V < (1 << 18) - 1);
3055}
3056
3057bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003058 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003059}