blob: f2980e62e86a68d7564673207a3e0fdc9a666125 [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 Michel430a5552008-11-19 15:24:16 +0000134#if 0
Evan Cheng03294662008-10-14 21:26:46 +0000135 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
136 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
137 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Chris Lattnerddf89562008-01-17 19:59:44 +0000138 setTruncStoreAction(MVT::i8, MVT::i1, Custom);
139 setTruncStoreAction(MVT::i16, MVT::i1, Custom);
140 setTruncStoreAction(MVT::i32, MVT::i1, Custom);
141 setTruncStoreAction(MVT::i64, MVT::i1, Custom);
142 setTruncStoreAction(MVT::i128, MVT::i1, Custom);
Scott Michel430a5552008-11-19 15:24:16 +0000143#else
144 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
145 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
146 setTruncStoreAction(MVT::i8, MVT::i1, Promote);
147#endif
Scott Michel266bc8f2007-12-04 22:23:35 +0000148
Evan Cheng03294662008-10-14 21:26:46 +0000149 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
150 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
151 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Chris Lattnerddf89562008-01-17 19:59:44 +0000152 setTruncStoreAction(MVT::i8 , MVT::i8, Custom);
153 setTruncStoreAction(MVT::i16 , MVT::i8, Custom);
154 setTruncStoreAction(MVT::i32 , MVT::i8, Custom);
155 setTruncStoreAction(MVT::i64 , MVT::i8, Custom);
156 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000157
Evan Cheng03294662008-10-14 21:26:46 +0000158 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
159 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
160 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000161
162 // SPU constant load actions are custom lowered:
163 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begemanccef5802008-02-14 18:43:04 +0000164 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000165 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
166
167 // SPU's loads and stores have to be custom lowered:
168 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
169 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000170 MVT VT = (MVT::SimpleValueType)sctype;
171
172 setOperationAction(ISD::LOAD, VT, Custom);
173 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000174 }
175
Scott Michel58c58182008-01-17 20:38:41 +0000176 // Custom lower BRCOND for i1, i8 to "promote" the result to
177 // i32 and i16, respectively.
178 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000179
180 // Expand the jumptable branches
181 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
182 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000183 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000184
185 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000186 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
187
Scott Michel266bc8f2007-12-04 22:23:35 +0000188 // PowerPC has no SREM/UREM instructions
189 setOperationAction(ISD::SREM, MVT::i32, Expand);
190 setOperationAction(ISD::UREM, MVT::i32, Expand);
191 setOperationAction(ISD::SREM, MVT::i64, Expand);
192 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000193
Scott Michel266bc8f2007-12-04 22:23:35 +0000194 // We don't support sin/cos/sqrt/fmod
195 setOperationAction(ISD::FSIN , MVT::f64, Expand);
196 setOperationAction(ISD::FCOS , MVT::f64, Expand);
197 setOperationAction(ISD::FREM , MVT::f64, Expand);
198 setOperationAction(ISD::FSIN , MVT::f32, Expand);
199 setOperationAction(ISD::FCOS , MVT::f32, Expand);
200 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000201
Scott Michel266bc8f2007-12-04 22:23:35 +0000202 // If we're enabling GP optimizations, use hardware square root
203 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
204 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000205
Scott Michel266bc8f2007-12-04 22:23:35 +0000206 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
207 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
208
209 // SPU can do rotate right and left, so legalize it... but customize for i8
210 // because instructions don't exist.
Bill Wendling9440e352008-08-31 02:59:23 +0000211
212 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
213 // .td files.
214 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
215 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
216 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
217
Scott Michel266bc8f2007-12-04 22:23:35 +0000218 setOperationAction(ISD::ROTL, MVT::i32, Legal);
219 setOperationAction(ISD::ROTL, MVT::i16, Legal);
220 setOperationAction(ISD::ROTL, MVT::i8, Custom);
221 // SPU has no native version of shift left/right for i8
222 setOperationAction(ISD::SHL, MVT::i8, Custom);
223 setOperationAction(ISD::SRL, MVT::i8, Custom);
224 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michela59d4692008-02-23 18:41:37 +0000225 // And SPU needs custom lowering for shift left/right for i64
226 setOperationAction(ISD::SHL, MVT::i64, Custom);
227 setOperationAction(ISD::SRL, MVT::i64, Custom);
228 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000229
Scott Michel5af8f0e2008-07-16 17:17:29 +0000230 // Custom lower i8, i32 and i64 multiplications
231 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000232 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000233 setOperationAction(ISD::MUL, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000234
Scott Michel8bf61e82008-06-02 22:18:03 +0000235 // Need to custom handle (some) common i8, i64 math ops
236 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000237 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel8bf61e82008-06-02 22:18:03 +0000238 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000239
Scott Michel266bc8f2007-12-04 22:23:35 +0000240 // SPU does not have BSWAP. It does have i32 support CTLZ.
241 // CTPOP has to be custom lowered.
242 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
243 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
244
245 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
246 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
247 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
248 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
249
250 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
251 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
252
253 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000254
Scott Michel8bf61e82008-06-02 22:18:03 +0000255 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000256 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000257 setOperationAction(ISD::SELECT, MVT::i1, Promote);
258 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000259 setOperationAction(ISD::SELECT, MVT::i16, Legal);
260 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000261 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000262
Scott Michel78c47fa2008-03-10 16:58:52 +0000263 setOperationAction(ISD::SETCC, MVT::i1, Promote);
264 setOperationAction(ISD::SETCC, MVT::i8, Legal);
265 setOperationAction(ISD::SETCC, MVT::i16, Legal);
266 setOperationAction(ISD::SETCC, MVT::i32, Legal);
267 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michelad2715e2008-03-05 23:02:02 +0000268
Scott Michela59d4692008-02-23 18:41:37 +0000269 // Zero extension and sign extension for i64 have to be
270 // custom legalized
271 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
272 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
273 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000274
Scott Michel266bc8f2007-12-04 22:23:35 +0000275 // SPU has a legal FP -> signed INT instruction
276 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
277 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
278 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
279 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
280
281 // FDIV on SPU requires custom lowering
282 setOperationAction(ISD::FDIV, MVT::f32, Custom);
283 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
284
285 // SPU has [U|S]INT_TO_FP
286 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
287 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
288 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
289 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
290 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
291 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
292 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
293 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
294
Scott Michel86c041f2007-12-20 00:44:13 +0000295 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
296 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
297 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
298 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000299
300 // We cannot sextinreg(i1). Expand to shifts.
301 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000302
Scott Michel266bc8f2007-12-04 22:23:35 +0000303 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000304 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000305 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000306
307 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000308 // appropriate instructions to materialize the address.
Scott Michel053c1da2008-01-29 02:16:57 +0000309 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
310 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000311 MVT VT = (MVT::SimpleValueType)sctype;
312
313 setOperationAction(ISD::GlobalAddress, VT, Custom);
314 setOperationAction(ISD::ConstantPool, VT, Custom);
315 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000316 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000317
318 // RET must be custom lowered, to meet ABI requirements
319 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000320
Scott Michel266bc8f2007-12-04 22:23:35 +0000321 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
322 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000323
Scott Michel266bc8f2007-12-04 22:23:35 +0000324 // Use the default implementation.
325 setOperationAction(ISD::VAARG , MVT::Other, Expand);
326 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
327 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000328 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000329 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
330 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
331 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
332
333 // Cell SPU has instructions for converting between i64 and fp.
334 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
335 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000336
Scott Michel266bc8f2007-12-04 22:23:35 +0000337 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
338 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
339
340 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
341 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
342
343 // First set operation action for all vector types to expand. Then we
344 // will selectively turn on ones that can be effectively codegen'd.
345 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
346 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
347 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
348 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
349 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
350 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
351
Duncan Sands83ec4b62008-06-06 12:08:01 +0000352 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
353 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
354 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000355
Duncan Sands83ec4b62008-06-06 12:08:01 +0000356 // add/sub are legal for all supported vector VT's.
357 setOperationAction(ISD::ADD , VT, Legal);
358 setOperationAction(ISD::SUB , VT, Legal);
359 // mul has to be custom lowered.
360 setOperationAction(ISD::MUL , VT, Custom);
361
362 setOperationAction(ISD::AND , VT, Legal);
363 setOperationAction(ISD::OR , VT, Legal);
364 setOperationAction(ISD::XOR , VT, Legal);
365 setOperationAction(ISD::LOAD , VT, Legal);
366 setOperationAction(ISD::SELECT, VT, Legal);
367 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000368
Scott Michel266bc8f2007-12-04 22:23:35 +0000369 // These operations need to be expanded:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000370 setOperationAction(ISD::SDIV, VT, Expand);
371 setOperationAction(ISD::SREM, VT, Expand);
372 setOperationAction(ISD::UDIV, VT, Expand);
373 setOperationAction(ISD::UREM, VT, Expand);
374 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000375
376 // Custom lower build_vector, constant pool spills, insert and
377 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000378 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
379 setOperationAction(ISD::ConstantPool, VT, Custom);
380 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
381 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
382 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
383 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000384 }
385
386 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
387 setOperationAction(ISD::AND, MVT::v16i8, Custom);
388 setOperationAction(ISD::OR, MVT::v16i8, Custom);
389 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
390 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000391
Scott Michel266bc8f2007-12-04 22:23:35 +0000392 setShiftAmountType(MVT::i32);
393 setSetCCResultContents(ZeroOrOneSetCCResult);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000394
Scott Michel266bc8f2007-12-04 22:23:35 +0000395 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000396
Scott Michel266bc8f2007-12-04 22:23:35 +0000397 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000398 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000399 setTargetDAGCombine(ISD::ZERO_EXTEND);
400 setTargetDAGCombine(ISD::SIGN_EXTEND);
401 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000402
Scott Michel266bc8f2007-12-04 22:23:35 +0000403 computeRegisterProperties();
404}
405
406const char *
407SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
408{
409 if (node_names.empty()) {
410 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
411 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
412 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
413 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000414 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000415 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000416 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
417 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
418 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
419 node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
420 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
421 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
422 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
Gabor Greif93c53e52008-08-31 15:37:04 +0000423 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED]
424 = "SPUISD::EXTRACT_ELT0_CHAINED";
Scott Michel266bc8f2007-12-04 22:23:35 +0000425 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
426 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
427 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
428 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
429 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
430 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
431 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
432 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michela59d4692008-02-23 18:41:37 +0000433 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
434 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000435 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
436 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
437 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
438 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
439 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michela59d4692008-02-23 18:41:37 +0000440 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
441 "SPUISD::ROTQUAD_RZ_BYTES";
442 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
443 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel266bc8f2007-12-04 22:23:35 +0000444 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
445 "SPUISD::ROTBYTES_RIGHT_S";
446 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
447 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
448 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel8bf61e82008-06-02 22:18:03 +0000449 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
450 "SPUISD::ROTBYTES_LEFT_BITS";
451 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000452 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000453 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
454 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
455 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
456 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000457 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
458 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
459 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
460 }
461
462 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
463
464 return ((i != node_names.end()) ? i->second : 0);
465}
466
Dan Gohman475871a2008-07-27 21:46:04 +0000467MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000468 MVT VT = Op.getValueType();
Scott Micheld976c212008-10-30 01:51:48 +0000469 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel78c47fa2008-03-10 16:58:52 +0000470}
471
Scott Michel266bc8f2007-12-04 22:23:35 +0000472//===----------------------------------------------------------------------===//
473// Calling convention code:
474//===----------------------------------------------------------------------===//
475
476#include "SPUGenCallingConv.inc"
477
478//===----------------------------------------------------------------------===//
479// LowerOperation implementation
480//===----------------------------------------------------------------------===//
481
Scott Michel9de5d0d2008-01-11 02:53:15 +0000482/// Aligned load common code for CellSPU
483/*!
484 \param[in] Op The SelectionDAG load or store operand
485 \param[in] DAG The selection DAG
486 \param[in] ST CellSPU subtarget information structure
487 \param[in,out] alignment Caller initializes this to the load or store node's
488 value from getAlignment(), may be updated while generating the aligned load
489 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
490 offset (divisible by 16, modulo 16 == 0)
491 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
492 offset of the preferred slot (modulo 16 != 0)
493 \param[in,out] VT Caller initializes this value type to the the load or store
494 node's loaded or stored value type; may be updated if an i1-extended load or
495 store.
496 \param[out] was16aligned true if the base pointer had 16-byte alignment,
497 otherwise false. Can help to determine if the chunk needs to be rotated.
498
499 Both load and store lowering load a block of data aligned on a 16-byte
500 boundary. This is the common aligned load code shared between both.
501 */
Dan Gohman475871a2008-07-27 21:46:04 +0000502static SDValue
503AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Michel9de5d0d2008-01-11 02:53:15 +0000504 LSBaseSDNode *LSN,
505 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000506 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000507{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000508 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000509 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman475871a2008-07-27 21:46:04 +0000510 SDValue basePtr = LSN->getBasePtr();
511 SDValue chain = LSN->getChain();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000512
513 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000514 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000515
Gabor Greif93c53e52008-08-31 15:37:04 +0000516 if (Op1.getOpcode() == ISD::Constant
517 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000518 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000519
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000520 alignOffs = (int) CN->getZExtValue();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000521 prefSlotOffs = (int) (alignOffs & 0xf);
522
523 // Adjust the rotation amount to ensure that the final result ends up in
524 // the preferred slot:
525 prefSlotOffs -= vtm->prefslot_byte;
526 basePtr = basePtr.getOperand(0);
527
Scott Michel58c58182008-01-17 20:38:41 +0000528 // Loading from memory, can we adjust alignment?
529 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +0000530 SDValue APtr = basePtr.getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000531 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
532 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
533 alignment = GSDN->getGlobal()->getAlignment();
534 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000535 }
536 } else {
537 alignOffs = 0;
538 prefSlotOffs = -vtm->prefslot_byte;
539 }
Scott Michel203b2d62008-04-30 00:30:08 +0000540 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
541 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
542 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
543 prefSlotOffs = (int) (alignOffs & 0xf);
544 prefSlotOffs -= vtm->prefslot_byte;
545 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000546 } else {
547 alignOffs = 0;
548 prefSlotOffs = -vtm->prefslot_byte;
549 }
550
551 if (alignment == 16) {
552 // Realign the base pointer as a D-Form address:
553 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000554 basePtr = DAG.getNode(ISD::ADD, PtrVT,
555 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000556 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000557 }
558
559 // Emit the vector load:
560 was16aligned = true;
561 return DAG.getLoad(MVT::v16i8, chain, basePtr,
562 LSN->getSrcValue(), LSN->getSrcValueOffset(),
563 LSN->isVolatile(), 16);
564 }
565
566 // Unaligned load or we're using the "large memory" model, which means that
567 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000568 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greif93c53e52008-08-31 15:37:04 +0000569 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
570 DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000571 }
572
573 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000574 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000575 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000576 was16aligned = false;
577 return DAG.getLoad(MVT::v16i8, chain, basePtr,
578 LSN->getSrcValue(), LSN->getSrcValueOffset(),
579 LSN->isVolatile(), 16);
580}
581
Scott Michel266bc8f2007-12-04 22:23:35 +0000582/// Custom lower loads for CellSPU
583/*!
584 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
585 within a 16-byte block, we have to rotate to extract the requested element.
586 */
Dan Gohman475871a2008-07-27 21:46:04 +0000587static SDValue
588LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000589 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000590 SDValue the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000591 MVT VT = LN->getMemoryVT();
Gabor Greifba36cb52008-08-28 21:40:38 +0000592 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000593 ISD::LoadExtType ExtType = LN->getExtensionType();
594 unsigned alignment = LN->getAlignment();
Dan Gohman475871a2008-07-27 21:46:04 +0000595 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000596
Scott Michel266bc8f2007-12-04 22:23:35 +0000597 switch (LN->getAddressingMode()) {
598 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000599 int offset, rotamt;
600 bool was16aligned;
Dan Gohman475871a2008-07-27 21:46:04 +0000601 SDValue result =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000602 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000603
Gabor Greifba36cb52008-08-28 21:40:38 +0000604 if (result.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000605 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000606
607 the_chain = result.getValue(1);
608 // Rotate the chunk if necessary
609 if (rotamt < 0)
610 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000611 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000612 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
613
Scott Michel58c58182008-01-17 20:38:41 +0000614 Ops[0] = the_chain;
615 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000616 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000617 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
618 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000619 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000620 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000621 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000622 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000623 }
624
625 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
626 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000627 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000628
629 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
630 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000631 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000632
Scott Michel9de5d0d2008-01-11 02:53:15 +0000633 // Convert the loaded v16i8 vector to the appropriate vector type
634 // specified by the operand:
635 if (OpVT == VT) {
636 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000637 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000638 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000639 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000640
641 Ops[0] = the_chain;
642 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
643 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
644 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
645 the_chain = result.getValue(1);
646 } else {
647 // Handle the sign and zero-extending loads for i1 and i8:
648 unsigned NewOpC;
649
650 if (ExtType == ISD::SEXTLOAD) {
651 NewOpC = (OpVT == MVT::i1
652 ? SPUISD::EXTRACT_I1_SEXT
653 : SPUISD::EXTRACT_I8_SEXT);
654 } else {
655 assert(ExtType == ISD::ZEXTLOAD);
656 NewOpC = (OpVT == MVT::i1
657 ? SPUISD::EXTRACT_I1_ZEXT
658 : SPUISD::EXTRACT_I8_ZEXT);
659 }
660
661 result = DAG.getNode(NewOpC, OpVT, result);
662 }
663
664 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000665 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000666 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000667 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000668 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000669
Scott Michel58c58182008-01-17 20:38:41 +0000670 result = DAG.getNode(SPUISD::LDRESULT, retvts,
671 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000672 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000673 }
674 case ISD::PRE_INC:
675 case ISD::PRE_DEC:
676 case ISD::POST_INC:
677 case ISD::POST_DEC:
678 case ISD::LAST_INDEXED_MODE:
679 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
680 "UNINDEXED\n";
681 cerr << (unsigned) LN->getAddressingMode() << "\n";
682 abort();
683 /*NOTREACHED*/
684 }
685
Dan Gohman475871a2008-07-27 21:46:04 +0000686 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000687}
688
689/// Custom lower stores for CellSPU
690/*!
691 All CellSPU stores are aligned to 16-byte boundaries, so for elements
692 within a 16-byte block, we have to generate a shuffle to insert the
693 requested element into its place, then store the resulting block.
694 */
Dan Gohman475871a2008-07-27 21:46:04 +0000695static SDValue
696LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000697 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000698 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000699 MVT VT = Value.getValueType();
700 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
701 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000702 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000703
704 switch (SN->getAddressingMode()) {
705 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000706 int chunk_offset, slot_offset;
707 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000708
709 // The vector type we really want to load from the 16-byte chunk, except
710 // in the case of MVT::i1, which has to be v16i8.
Scott Michel430a5552008-11-19 15:24:16 +0000711 MVT vecVT = MVT::v16i8, stVecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000712
Scott Michel430a5552008-11-19 15:24:16 +0000713 if (StVT != MVT::i1) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000714 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel430a5552008-11-19 15:24:16 +0000715 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
716 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000717
Dan Gohman475871a2008-07-27 21:46:04 +0000718 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000719 AlignedLoad(Op, DAG, ST, SN, alignment,
720 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000721
Gabor Greifba36cb52008-08-28 21:40:38 +0000722 if (alignLoadVec.getNode() == 0)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000723 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000724
Scott Michel9de5d0d2008-01-11 02:53:15 +0000725 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000726 SDValue basePtr = LN->getBasePtr();
727 SDValue the_chain = alignLoadVec.getValue(1);
728 SDValue theValue = SN->getValue();
729 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000730
731 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000732 && (theValue.getOpcode() == ISD::AssertZext
733 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000734 // Drill down and get the value for zero- and sign-extended
735 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000736 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000737 }
738
Scott Michel9de5d0d2008-01-11 02:53:15 +0000739 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000740
Dan Gohman475871a2008-07-27 21:46:04 +0000741 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
742 SDValue insertEltPtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000743
744 // If the base pointer is already a D-form address, then just create
745 // a new D-form address with a slot offset and the orignal base pointer.
746 // Otherwise generate a D-form address with the slot offset relative
747 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000748 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greifba36cb52008-08-28 21:40:38 +0000749 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michel497e8882008-01-11 21:01:19 +0000750 DEBUG(cerr << "\n");
751
Scott Michel053c1da2008-01-29 02:16:57 +0000752 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
753 (basePtr.getOpcode() == ISD::ADD
754 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000755 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000756 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000757 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000758 }
759
Scott Michel430a5552008-11-19 15:24:16 +0000760 SDValue insertEltOp =
761 DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
762 SDValue vectorizeOp;
763
764#if 0
765 if (VT == MVT::i1 || StVT != VT) {
766 MVT toVT = (VT != MVT::i1) ? VT : MVT::i8;
767 if (toVT.bitsGT(VT)) {
768 vectorizeOp = DAG.getNode(ISD::ANY_EXTEND, toVT, theValue);
769 } else if (StVT.bitsLT(VT)) {
770 vectorizeOp = DAG.getNode(ISD::TRUNCATE, toVT, theValue);
771 }
772
773 vectorizeOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, vectorizeOp);
774 } else
775#endif
776 vectorizeOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
777
778 result = DAG.getNode(SPUISD::SHUFB, vecVT, vectorizeOp, alignLoadVec,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000779 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000780
Scott Michel9de5d0d2008-01-11 02:53:15 +0000781 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000782 LN->getSrcValue(), LN->getSrcValueOffset(),
783 LN->isVolatile(), LN->getAlignment());
784
Scott Michel430a5552008-11-19 15:24:16 +0000785#ifndef NDEBUG
786 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
787 const SDValue &currentRoot = DAG.getRoot();
788
789 DAG.setRoot(result);
790 cerr << "------- CellSPU:LowerStore result:\n";
791 DAG.dump();
792 cerr << "-------\n";
793 DAG.setRoot(currentRoot);
794 }
795#endif
796
Scott Michel266bc8f2007-12-04 22:23:35 +0000797 return result;
798 /*UNREACHED*/
799 }
800 case ISD::PRE_INC:
801 case ISD::PRE_DEC:
802 case ISD::POST_INC:
803 case ISD::POST_DEC:
804 case ISD::LAST_INDEXED_MODE:
805 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
806 "UNINDEXED\n";
807 cerr << (unsigned) SN->getAddressingMode() << "\n";
808 abort();
809 /*NOTREACHED*/
810 }
811
Dan Gohman475871a2008-07-27 21:46:04 +0000812 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000813}
814
815/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000816static SDValue
817LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000818 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000819 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
820 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000821 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
822 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000823 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000824
825 if (TM.getRelocationModel() == Reloc::Static) {
826 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000827 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000828 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000829 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000830 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
831 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000832 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000833 }
834 }
835
836 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000837 "LowerConstantPool: Relocation model other than static"
838 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000839 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000840}
841
Dan Gohman475871a2008-07-27 21:46:04 +0000842static SDValue
843LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000844 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000845 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000846 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
847 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000848 const TargetMachine &TM = DAG.getTarget();
849
850 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000851 if (!ST->usingLargeMem()) {
852 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
853 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000854 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
855 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000856 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
857 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000858 }
859
860 assert(0 &&
861 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000862 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000863}
864
Dan Gohman475871a2008-07-27 21:46:04 +0000865static SDValue
866LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000867 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000868 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
869 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000870 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000871 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000872 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000873
Scott Michel266bc8f2007-12-04 22:23:35 +0000874 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000875 if (!ST->usingLargeMem()) {
876 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
877 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000878 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
879 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000880 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
881 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000882 } else {
883 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000884 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000885 abort();
886 /*NOTREACHED*/
887 }
888
Dan Gohman475871a2008-07-27 21:46:04 +0000889 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000890}
891
892//! Custom lower i64 integer constants
893/*!
894 This code inserts all of the necessary juggling that needs to occur to load
895 a 64-bit constant into a register.
896 */
Dan Gohman475871a2008-07-27 21:46:04 +0000897static SDValue
898LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000899 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000900 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000901
902 if (VT == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000903 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +0000904 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000905 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000906 } else {
907 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000908 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000909 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000910 abort();
911 /*NOTREACHED*/
912 }
913
Dan Gohman475871a2008-07-27 21:46:04 +0000914 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000915}
916
Nate Begemanccef5802008-02-14 18:43:04 +0000917//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000918static SDValue
919LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000920 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000921 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000922
923 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000924 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000925
Nate Begemanccef5802008-02-14 18:43:04 +0000926 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000927 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000928 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000929 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000930 }
931
Dan Gohman475871a2008-07-27 21:46:04 +0000932 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000933}
934
Scott Michel58c58182008-01-17 20:38:41 +0000935//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000936static SDValue
937LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000938{
Dan Gohman475871a2008-07-27 21:46:04 +0000939 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000940 MVT CondVT = Cond.getValueType();
941 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000942
943 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
944 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
945 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
946 Op.getOperand(0),
947 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
948 Op.getOperand(2));
949 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000950 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000951}
952
Dan Gohman475871a2008-07-27 21:46:04 +0000953static SDValue
954LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000955{
956 MachineFunction &MF = DAG.getMachineFunction();
957 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000958 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Micheld976c212008-10-30 01:51:48 +0000959 SmallVector<SDValue, 48> ArgValues;
Dan Gohman475871a2008-07-27 21:46:04 +0000960 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000961 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000962
963 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
964 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000965
Scott Michel266bc8f2007-12-04 22:23:35 +0000966 unsigned ArgOffset = SPUFrameInfo::minStackSize();
967 unsigned ArgRegIdx = 0;
968 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000969
Duncan Sands83ec4b62008-06-06 12:08:01 +0000970 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000971
Scott Michel266bc8f2007-12-04 22:23:35 +0000972 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000973 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
974 ArgNo != e; ++ArgNo) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000975 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
976 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Micheld976c212008-10-30 01:51:48 +0000977 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000978
Scott Micheld976c212008-10-30 01:51:48 +0000979 if (ArgRegIdx < NumArgRegs) {
980 const TargetRegisterClass *ArgRegClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000981
Scott Micheld976c212008-10-30 01:51:48 +0000982 switch (ObjectVT.getSimpleVT()) {
983 default: {
984 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
985 << ObjectVT.getMVTString()
986 << "\n";
987 abort();
988 }
989 case MVT::i8:
990 ArgRegClass = &SPU::R8CRegClass;
991 break;
992 case MVT::i16:
993 ArgRegClass = &SPU::R16CRegClass;
994 break;
995 case MVT::i32:
996 ArgRegClass = &SPU::R32CRegClass;
997 break;
998 case MVT::i64:
999 ArgRegClass = &SPU::R64CRegClass;
1000 break;
1001 case MVT::f32:
1002 ArgRegClass = &SPU::R32FPRegClass;
1003 break;
1004 case MVT::f64:
1005 ArgRegClass = &SPU::R64FPRegClass;
1006 break;
1007 case MVT::v2f64:
1008 case MVT::v4f32:
1009 case MVT::v2i64:
1010 case MVT::v4i32:
1011 case MVT::v8i16:
1012 case MVT::v16i8:
1013 ArgRegClass = &SPU::VECREGRegClass;
Scott Micheld976c212008-10-30 01:51:48 +00001014 break;
1015 }
1016
1017 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
1018 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
1019 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1020 ++ArgRegIdx;
1021 } else {
1022 // We need to load the argument to a virtual register if we determined
1023 // above that we ran out of physical registers of the appropriate type
1024 // or we're forced to do vararg
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001025 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001026 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001027 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001028 ArgOffset += StackSlotSize;
1029 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001030
Scott Michel266bc8f2007-12-04 22:23:35 +00001031 ArgValues.push_back(ArgVal);
Scott Micheld976c212008-10-30 01:51:48 +00001032 // Update the chain
1033 Root = ArgVal.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001034 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001035
Scott Micheld976c212008-10-30 01:51:48 +00001036 // vararg handling:
Scott Michel266bc8f2007-12-04 22:23:35 +00001037 if (isVarArg) {
Scott Micheld976c212008-10-30 01:51:48 +00001038 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1039 // We will spill (79-3)+1 registers to the stack
1040 SmallVector<SDValue, 79-3+1> MemOps;
1041
1042 // Create the frame slot
1043
Scott Michel266bc8f2007-12-04 22:23:35 +00001044 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Micheld976c212008-10-30 01:51:48 +00001045 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1046 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1047 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1048 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1049 Root = Store.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001050 MemOps.push_back(Store);
Scott Micheld976c212008-10-30 01:51:48 +00001051
1052 // Increment address by stack slot size for the next stored argument
1053 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001054 }
1055 if (!MemOps.empty())
Scott Micheld976c212008-10-30 01:51:48 +00001056 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001057 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001058
Scott Michel266bc8f2007-12-04 22:23:35 +00001059 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001060
Scott Michel266bc8f2007-12-04 22:23:35 +00001061 // Return the new list of results.
Gabor Greifba36cb52008-08-28 21:40:38 +00001062 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf9516202008-06-30 10:19:09 +00001063 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001064}
1065
1066/// isLSAAddress - Return the immediate to use if the specified
1067/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001068static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001069 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +00001070 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001071
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001072 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001073 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1074 (Addr << 14 >> 14) != Addr)
1075 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001076
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001077 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001078}
1079
1080static
Dan Gohman475871a2008-07-27 21:46:04 +00001081SDValue
1082LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman095cc292008-09-13 01:54:27 +00001083 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1084 SDValue Chain = TheCall->getChain();
Dan Gohman095cc292008-09-13 01:54:27 +00001085 SDValue Callee = TheCall->getCallee();
1086 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001087 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1088 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1089 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1090
1091 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001092 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001093
Scott Michel266bc8f2007-12-04 22:23:35 +00001094 // Accumulate how many bytes are to be pushed on the stack, including the
1095 // linkage area, and parameter passing area. According to the SPU ABI,
1096 // we minimally need space for [LR] and [SP]
1097 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001098
Scott Michel266bc8f2007-12-04 22:23:35 +00001099 // Set up a copy of the stack pointer for use loading and storing any
1100 // arguments that may not fit in the registers available for argument
1101 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001102 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001103
Scott Michel266bc8f2007-12-04 22:23:35 +00001104 // Figure out which arguments are going to go in registers, and which in
1105 // memory.
1106 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1107 unsigned ArgRegIdx = 0;
1108
1109 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001110 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001111 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001112 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001113
1114 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001115 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001116
Scott Michel266bc8f2007-12-04 22:23:35 +00001117 // PtrOff will be used to store the current argument to the stack if a
1118 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001119 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001120 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1121
Duncan Sands83ec4b62008-06-06 12:08:01 +00001122 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001123 default: assert(0 && "Unexpected ValueType for argument!");
1124 case MVT::i32:
1125 case MVT::i64:
1126 case MVT::i128:
1127 if (ArgRegIdx != NumArgRegs) {
1128 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1129 } else {
1130 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001131 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001132 }
1133 break;
1134 case MVT::f32:
1135 case MVT::f64:
1136 if (ArgRegIdx != NumArgRegs) {
1137 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1138 } else {
1139 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001140 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001141 }
1142 break;
1143 case MVT::v4f32:
1144 case MVT::v4i32:
1145 case MVT::v8i16:
1146 case MVT::v16i8:
1147 if (ArgRegIdx != NumArgRegs) {
1148 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1149 } else {
1150 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001151 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001152 }
1153 break;
1154 }
1155 }
1156
1157 // Update number of stack bytes actually used, insert a call sequence start
1158 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnere563bbc2008-10-11 22:08:30 +00001159 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1160 true));
Scott Michel266bc8f2007-12-04 22:23:35 +00001161
1162 if (!MemOpChains.empty()) {
1163 // Adjust the stack pointer for the stack arguments.
1164 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1165 &MemOpChains[0], MemOpChains.size());
1166 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001167
Scott Michel266bc8f2007-12-04 22:23:35 +00001168 // Build a sequence of copy-to-reg nodes chained together with token chain
1169 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001170 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001171 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1172 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1173 InFlag);
1174 InFlag = Chain.getValue(1);
1175 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001176
Dan Gohman475871a2008-07-27 21:46:04 +00001177 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001178 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001179
Bill Wendling056292f2008-09-16 21:48:12 +00001180 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1181 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1182 // node so that legalize doesn't hack it.
Scott Michel19fd42a2008-11-11 03:06:06 +00001183 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001184 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001185 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001186 SDValue Zero = DAG.getConstant(0, PtrVT);
1187 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001188
Scott Michel9de5d0d2008-01-11 02:53:15 +00001189 if (!ST->usingLargeMem()) {
1190 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1191 // style calls, otherwise, external symbols are BRASL calls. This assumes
1192 // that declared/defined symbols are in the same compilation unit and can
1193 // be reached through PC-relative jumps.
1194 //
1195 // NOTE:
1196 // This may be an unsafe assumption for JIT and really large compilation
1197 // units.
1198 if (GV->isDeclaration()) {
1199 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1200 } else {
1201 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1202 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001203 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001204 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1205 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001206 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001207 }
Scott Michel19fd42a2008-11-11 03:06:06 +00001208 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendling056292f2008-09-16 21:48:12 +00001209 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001210 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001211 // If this is an absolute destination address that appears to be a legal
1212 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001213 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001214 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001215
1216 Ops.push_back(Chain);
1217 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001218
Scott Michel266bc8f2007-12-04 22:23:35 +00001219 // Add argument registers to the end of the list so that they are known live
1220 // into the call.
1221 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001222 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001223 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001224
Gabor Greifba36cb52008-08-28 21:40:38 +00001225 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001226 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001227 // Returns a chain and a flag for retval copy to use.
1228 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1229 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001230 InFlag = Chain.getValue(1);
1231
Chris Lattnere563bbc2008-10-11 22:08:30 +00001232 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1233 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001234 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001235 InFlag = Chain.getValue(1);
1236
Dan Gohman475871a2008-07-27 21:46:04 +00001237 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001238 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001239
Scott Michel266bc8f2007-12-04 22:23:35 +00001240 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001241 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001242 default: assert(0 && "Unexpected ret value!");
1243 case MVT::Other: break;
1244 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001245 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001246 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1247 ResultVals[0] = Chain.getValue(0);
1248 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1249 Chain.getValue(2)).getValue(1);
1250 ResultVals[1] = Chain.getValue(0);
1251 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001252 } else {
1253 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1254 ResultVals[0] = Chain.getValue(0);
1255 NumResults = 1;
1256 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001257 break;
1258 case MVT::i64:
1259 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1260 ResultVals[0] = Chain.getValue(0);
1261 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001262 break;
1263 case MVT::f32:
1264 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001265 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001266 InFlag).getValue(1);
1267 ResultVals[0] = Chain.getValue(0);
1268 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001269 break;
1270 case MVT::v2f64:
1271 case MVT::v4f32:
1272 case MVT::v4i32:
1273 case MVT::v8i16:
1274 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001275 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001276 InFlag).getValue(1);
1277 ResultVals[0] = Chain.getValue(0);
1278 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001279 break;
1280 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001281
Scott Michel266bc8f2007-12-04 22:23:35 +00001282 // If the function returns void, just return the chain.
1283 if (NumResults == 0)
1284 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001285
Scott Michel266bc8f2007-12-04 22:23:35 +00001286 // Otherwise, merge everything together with a MERGE_VALUES node.
1287 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001288 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001289 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001290}
1291
Dan Gohman475871a2008-07-27 21:46:04 +00001292static SDValue
1293LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001294 SmallVector<CCValAssign, 16> RVLocs;
1295 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1296 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1297 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001298 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001299
Scott Michel266bc8f2007-12-04 22:23:35 +00001300 // If this is the first return lowered for this function, add the regs to the
1301 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001302 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001303 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001304 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001305 }
1306
Dan Gohman475871a2008-07-27 21:46:04 +00001307 SDValue Chain = Op.getOperand(0);
1308 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001309
Scott Michel266bc8f2007-12-04 22:23:35 +00001310 // Copy the result values into the output registers.
1311 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1312 CCValAssign &VA = RVLocs[i];
1313 assert(VA.isRegLoc() && "Can only return in registers!");
1314 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1315 Flag = Chain.getValue(1);
1316 }
1317
Gabor Greifba36cb52008-08-28 21:40:38 +00001318 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001319 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1320 else
1321 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1322}
1323
1324
1325//===----------------------------------------------------------------------===//
1326// Vector related lowering:
1327//===----------------------------------------------------------------------===//
1328
1329static ConstantSDNode *
1330getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001331 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001332
Scott Michel266bc8f2007-12-04 22:23:35 +00001333 // Check to see if this buildvec has a single non-undef value in its elements.
1334 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1335 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001336 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001337 OpVal = N->getOperand(i);
1338 else if (OpVal != N->getOperand(i))
1339 return 0;
1340 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001341
Gabor Greifba36cb52008-08-28 21:40:38 +00001342 if (OpVal.getNode() != 0) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001343 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001344 return CN;
1345 }
1346 }
1347
1348 return 0; // All UNDEF: use implicit def.; not Constant node
1349}
1350
1351/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1352/// and the value fits into an unsigned 18-bit constant, and if so, return the
1353/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001354SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001355 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001356 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001357 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001358 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001359 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001360 uint32_t upper = uint32_t(UValue >> 32);
1361 uint32_t lower = uint32_t(UValue);
1362 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001363 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001364 Value = Value >> 32;
1365 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001366 if (Value <= 0x3ffff)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001367 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001368 }
1369
Dan Gohman475871a2008-07-27 21:46:04 +00001370 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001371}
1372
1373/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1374/// and the value fits into a signed 16-bit constant, and if so, return the
1375/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001376SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001377 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001378 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001379 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001380 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001381 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001382 uint32_t upper = uint32_t(UValue >> 32);
1383 uint32_t lower = uint32_t(UValue);
1384 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001385 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001386 Value = Value >> 32;
1387 }
Scott Michelad2715e2008-03-05 23:02:02 +00001388 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001389 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001390 }
1391 }
1392
Dan Gohman475871a2008-07-27 21:46:04 +00001393 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001394}
1395
1396/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1397/// and the value fits into a signed 10-bit constant, and if so, return the
1398/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001399SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001400 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001401 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001402 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001403 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001404 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001405 uint32_t upper = uint32_t(UValue >> 32);
1406 uint32_t lower = uint32_t(UValue);
1407 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001408 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001409 Value = Value >> 32;
1410 }
Scott Michelad2715e2008-03-05 23:02:02 +00001411 if (isS10Constant(Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001412 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001413 }
1414
Dan Gohman475871a2008-07-27 21:46:04 +00001415 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001416}
1417
1418/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1419/// and the value fits into a signed 8-bit constant, and if so, return the
1420/// constant.
1421///
1422/// @note: The incoming vector is v16i8 because that's the only way we can load
1423/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1424/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001425SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001426 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001427 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001428 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001429 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001430 && Value <= 0xffff /* truncated from uint64_t */
1431 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001432 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001433 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001434 && (Value & 0xff) == Value)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001435 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001436 }
1437
Dan Gohman475871a2008-07-27 21:46:04 +00001438 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001439}
1440
1441/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1442/// and the value fits into a signed 16-bit constant, and if so, return the
1443/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001444SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001445 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001446 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001447 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001448 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001449 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1450 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001451 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001452 }
1453
Dan Gohman475871a2008-07-27 21:46:04 +00001454 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001455}
1456
1457/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001458SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001459 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001460 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001461 }
1462
Dan Gohman475871a2008-07-27 21:46:04 +00001463 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001464}
1465
1466/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001467SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001468 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001469 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001470 }
1471
Dan Gohman475871a2008-07-27 21:46:04 +00001472 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001473}
1474
1475// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001476// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001477// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1478// zero. Return true if this is not an array of constants, false if it is.
1479//
1480static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1481 uint64_t UndefBits[2]) {
1482 // Start with zero'd results.
1483 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001484
Duncan Sands83ec4b62008-06-06 12:08:01 +00001485 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001486 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001487 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001488
Scott Michel266bc8f2007-12-04 22:23:35 +00001489 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1490 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1491
1492 uint64_t EltBits = 0;
1493 if (OpVal.getOpcode() == ISD::UNDEF) {
1494 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1495 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1496 continue;
Scott Michel19fd42a2008-11-11 03:06:06 +00001497 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001498 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel19fd42a2008-11-11 03:06:06 +00001499 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001500 const APFloat &apf = CN->getValueAPF();
1501 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001502 ? FloatToBits(apf.convertToFloat())
1503 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001504 } else {
1505 // Nonconstant element.
1506 return true;
1507 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001508
Scott Michel266bc8f2007-12-04 22:23:35 +00001509 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1510 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001511
1512 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001513 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1514 return false;
1515}
1516
1517/// If this is a splat (repetition) of a value across the whole vector, return
1518/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001519/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001520/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001521static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001522 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001523 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001524 uint64_t &SplatBits, uint64_t &SplatUndef,
1525 int &SplatSize) {
1526 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1527 // the same as the lower 64-bits, ignoring undefs.
1528 uint64_t Bits64 = Bits128[0] | Bits128[1];
1529 uint64_t Undef64 = Undef128[0] & Undef128[1];
1530 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1531 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1532 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1533 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1534
1535 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1536 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001537
Scott Michel266bc8f2007-12-04 22:23:35 +00001538 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1539 // undefs.
1540 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001541 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001542
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001543 // If the top 16-bits are different than the lower 16-bits, ignoring
1544 // undefs, we have an i32 splat.
1545 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1546 if (MinSplatBits < 16) {
1547 // If the top 8-bits are different than the lower 8-bits, ignoring
1548 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001549 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1550 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001551 // Otherwise, we have an 8-bit splat.
1552 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1553 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1554 SplatSize = 1;
1555 return true;
1556 }
1557 } else {
1558 SplatBits = Bits16;
1559 SplatUndef = Undef16;
1560 SplatSize = 2;
1561 return true;
1562 }
1563 }
1564 } else {
1565 SplatBits = Bits32;
1566 SplatUndef = Undef32;
1567 SplatSize = 4;
1568 return true;
1569 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001570 }
1571 } else {
1572 SplatBits = Bits128[0];
1573 SplatUndef = Undef128[0];
1574 SplatSize = 8;
1575 return true;
1576 }
1577 }
1578
1579 return false; // Can't be a splat if two pieces don't match.
1580}
1581
1582// If this is a case we can't handle, return null and let the default
1583// expansion code take care of it. If we CAN select this case, and if it
1584// selects to a single instruction, return Op. Otherwise, if we can codegen
1585// this case more efficiently than a constant pool load, lower it to the
1586// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001587static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001588 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001589 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001590 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001591 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001592 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001593 uint64_t VectorBits[2];
1594 uint64_t UndefBits[2];
1595 uint64_t SplatBits, SplatUndef;
1596 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001597 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001598 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001599 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001600 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001601 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001602
Duncan Sands83ec4b62008-06-06 12:08:01 +00001603 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001604 default:
1605 case MVT::v4f32: {
1606 uint32_t Value32 = SplatBits;
1607 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001608 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001609 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001610 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001611 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001612 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001613 break;
1614 }
1615 case MVT::v2f64: {
1616 uint64_t f64val = SplatBits;
1617 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001618 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001619 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001620 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001621 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001622 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001623 break;
1624 }
1625 case MVT::v16i8: {
1626 // 8-bit constants have to be expanded to 16-bits
1627 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001628 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001629 for (int i = 0; i < 8; ++i)
1630 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1631 return DAG.getNode(ISD::BIT_CONVERT, VT,
1632 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1633 }
1634 case MVT::v8i16: {
1635 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001636 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001637 Value16 = (unsigned short) (SplatBits & 0xffff);
1638 else
1639 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001640 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1641 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001642 for (int i = 0; i < 8; ++i) Ops[i] = T;
1643 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1644 }
1645 case MVT::v4i32: {
1646 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001647 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001648 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1649 }
1650 case MVT::v2i64: {
1651 uint64_t val = SplatBits;
1652 uint32_t upper = uint32_t(val >> 32);
1653 uint32_t lower = uint32_t(val);
1654
Scott Michel4cb8bd82008-03-06 04:02:54 +00001655 if (upper == lower) {
1656 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001657 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001658 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001659 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001660 SDValue LO32;
1661 SDValue HI32;
1662 SmallVector<SDValue, 16> ShufBytes;
1663 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001664 bool upper_special, lower_special;
1665
1666 // NOTE: This code creates common-case shuffle masks that can be easily
1667 // detected as common expressions. It is not attempting to create highly
1668 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1669
1670 // Detect if the upper or lower half is a special shuffle mask pattern:
1671 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1672 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1673
1674 // Create lower vector if not a special pattern
1675 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001676 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001677 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1678 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1679 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001680 }
1681
1682 // Create upper vector if not a special pattern
1683 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001684 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001685 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1686 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1687 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001688 }
1689
1690 // If either upper or lower are special, then the two input operands are
1691 // the same (basically, one of them is a "don't care")
1692 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001693 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001694 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001695 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001696 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001697 // Unhappy situation... both upper and lower are special, so punt with
1698 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001699 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001700 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001701 Zero, Zero);
1702 }
1703
1704 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001705 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001706 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001707 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001708 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001709 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001710 process_upper = (upper_special && (i & 1) == 0);
1711 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001712
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001713 if (process_upper || process_lower) {
1714 if ((process_upper && upper == 0)
1715 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001716 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001717 else if ((process_upper && upper == 0xffffffff)
1718 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001719 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001720 else if ((process_upper && upper == 0x80000000)
1721 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001722 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001723 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001724 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001725 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001726
1727 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001728 }
1729
1730 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001731 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001732 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001733 }
1734 }
1735 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001736
Dan Gohman475871a2008-07-27 21:46:04 +00001737 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001738}
1739
1740/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1741/// which the Cell can operate. The code inspects V3 to ascertain whether the
1742/// permutation vector, V3, is monotonically increasing with one "exception"
1743/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1744/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1745/// In either case, the net result is going to eventually invoke SHUFB to
1746/// permute/shuffle the bytes from V1 and V2.
1747/// \note
1748/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1749/// control word for byte/halfword/word insertion. This takes care of a single
1750/// element move from V2 into V1.
1751/// \note
1752/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001753static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1754 SDValue V1 = Op.getOperand(0);
1755 SDValue V2 = Op.getOperand(1);
1756 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001757
Scott Michel266bc8f2007-12-04 22:23:35 +00001758 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001759
Scott Michel266bc8f2007-12-04 22:23:35 +00001760 // If we have a single element being moved from V1 to V2, this can be handled
1761 // using the C*[DX] compute mask instructions, but the vector elements have
1762 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001763 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001764 unsigned EltsFromV2 = 0;
1765 unsigned V2Elt = 0;
1766 unsigned V2EltIdx0 = 0;
1767 unsigned CurrElt = 0;
1768 bool monotonic = true;
1769 if (EltVT == MVT::i8)
1770 V2EltIdx0 = 16;
1771 else if (EltVT == MVT::i16)
1772 V2EltIdx0 = 8;
1773 else if (EltVT == MVT::i32)
1774 V2EltIdx0 = 4;
1775 else
1776 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1777
1778 for (unsigned i = 0, e = PermMask.getNumOperands();
1779 EltsFromV2 <= 1 && monotonic && i != e;
1780 ++i) {
1781 unsigned SrcElt;
1782 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1783 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001784 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001785 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001786
1787 if (SrcElt >= V2EltIdx0) {
1788 ++EltsFromV2;
1789 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1790 } else if (CurrElt != SrcElt) {
1791 monotonic = false;
1792 }
1793
1794 ++CurrElt;
1795 }
1796
1797 if (EltsFromV2 == 1 && monotonic) {
1798 // Compute mask and shuffle
1799 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001800 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1801 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001802 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001803 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001804 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001805 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1806 // Copy register's contents as index in INSERT_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001807 SDValue ShufMaskOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001808 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001809 DAG.getTargetConstant(V2Elt, MVT::i32),
1810 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001811 // Use shuffle mask in SHUFB synthetic instruction:
1812 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1813 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001814 // Convert the SHUFFLE_VECTOR mask's input element units to the
1815 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001816 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001817
Dan Gohman475871a2008-07-27 21:46:04 +00001818 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001819 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1820 unsigned SrcElt;
1821 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001822 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001823 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001824 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001825
Scott Michela59d4692008-02-23 18:41:37 +00001826 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001827 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1828 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001829 }
1830 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001831
Dan Gohman475871a2008-07-27 21:46:04 +00001832 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001833 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001834 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1835 }
1836}
1837
Dan Gohman475871a2008-07-27 21:46:04 +00001838static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1839 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001840
Gabor Greifba36cb52008-08-28 21:40:38 +00001841 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001842 // For a constant, build the appropriate constant vector, which will
1843 // eventually simplify to a vector register load.
1844
Gabor Greifba36cb52008-08-28 21:40:38 +00001845 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001846 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001847 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001848 size_t n_copies;
1849
1850 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001851 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001852 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001853 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001854 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1855 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1856 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1857 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1858 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1859 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1860 }
1861
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001862 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001863 for (size_t j = 0; j < n_copies; ++j)
1864 ConstVecValues.push_back(CValue);
1865
1866 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001867 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001868 } else {
1869 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001870 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001871 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1872 case MVT::i8:
1873 case MVT::i16:
1874 case MVT::i32:
1875 case MVT::i64:
1876 case MVT::f32:
1877 case MVT::f64:
1878 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1879 }
1880 }
1881
Dan Gohman475871a2008-07-27 21:46:04 +00001882 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001883}
1884
Dan Gohman475871a2008-07-27 21:46:04 +00001885static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001886 switch (Op.getValueType().getSimpleVT()) {
1887 default:
1888 cerr << "CellSPU: Unknown vector multiplication, got "
1889 << Op.getValueType().getMVTString()
1890 << "\n";
1891 abort();
1892 /*NOTREACHED*/
1893
Scott Michel266bc8f2007-12-04 22:23:35 +00001894 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001895 SDValue rA = Op.getOperand(0);
1896 SDValue rB = Op.getOperand(1);
1897 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1898 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1899 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1900 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001901
1902 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1903 break;
1904 }
1905
1906 // Multiply two v8i16 vectors (pipeline friendly version):
1907 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1908 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1909 // c) Use SELB to select upper and lower halves from the intermediate results
1910 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001911 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001912 // dual-issue. This code does manage to do this, even if it's a little on
1913 // the wacky side
1914 case MVT::v8i16: {
1915 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001916 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001917 SDValue Chain = Op.getOperand(0);
1918 SDValue rA = Op.getOperand(0);
1919 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001920 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1921 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001922
Dan Gohman475871a2008-07-27 21:46:04 +00001923 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001924 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001925 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001926 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001927
Dan Gohman475871a2008-07-27 21:46:04 +00001928 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001929 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001930 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001931
Dan Gohman475871a2008-07-27 21:46:04 +00001932 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001933 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001934 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001935
1936 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001937 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1938 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1939 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1940 HHProd_v4i32,
1941 DAG.getConstant(16, MVT::i16))),
1942 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001943 }
1944
1945 // This M00sE is N@stI! (apologies to Monty Python)
1946 //
1947 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1948 // is to break it all apart, sign extend, and reassemble the various
1949 // intermediate products.
1950 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001951 SDValue rA = Op.getOperand(0);
1952 SDValue rB = Op.getOperand(1);
1953 SDValue c8 = DAG.getConstant(8, MVT::i32);
1954 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001955
Dan Gohman475871a2008-07-27 21:46:04 +00001956 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001957 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001958 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1959 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001960
Dan Gohman475871a2008-07-27 21:46:04 +00001961 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001962
Dan Gohman475871a2008-07-27 21:46:04 +00001963 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001964
Dan Gohman475871a2008-07-27 21:46:04 +00001965 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001966 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001967 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001968
Dan Gohman475871a2008-07-27 21:46:04 +00001969 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001970 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001971
Dan Gohman475871a2008-07-27 21:46:04 +00001972 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001973 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1974 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1975 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001976
Dan Gohman475871a2008-07-27 21:46:04 +00001977 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001978
Dan Gohman475871a2008-07-27 21:46:04 +00001979 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001980 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00001981 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001982 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1983 LoProdMask, LoProdMask,
1984 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001985
Dan Gohman475871a2008-07-27 21:46:04 +00001986 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001987 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001988 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001989
Dan Gohman475871a2008-07-27 21:46:04 +00001990 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001991 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001992 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001993
Dan Gohman475871a2008-07-27 21:46:04 +00001994 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001995 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001996 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1997 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00001998
Dan Gohman475871a2008-07-27 21:46:04 +00001999 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002000 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002001 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002002 DAG.getNode(SPUISD::VEC_SRA,
2003 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002004 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002005 DAG.getNode(SPUISD::VEC_SRA,
2006 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002007
Dan Gohman475871a2008-07-27 21:46:04 +00002008 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00002009 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2010 HLProd,
2011 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2012 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002013
Dan Gohman475871a2008-07-27 21:46:04 +00002014 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002015 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002016
2017 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002018 DAG.getNode(ISD::OR, MVT::v4i32,
2019 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002020 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002021 }
2022
Dan Gohman475871a2008-07-27 21:46:04 +00002023 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002024}
2025
Dan Gohman475871a2008-07-27 21:46:04 +00002026static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002027 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002028 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002029
Dan Gohman475871a2008-07-27 21:46:04 +00002030 SDValue A = Op.getOperand(0);
2031 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002032 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002033
2034 unsigned VRegBR, VRegC;
2035
2036 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002037 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2038 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002039 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002040 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2041 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002042 }
2043 // TODO: make sure we're feeding FPInterp the right arguments
2044 // Right now: fi B, frest(B)
2045
2046 // Computes BRcpl =
2047 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002048 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002049 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2050 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002051 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002052
Scott Michel266bc8f2007-12-04 22:23:35 +00002053 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002054 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002055 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002056 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002057 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002058 // What's the Chain variable do? It's magic!
2059 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002060
2061 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002062 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002063 DAG.getNode(ISD::FMUL, VT,
2064 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002065 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002066 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002067 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002068}
2069
Dan Gohman475871a2008-07-27 21:46:04 +00002070static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002071 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002072 SDValue N = Op.getOperand(0);
2073 SDValue Elt = Op.getOperand(1);
2074 SDValue ShufMask[16];
Scott Michel19fd42a2008-11-11 03:06:06 +00002075 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
Scott Michel266bc8f2007-12-04 22:23:35 +00002076
2077 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2078
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002079 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002080
2081 // sanity checks:
2082 if (VT == MVT::i8 && EltNo >= 16)
2083 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2084 else if (VT == MVT::i16 && EltNo >= 8)
2085 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2086 else if (VT == MVT::i32 && EltNo >= 4)
2087 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2088 else if (VT == MVT::i64 && EltNo >= 2)
2089 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2090
2091 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2092 // i32 and i64: Element 0 is the preferred slot
2093 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2094 }
2095
2096 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002097 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002098 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002099
Duncan Sands83ec4b62008-06-06 12:08:01 +00002100 switch (VT.getSimpleVT()) {
2101 default:
2102 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002103 case MVT::i8: {
2104 prefslot_begin = prefslot_end = 3;
2105 break;
2106 }
2107 case MVT::i16: {
2108 prefslot_begin = 2; prefslot_end = 3;
2109 break;
2110 }
Scott Michel73ce1c52008-11-10 23:43:06 +00002111 case MVT::i32:
2112 case MVT::f32: {
Scott Michel266bc8f2007-12-04 22:23:35 +00002113 prefslot_begin = 0; prefslot_end = 3;
2114 break;
2115 }
Scott Michel73ce1c52008-11-10 23:43:06 +00002116 case MVT::i64:
2117 case MVT::f64: {
Scott Michel266bc8f2007-12-04 22:23:35 +00002118 prefslot_begin = 0; prefslot_end = 7;
2119 break;
2120 }
2121 }
2122
Scott Michel0e5665b2007-12-19 21:17:42 +00002123 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002124 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002125
Scott Michel266bc8f2007-12-04 22:23:35 +00002126 for (int i = 0; i < 16; ++i) {
2127 // zero fill uppper part of preferred slot, don't care about the
2128 // other slots:
2129 unsigned int mask_val;
2130
2131 if (i <= prefslot_end) {
2132 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002133 ((i < prefslot_begin)
2134 ? 0x80
2135 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002136
Scott Michel0e5665b2007-12-19 21:17:42 +00002137 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002138 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002139 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2140 }
2141
Dan Gohman475871a2008-07-27 21:46:04 +00002142 SDValue ShufMaskVec =
Scott Michel266bc8f2007-12-04 22:23:35 +00002143 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002144 &ShufMask[0],
2145 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002146
2147 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002148 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2149 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002150
Scott Michel266bc8f2007-12-04 22:23:35 +00002151}
2152
Dan Gohman475871a2008-07-27 21:46:04 +00002153static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2154 SDValue VecOp = Op.getOperand(0);
2155 SDValue ValOp = Op.getOperand(1);
2156 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002157 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002158
2159 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2160 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2161
Duncan Sands83ec4b62008-06-06 12:08:01 +00002162 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002163 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002164 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002165
Dan Gohman475871a2008-07-27 21:46:04 +00002166 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002167 DAG.getNode(SPUISD::SHUFB, VT,
2168 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2169 VecOp,
2170 DAG.getNode(SPUISD::INSERT_MASK, VT,
2171 DAG.getNode(ISD::ADD, PtrVT,
2172 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002173 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002174 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002175
2176 return result;
2177}
2178
Dan Gohman475871a2008-07-27 21:46:04 +00002179static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002180{
Dan Gohman475871a2008-07-27 21:46:04 +00002181 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002182
2183 assert(Op.getValueType() == MVT::i8);
2184 switch (Opc) {
2185 default:
2186 assert(0 && "Unhandled i8 math operator");
2187 /*NOTREACHED*/
2188 break;
2189 case ISD::SUB: {
2190 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2191 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002192 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002193 N0 = (N0.getOpcode() != ISD::Constant
2194 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002195 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2196 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002197 N1 = (N1.getOpcode() != ISD::Constant
2198 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002199 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2200 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002201 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002202 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002203 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002204 case ISD::ROTR:
2205 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002206 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002207 unsigned N1Opc;
2208 N0 = (N0.getOpcode() != ISD::Constant
2209 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002210 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2211 MVT::i16));
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002212 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greif93c53e52008-08-31 15:37:04 +00002213 ? ISD::ZERO_EXTEND
2214 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002215 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002216 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002217 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002218 MVT::i32));
Dan Gohman475871a2008-07-27 21:46:04 +00002219 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002220 DAG.getNode(ISD::OR, MVT::i16, N0,
2221 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002222 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002223 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002224 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2225 }
2226 case ISD::SRL:
2227 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002228 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002229 unsigned N1Opc;
2230 N0 = (N0.getOpcode() != ISD::Constant
2231 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002232 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2233 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002234 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2235 ? ISD::ZERO_EXTEND
2236 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002237 N1 = (N1.getOpcode() != ISD::Constant
2238 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002239 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2240 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002241 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002242 DAG.getNode(Opc, MVT::i16, N0, N1));
2243 }
2244 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002245 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002246 unsigned N1Opc;
2247 N0 = (N0.getOpcode() != ISD::Constant
2248 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002249 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2250 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002251 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2252 ? ISD::SIGN_EXTEND
2253 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002254 N1 = (N1.getOpcode() != ISD::Constant
2255 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002256 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2257 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002258 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002259 DAG.getNode(Opc, MVT::i16, N0, N1));
2260 }
2261 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002262 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002263 unsigned N1Opc;
2264 N0 = (N0.getOpcode() != ISD::Constant
2265 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002266 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2267 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002268 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002269 N1 = (N1.getOpcode() != ISD::Constant
2270 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002271 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2272 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002273 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002274 DAG.getNode(Opc, MVT::i16, N0, N1));
2275 break;
2276 }
2277 }
2278
Dan Gohman475871a2008-07-27 21:46:04 +00002279 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002280}
2281
Dan Gohman475871a2008-07-27 21:46:04 +00002282static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002283{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002284 MVT VT = Op.getValueType();
2285 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002286
Dan Gohman475871a2008-07-27 21:46:04 +00002287 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002288
2289 switch (Opc) {
2290 case ISD::ZERO_EXTEND:
2291 case ISD::SIGN_EXTEND:
2292 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002293 MVT Op0VT = Op0.getValueType();
2294 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002295
2296 assert(Op0VT == MVT::i32
2297 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002298 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002299
2300 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2301 ? SPUISD::ROTBYTES_RIGHT_S
2302 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002303 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002304 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2305
2306 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2307 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2308 DAG.getNode(NewOpc, Op0VecVT,
2309 PromoteScalar,
2310 DAG.getConstant(4, MVT::i32))));
2311 }
2312
Scott Michel8bf61e82008-06-02 22:18:03 +00002313 case ISD::ADD: {
2314 // Turn operands into vectors to satisfy type checking (shufb works on
2315 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002316 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002317 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002318 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002319 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002320 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002321
2322 // Create the shuffle mask for "rotating" the borrow up one register slot
2323 // once the borrow is generated.
2324 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2325 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2326 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2327 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2328
Dan Gohman475871a2008-07-27 21:46:04 +00002329 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002330 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002331 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002332 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2333 CarryGen, CarryGen,
2334 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2335 &ShufBytes[0], ShufBytes.size()));
2336
2337 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2338 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2339 Op0, Op1, ShiftedCarry));
2340 }
2341
2342 case ISD::SUB: {
2343 // Turn operands into vectors to satisfy type checking (shufb works on
2344 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002345 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002346 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002347 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002348 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002349 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002350
2351 // Create the shuffle mask for "rotating" the borrow up one register slot
2352 // once the borrow is generated.
2353 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2354 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2355 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2356 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2357
Dan Gohman475871a2008-07-27 21:46:04 +00002358 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002359 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002360 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002361 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2362 BorrowGen, BorrowGen,
2363 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2364 &ShufBytes[0], ShufBytes.size()));
2365
2366 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2367 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2368 Op0, Op1, ShiftedBorrow));
2369 }
2370
Scott Michela59d4692008-02-23 18:41:37 +00002371 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002372 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002373 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002374 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2375 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002376 DAG.getNode(SPUISD::SELB, VecVT,
2377 Op0Vec,
2378 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002379 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002380 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002381 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002382 DAG.getNode(ISD::SRL, ShiftAmtVT,
2383 ShiftAmt,
2384 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002385 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002386 DAG.getNode(ISD::AND, ShiftAmtVT,
2387 ShiftAmt,
2388 DAG.getConstant(7, ShiftAmtVT));
2389
2390 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2391 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2392 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2393 MaskLower, ShiftAmtBytes),
2394 ShiftAmtBits));
2395 }
2396
2397 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002398 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002399 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002400 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002401 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002402 DAG.getNode(ISD::SRL, ShiftAmtVT,
2403 ShiftAmt,
2404 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002405 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002406 DAG.getNode(ISD::AND, ShiftAmtVT,
2407 ShiftAmt,
2408 DAG.getConstant(7, ShiftAmtVT));
2409
2410 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2411 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2412 Op0, ShiftAmtBytes),
2413 ShiftAmtBits);
2414 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002415
2416 case ISD::SRA: {
2417 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002418 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002419 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002420 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002421 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002422
2423 // Negate variable shift amounts
2424 if (!isa<ConstantSDNode>(ShiftAmt)) {
2425 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2426 DAG.getConstant(0, ShiftVT), ShiftAmt);
2427 }
2428
Dan Gohman475871a2008-07-27 21:46:04 +00002429 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002430 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2431 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2432 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2433 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002434 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002435 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002436 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002437 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2438 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002439 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002440 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2441 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002442 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002443 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2444 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002445 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002446 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2447 RotateLeftBytes, ShiftAmt);
2448
2449 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2450 RotateLeftBits);
2451 }
Scott Michela59d4692008-02-23 18:41:37 +00002452 }
2453
Dan Gohman475871a2008-07-27 21:46:04 +00002454 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002455}
2456
Scott Michel266bc8f2007-12-04 22:23:35 +00002457//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002458static SDValue
2459LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2460 SDValue ConstVec;
2461 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002462 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002463
2464 ConstVec = Op.getOperand(0);
2465 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002466 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2467 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002468 ConstVec = ConstVec.getOperand(0);
2469 } else {
2470 ConstVec = Op.getOperand(1);
2471 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002472 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002473 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002474 }
2475 }
2476 }
2477
Gabor Greifba36cb52008-08-28 21:40:38 +00002478 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002479 uint64_t VectorBits[2];
2480 uint64_t UndefBits[2];
2481 uint64_t SplatBits, SplatUndef;
2482 int SplatSize;
2483
Gabor Greifba36cb52008-08-28 21:40:38 +00002484 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002485 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002486 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002487 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002488 SDValue tcVec[16];
2489 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002490 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2491
2492 // Turn the BUILD_VECTOR into a set of target constants:
2493 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002494 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002495
Gabor Greifba36cb52008-08-28 21:40:38 +00002496 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002497 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002498 }
2499 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002500 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2501 // lowered. Return the operation, rather than a null SDValue.
2502 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002503}
2504
2505//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002506static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002507 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002508 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002509 default:
2510 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002511 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002512 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002513 abort();
2514 /*NOTREACHED*/
2515
2516 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002517 SDValue rA = Op.getOperand(0);
2518 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002519
2520 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002521 DAG.getNode(ISD::ADD, MVT::i32,
2522 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2523 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2524 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002525 }
2526 }
2527
Dan Gohman475871a2008-07-27 21:46:04 +00002528 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002529}
2530
2531//! Custom lowering for CTPOP (count population)
2532/*!
2533 Custom lowering code that counts the number ones in the input
2534 operand. SPU has such an instruction, but it counts the number of
2535 ones per byte, which then have to be accumulated.
2536*/
Dan Gohman475871a2008-07-27 21:46:04 +00002537static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002538 MVT VT = Op.getValueType();
2539 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002540
Duncan Sands83ec4b62008-06-06 12:08:01 +00002541 switch (VT.getSimpleVT()) {
2542 default:
2543 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002544 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002545 SDValue N = Op.getOperand(0);
2546 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002547
Dan Gohman475871a2008-07-27 21:46:04 +00002548 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2549 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002550
2551 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2552 }
2553
2554 case MVT::i16: {
2555 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002556 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002557
Chris Lattner84bc5422007-12-31 04:13:23 +00002558 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002559
Dan Gohman475871a2008-07-27 21:46:04 +00002560 SDValue N = Op.getOperand(0);
2561 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2562 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002563 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002564
Dan Gohman475871a2008-07-27 21:46:04 +00002565 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2566 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002567
2568 // CNTB_result becomes the chain to which all of the virtual registers
2569 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002570 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002571 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002572
Dan Gohman475871a2008-07-27 21:46:04 +00002573 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002574 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2575
Dan Gohman475871a2008-07-27 21:46:04 +00002576 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002577
2578 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002579 DAG.getNode(ISD::ADD, MVT::i16,
2580 DAG.getNode(ISD::SRL, MVT::i16,
2581 Tmp1, Shift1),
2582 Tmp1),
2583 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002584 }
2585
2586 case MVT::i32: {
2587 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002588 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002589
Chris Lattner84bc5422007-12-31 04:13:23 +00002590 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2591 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002592
Dan Gohman475871a2008-07-27 21:46:04 +00002593 SDValue N = Op.getOperand(0);
2594 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2595 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2596 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2597 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002598
Dan Gohman475871a2008-07-27 21:46:04 +00002599 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2600 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002601
2602 // CNTB_result becomes the chain to which all of the virtual registers
2603 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002604 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002605 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002606
Dan Gohman475871a2008-07-27 21:46:04 +00002607 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002608 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2609
Dan Gohman475871a2008-07-27 21:46:04 +00002610 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002611 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002612 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002613
Dan Gohman475871a2008-07-27 21:46:04 +00002614 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002615 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002616 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002617
Dan Gohman475871a2008-07-27 21:46:04 +00002618 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002619 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2620
Dan Gohman475871a2008-07-27 21:46:04 +00002621 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002622 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002623 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2624 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002625 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002626 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002627 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002628
2629 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2630 }
2631
2632 case MVT::i64:
2633 break;
2634 }
2635
Dan Gohman475871a2008-07-27 21:46:04 +00002636 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002637}
2638
2639/// LowerOperation - Provide custom lowering hooks for some operations.
2640///
Dan Gohman475871a2008-07-27 21:46:04 +00002641SDValue
2642SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002643{
Scott Michela59d4692008-02-23 18:41:37 +00002644 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002645 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002646
2647 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002648 default: {
2649 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002650 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002651 cerr << "*Op.getNode():\n";
2652 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002653 abort();
2654 }
2655 case ISD::LOAD:
2656 case ISD::SEXTLOAD:
2657 case ISD::ZEXTLOAD:
2658 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2659 case ISD::STORE:
2660 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2661 case ISD::ConstantPool:
2662 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2663 case ISD::GlobalAddress:
2664 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2665 case ISD::JumpTable:
2666 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2667 case ISD::Constant:
2668 return LowerConstant(Op, DAG);
2669 case ISD::ConstantFP:
2670 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002671 case ISD::BRCOND:
2672 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002673 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002674 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002675 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002676 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002677 case ISD::RET:
2678 return LowerRET(Op, DAG, getTargetMachine());
2679
Scott Michela59d4692008-02-23 18:41:37 +00002680
2681 // i8, i64 math ops:
2682 case ISD::ZERO_EXTEND:
2683 case ISD::SIGN_EXTEND:
2684 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002685 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002686 case ISD::SUB:
2687 case ISD::ROTR:
2688 case ISD::ROTL:
2689 case ISD::SRL:
2690 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002691 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002692 if (VT == MVT::i8)
2693 return LowerI8Math(Op, DAG, Opc);
2694 else if (VT == MVT::i64)
2695 return LowerI64Math(Op, DAG, Opc);
2696 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002697 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002698
2699 // Vector-related lowering.
2700 case ISD::BUILD_VECTOR:
2701 return LowerBUILD_VECTOR(Op, DAG);
2702 case ISD::SCALAR_TO_VECTOR:
2703 return LowerSCALAR_TO_VECTOR(Op, DAG);
2704 case ISD::VECTOR_SHUFFLE:
2705 return LowerVECTOR_SHUFFLE(Op, DAG);
2706 case ISD::EXTRACT_VECTOR_ELT:
2707 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2708 case ISD::INSERT_VECTOR_ELT:
2709 return LowerINSERT_VECTOR_ELT(Op, DAG);
2710
2711 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2712 case ISD::AND:
2713 case ISD::OR:
2714 case ISD::XOR:
2715 return LowerByteImmed(Op, DAG);
2716
2717 // Vector and i8 multiply:
2718 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002719 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002720 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002721 else if (VT == MVT::i8)
2722 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002723 else
Scott Michela59d4692008-02-23 18:41:37 +00002724 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002725
2726 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002727 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002728 return LowerFDIVf32(Op, DAG);
2729// else if (Op.getValueType() == MVT::f64)
2730// return LowerFDIVf64(Op, DAG);
2731 else
2732 assert(0 && "Calling FDIV on unsupported MVT");
2733
2734 case ISD::CTPOP:
2735 return LowerCTPOP(Op, DAG);
2736 }
2737
Dan Gohman475871a2008-07-27 21:46:04 +00002738 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002739}
2740
Scott Michel73ce1c52008-11-10 23:43:06 +00002741SDNode *SPUTargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG)
2742{
2743#if 0
2744 unsigned Opc = (unsigned) N->getOpcode();
2745 MVT OpVT = N->getValueType(0);
2746
2747 switch (Opc) {
2748 default: {
2749 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2750 cerr << "Op.getOpcode() = " << Opc << "\n";
2751 cerr << "*Op.getNode():\n";
2752 N->dump();
2753 abort();
2754 /*NOTREACHED*/
2755 }
2756 }
2757#endif
2758
2759 /* Otherwise, return unchanged */
2760 return 0;
2761}
2762
Scott Michel266bc8f2007-12-04 22:23:35 +00002763//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002764// Target Optimization Hooks
2765//===----------------------------------------------------------------------===//
2766
Dan Gohman475871a2008-07-27 21:46:04 +00002767SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002768SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2769{
2770#if 0
2771 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002772#endif
2773 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002774 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002775 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2776 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002777
2778 switch (N->getOpcode()) {
2779 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002780 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002781 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002782
Scott Michel8bf61e82008-06-02 22:18:03 +00002783 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002784 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002785 if (Op01.getOpcode() == ISD::Constant
2786 || Op01.getOpcode() == ISD::TargetConstant) {
2787 // (add <const>, (SPUindirect <arg>, <const>)) ->
2788 // (SPUindirect <arg>, <const + const>)
2789 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2790 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002791 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002792 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002793 Op0.getValueType());
2794
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002795 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2796 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002797 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002798 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002799 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2800 Op0.getOperand(0), combinedConst);
2801 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002802 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002803 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002804 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002805 if (Op11.getOpcode() == ISD::Constant
2806 || Op11.getOpcode() == ISD::TargetConstant) {
2807 // (add (SPUindirect <arg>, <const>), <const>) ->
2808 // (SPUindirect <arg>, <const + const>)
2809 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2810 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002811 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002812 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002813 Op0.getValueType());
2814
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002815 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2816 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002817 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002818 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002819
2820 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2821 Op1.getOperand(0), combinedConst);
2822 }
2823 }
Scott Michela59d4692008-02-23 18:41:37 +00002824 break;
2825 }
2826 case ISD::SIGN_EXTEND:
2827 case ISD::ZERO_EXTEND:
2828 case ISD::ANY_EXTEND: {
2829 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2830 N->getValueType(0) == Op0.getValueType()) {
2831 // (any_extend (SPUextract_elt0 <arg>)) ->
2832 // (SPUextract_elt0 <arg>)
2833 // Types must match, however...
2834 DEBUG(cerr << "Replace: ");
2835 DEBUG(N->dump(&DAG));
2836 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002837 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002838 DEBUG(cerr << "\n");
2839
2840 return Op0;
2841 }
2842 break;
2843 }
2844 case SPUISD::IndirectAddr: {
2845 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2846 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002847 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002848 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2849 // (SPUaform <addr>, 0)
2850
2851 DEBUG(cerr << "Replace: ");
2852 DEBUG(N->dump(&DAG));
2853 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002854 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002855 DEBUG(cerr << "\n");
2856
2857 return Op0;
2858 }
2859 }
2860 break;
2861 }
2862 case SPUISD::SHLQUAD_L_BITS:
2863 case SPUISD::SHLQUAD_L_BYTES:
2864 case SPUISD::VEC_SHL:
2865 case SPUISD::VEC_SRL:
2866 case SPUISD::VEC_SRA:
2867 case SPUISD::ROTQUAD_RZ_BYTES:
2868 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002869 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002870
2871 if (isa<ConstantSDNode>(Op1)) {
2872 // Kill degenerate vector shifts:
2873 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2874
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002875 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002876 Result = Op0;
2877 }
2878 }
2879 break;
2880 }
2881 case SPUISD::PROMOTE_SCALAR: {
2882 switch (Op0.getOpcode()) {
2883 default:
2884 break;
2885 case ISD::ANY_EXTEND:
2886 case ISD::ZERO_EXTEND:
2887 case ISD::SIGN_EXTEND: {
2888 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2889 // <arg>
2890 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002891 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002892 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00002893 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002894 if (Op000.getValueType() == N->getValueType(0)) {
2895 Result = Op000;
2896 }
2897 }
2898 break;
2899 }
2900 case SPUISD::EXTRACT_ELT0: {
2901 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2902 // <arg>
2903 Result = Op0.getOperand(0);
2904 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002905 }
Scott Michela59d4692008-02-23 18:41:37 +00002906 }
2907 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002908 }
2909 }
Scott Michel58c58182008-01-17 20:38:41 +00002910 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002911#if 1
Gabor Greifba36cb52008-08-28 21:40:38 +00002912 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00002913 DEBUG(cerr << "\nReplace.SPU: ");
2914 DEBUG(N->dump(&DAG));
2915 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002916 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002917 DEBUG(cerr << "\n");
2918 }
2919#endif
2920
2921 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002922}
2923
2924//===----------------------------------------------------------------------===//
2925// Inline Assembly Support
2926//===----------------------------------------------------------------------===//
2927
2928/// getConstraintType - Given a constraint letter, return the type of
2929/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002930SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002931SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2932 if (ConstraintLetter.size() == 1) {
2933 switch (ConstraintLetter[0]) {
2934 default: break;
2935 case 'b':
2936 case 'r':
2937 case 'f':
2938 case 'v':
2939 case 'y':
2940 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002941 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002942 }
2943 return TargetLowering::getConstraintType(ConstraintLetter);
2944}
2945
Scott Michel5af8f0e2008-07-16 17:17:29 +00002946std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002947SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002948 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002949{
2950 if (Constraint.size() == 1) {
2951 // GCC RS6000 Constraint Letters
2952 switch (Constraint[0]) {
2953 case 'b': // R1-R31
2954 case 'r': // R0-R31
2955 if (VT == MVT::i64)
2956 return std::make_pair(0U, SPU::R64CRegisterClass);
2957 return std::make_pair(0U, SPU::R32CRegisterClass);
2958 case 'f':
2959 if (VT == MVT::f32)
2960 return std::make_pair(0U, SPU::R32FPRegisterClass);
2961 else if (VT == MVT::f64)
2962 return std::make_pair(0U, SPU::R64FPRegisterClass);
2963 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002964 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002965 return std::make_pair(0U, SPU::GPRCRegisterClass);
2966 }
2967 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002968
Scott Michel266bc8f2007-12-04 22:23:35 +00002969 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2970}
2971
Scott Michela59d4692008-02-23 18:41:37 +00002972//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002973void
Dan Gohman475871a2008-07-27 21:46:04 +00002974SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002975 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002976 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002977 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002978 const SelectionDAG &DAG,
2979 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002980#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002981 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002982#endif
Scott Michela59d4692008-02-23 18:41:37 +00002983
2984 switch (Op.getOpcode()) {
2985 default:
2986 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2987 break;
2988
2989#if 0
2990 case CALL:
2991 case SHUFB:
2992 case INSERT_MASK:
2993 case CNTB:
2994#endif
2995
2996 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00002997 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002998 MVT Op0VT = Op0.getValueType();
2999 unsigned Op0VTBits = Op0VT.getSizeInBits();
3000 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003001 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3002 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003003 break;
3004 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003005
Scott Michela59d4692008-02-23 18:41:37 +00003006 case SPUISD::LDRESULT:
3007 case SPUISD::EXTRACT_ELT0:
3008 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00003009 MVT OpVT = Op.getValueType();
3010 unsigned OpVTBits = OpVT.getSizeInBits();
3011 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003012 KnownZero |= APInt(OpVTBits, ~InMask, false);
3013 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003014 break;
3015 }
3016
3017#if 0
3018 case EXTRACT_I1_ZEXT:
3019 case EXTRACT_I1_SEXT:
3020 case EXTRACT_I8_ZEXT:
3021 case EXTRACT_I8_SEXT:
3022 case MPY:
3023 case MPYU:
3024 case MPYH:
3025 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003026 case SPUISD::SHLQUAD_L_BITS:
3027 case SPUISD::SHLQUAD_L_BYTES:
3028 case SPUISD::VEC_SHL:
3029 case SPUISD::VEC_SRL:
3030 case SPUISD::VEC_SRA:
3031 case SPUISD::VEC_ROTL:
3032 case SPUISD::VEC_ROTR:
3033 case SPUISD::ROTQUAD_RZ_BYTES:
3034 case SPUISD::ROTQUAD_RZ_BITS:
3035 case SPUISD::ROTBYTES_RIGHT_S:
3036 case SPUISD::ROTBYTES_LEFT:
3037 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003038 case SPUISD::SELECT_MASK:
3039 case SPUISD::SELB:
3040 case SPUISD::FPInterp:
3041 case SPUISD::FPRecipEst:
3042 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003043#endif
3044 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003045}
3046
Scott Michel203b2d62008-04-30 00:30:08 +00003047// LowerAsmOperandForConstraint
3048void
Dan Gohman475871a2008-07-27 21:46:04 +00003049SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003050 char ConstraintLetter,
Evan Chengda43bcf2008-09-24 00:05:32 +00003051 bool hasMemory,
Dan Gohman475871a2008-07-27 21:46:04 +00003052 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003053 SelectionDAG &DAG) const {
3054 // Default, for the time being, to the base class handler
Evan Chengda43bcf2008-09-24 00:05:32 +00003055 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3056 Ops, DAG);
Scott Michel203b2d62008-04-30 00:30:08 +00003057}
3058
Scott Michel266bc8f2007-12-04 22:23:35 +00003059/// isLegalAddressImmediate - Return true if the integer value can be used
3060/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003061bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3062 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003063 // SPU's addresses are 256K:
3064 return (V > -(1 << 18) && V < (1 << 18) - 1);
3065}
3066
3067bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003068 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003069}
Dan Gohman6520e202008-10-18 02:06:02 +00003070
3071bool
3072SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3073 // The SPU target isn't yet aware of offsets.
3074 return false;
3075}