blob: 659ba7530d079e2f73f432f05e9090d14957121e [file] [log] [blame]
Scott Michel266bc8f2007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel266bc8f2007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SPUTargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPURegisterNames.h"
15#include "SPUISelLowering.h"
16#include "SPUTargetMachine.h"
Scott Michel203b2d62008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000018#include "llvm/ADT/VectorExtras.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000019#include "llvm/CodeGen/CallingConvLower.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner84bc5422007-12-31 04:13:23 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000025#include "llvm/Constants.h"
26#include "llvm/Function.h"
27#include "llvm/Intrinsics.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/MathExtras.h"
30#include "llvm/Target/TargetOptions.h"
31
32#include <map>
33
34using namespace llvm;
35
36// Used in getTargetNodeName() below
37namespace {
38 std::map<unsigned, const char *> node_names;
39
Duncan Sands83ec4b62008-06-06 12:08:01 +000040 //! MVT mapping to useful data for Cell SPU
Scott Michel266bc8f2007-12-04 22:23:35 +000041 struct valtype_map_s {
Duncan Sands83ec4b62008-06-06 12:08:01 +000042 const MVT valtype;
Scott Michel7f9ba9b2008-01-30 02:55:46 +000043 const int prefslot_byte;
Scott Michel266bc8f2007-12-04 22:23:35 +000044 };
Scott Michel5af8f0e2008-07-16 17:17:29 +000045
Scott Michel266bc8f2007-12-04 22:23:35 +000046 const valtype_map_s valtype_map[] = {
47 { MVT::i1, 3 },
48 { MVT::i8, 3 },
49 { MVT::i16, 2 },
50 { MVT::i32, 0 },
51 { MVT::f32, 0 },
52 { MVT::i64, 0 },
53 { MVT::f64, 0 },
54 { MVT::i128, 0 }
55 };
56
57 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
58
Duncan Sands83ec4b62008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel266bc8f2007-12-04 22:23:35 +000060 const valtype_map_s *retval = 0;
61
62 for (size_t i = 0; i < n_valtype_map; ++i) {
63 if (valtype_map[i].valtype == VT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel266bc8f2007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands83ec4b62008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +000074 abort();
75 }
76#endif
77
78 return retval;
79 }
80
81 //! Predicate that returns true if operand is a memory target
82 /*!
83 \arg Op Operand to test
84 \return true if the operand is a memory target (i.e., global
Scott Michel9de5d0d2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel266bc8f2007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman475871a2008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel266bc8f2007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
Bill Wendling056292f2008-09-16 21:48:12 +000095 || Opc == ISD::ExternalSymbol
Scott Michel266bc8f2007-12-04 22:23:35 +000096 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
Bill Wendling056292f2008-09-16 21:48:12 +0000100 || Opc == ISD::TargetExternalSymbol
Scott Michel9de5d0d2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000102 }
Scott Michel58c58182008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman475871a2008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel58c58182008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel58c58182008-01-17 20:38:41 +0000110 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000111}
112
113SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
114 : TargetLowering(TM),
115 SPUTM(TM)
116{
117 // Fold away setcc operations if possible.
118 setPow2DivIsCheap();
119
120 // Use _setjmp/_longjmp instead of setjmp/longjmp.
121 setUseUnderscoreSetJmp(true);
122 setUseUnderscoreLongJmp(true);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000123
Scott Michel266bc8f2007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel504c3692007-12-17 22:32:34 +0000125 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
126 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
127 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
128 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
129 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
130 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel266bc8f2007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000132
Scott Michel266bc8f2007-12-04 22:23:35 +0000133 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng03294662008-10-14 21:26:46 +0000134 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
135 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
136 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Chris Lattnerddf89562008-01-17 19:59:44 +0000137 setTruncStoreAction(MVT::i8, MVT::i1, Custom);
138 setTruncStoreAction(MVT::i16, MVT::i1, Custom);
139 setTruncStoreAction(MVT::i32, MVT::i1, Custom);
140 setTruncStoreAction(MVT::i64, MVT::i1, Custom);
141 setTruncStoreAction(MVT::i128, MVT::i1, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000142
Evan Cheng03294662008-10-14 21:26:46 +0000143 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
144 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
145 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Chris Lattnerddf89562008-01-17 19:59:44 +0000146 setTruncStoreAction(MVT::i8 , MVT::i8, Custom);
147 setTruncStoreAction(MVT::i16 , MVT::i8, Custom);
148 setTruncStoreAction(MVT::i32 , MVT::i8, Custom);
149 setTruncStoreAction(MVT::i64 , MVT::i8, Custom);
150 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000151
Evan Cheng03294662008-10-14 21:26:46 +0000152 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
153 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
154 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000155
156 // SPU constant load actions are custom lowered:
157 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begemanccef5802008-02-14 18:43:04 +0000158 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000159 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
160
161 // SPU's loads and stores have to be custom lowered:
162 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
163 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000164 MVT VT = (MVT::SimpleValueType)sctype;
165
166 setOperationAction(ISD::LOAD, VT, Custom);
167 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000168 }
169
Scott Michel58c58182008-01-17 20:38:41 +0000170 // Custom lower BRCOND for i1, i8 to "promote" the result to
171 // i32 and i16, respectively.
172 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000173
174 // Expand the jumptable branches
175 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
176 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000177 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000178
179 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000180 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
181
Scott Michel266bc8f2007-12-04 22:23:35 +0000182 // PowerPC has no SREM/UREM instructions
183 setOperationAction(ISD::SREM, MVT::i32, Expand);
184 setOperationAction(ISD::UREM, MVT::i32, Expand);
185 setOperationAction(ISD::SREM, MVT::i64, Expand);
186 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000187
Scott Michel266bc8f2007-12-04 22:23:35 +0000188 // We don't support sin/cos/sqrt/fmod
189 setOperationAction(ISD::FSIN , MVT::f64, Expand);
190 setOperationAction(ISD::FCOS , MVT::f64, Expand);
191 setOperationAction(ISD::FREM , MVT::f64, Expand);
192 setOperationAction(ISD::FSIN , MVT::f32, Expand);
193 setOperationAction(ISD::FCOS , MVT::f32, Expand);
194 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000195
Scott Michel266bc8f2007-12-04 22:23:35 +0000196 // If we're enabling GP optimizations, use hardware square root
197 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
198 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000199
Scott Michel266bc8f2007-12-04 22:23:35 +0000200 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
201 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
202
203 // SPU can do rotate right and left, so legalize it... but customize for i8
204 // because instructions don't exist.
Bill Wendling9440e352008-08-31 02:59:23 +0000205
206 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
207 // .td files.
208 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
209 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
210 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
211
Scott Michel266bc8f2007-12-04 22:23:35 +0000212 setOperationAction(ISD::ROTL, MVT::i32, Legal);
213 setOperationAction(ISD::ROTL, MVT::i16, Legal);
214 setOperationAction(ISD::ROTL, MVT::i8, Custom);
215 // SPU has no native version of shift left/right for i8
216 setOperationAction(ISD::SHL, MVT::i8, Custom);
217 setOperationAction(ISD::SRL, MVT::i8, Custom);
218 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michela59d4692008-02-23 18:41:37 +0000219 // And SPU needs custom lowering for shift left/right for i64
220 setOperationAction(ISD::SHL, MVT::i64, Custom);
221 setOperationAction(ISD::SRL, MVT::i64, Custom);
222 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000223
Scott Michel5af8f0e2008-07-16 17:17:29 +0000224 // Custom lower i8, i32 and i64 multiplications
225 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000226 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000227 setOperationAction(ISD::MUL, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000228
Scott Michel8bf61e82008-06-02 22:18:03 +0000229 // Need to custom handle (some) common i8, i64 math ops
230 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000231 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel8bf61e82008-06-02 22:18:03 +0000232 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000233
Scott Michel266bc8f2007-12-04 22:23:35 +0000234 // SPU does not have BSWAP. It does have i32 support CTLZ.
235 // CTPOP has to be custom lowered.
236 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
237 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
238
239 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
240 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
241 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
242 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
243
244 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
245 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
246
247 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000248
Scott Michel8bf61e82008-06-02 22:18:03 +0000249 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000250 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000251 setOperationAction(ISD::SELECT, MVT::i1, Promote);
252 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000253 setOperationAction(ISD::SELECT, MVT::i16, Legal);
254 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000255 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000256
Scott Michel78c47fa2008-03-10 16:58:52 +0000257 setOperationAction(ISD::SETCC, MVT::i1, Promote);
258 setOperationAction(ISD::SETCC, MVT::i8, Legal);
259 setOperationAction(ISD::SETCC, MVT::i16, Legal);
260 setOperationAction(ISD::SETCC, MVT::i32, Legal);
261 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michelad2715e2008-03-05 23:02:02 +0000262
Scott Michela59d4692008-02-23 18:41:37 +0000263 // Zero extension and sign extension for i64 have to be
264 // custom legalized
265 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
266 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
267 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000268
Scott Michel266bc8f2007-12-04 22:23:35 +0000269 // SPU has a legal FP -> signed INT instruction
270 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
271 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
272 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
273 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
274
275 // FDIV on SPU requires custom lowering
276 setOperationAction(ISD::FDIV, MVT::f32, Custom);
277 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
278
279 // SPU has [U|S]INT_TO_FP
280 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
281 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
282 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
283 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
284 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
285 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
286 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
287 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
288
Scott Michel86c041f2007-12-20 00:44:13 +0000289 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
290 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
291 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
292 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000293
294 // We cannot sextinreg(i1). Expand to shifts.
295 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000296
Scott Michel266bc8f2007-12-04 22:23:35 +0000297 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000298 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000299 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000300
301 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000302 // appropriate instructions to materialize the address.
Scott Michel053c1da2008-01-29 02:16:57 +0000303 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
304 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000305 MVT VT = (MVT::SimpleValueType)sctype;
306
307 setOperationAction(ISD::GlobalAddress, VT, Custom);
308 setOperationAction(ISD::ConstantPool, VT, Custom);
309 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000310 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000311
312 // RET must be custom lowered, to meet ABI requirements
313 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000314
Scott Michel266bc8f2007-12-04 22:23:35 +0000315 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
316 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000317
Scott Michel266bc8f2007-12-04 22:23:35 +0000318 // Use the default implementation.
319 setOperationAction(ISD::VAARG , MVT::Other, Expand);
320 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
321 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000322 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000323 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
324 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
325 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
326
327 // Cell SPU has instructions for converting between i64 and fp.
328 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
329 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000330
Scott Michel266bc8f2007-12-04 22:23:35 +0000331 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
332 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
333
334 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
335 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
336
337 // First set operation action for all vector types to expand. Then we
338 // will selectively turn on ones that can be effectively codegen'd.
339 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
340 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
341 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
342 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
343 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
344 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
345
Duncan Sands83ec4b62008-06-06 12:08:01 +0000346 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
347 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
348 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000349
Duncan Sands83ec4b62008-06-06 12:08:01 +0000350 // add/sub are legal for all supported vector VT's.
351 setOperationAction(ISD::ADD , VT, Legal);
352 setOperationAction(ISD::SUB , VT, Legal);
353 // mul has to be custom lowered.
354 setOperationAction(ISD::MUL , VT, Custom);
355
356 setOperationAction(ISD::AND , VT, Legal);
357 setOperationAction(ISD::OR , VT, Legal);
358 setOperationAction(ISD::XOR , VT, Legal);
359 setOperationAction(ISD::LOAD , VT, Legal);
360 setOperationAction(ISD::SELECT, VT, Legal);
361 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000362
Scott Michel266bc8f2007-12-04 22:23:35 +0000363 // These operations need to be expanded:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000364 setOperationAction(ISD::SDIV, VT, Expand);
365 setOperationAction(ISD::SREM, VT, Expand);
366 setOperationAction(ISD::UDIV, VT, Expand);
367 setOperationAction(ISD::UREM, VT, Expand);
368 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000369
370 // Custom lower build_vector, constant pool spills, insert and
371 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000372 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
373 setOperationAction(ISD::ConstantPool, VT, Custom);
374 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
375 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
376 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
377 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000378 }
379
380 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
381 setOperationAction(ISD::AND, MVT::v16i8, Custom);
382 setOperationAction(ISD::OR, MVT::v16i8, Custom);
383 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
384 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000385
Scott Michel266bc8f2007-12-04 22:23:35 +0000386 setShiftAmountType(MVT::i32);
387 setSetCCResultContents(ZeroOrOneSetCCResult);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000388
Scott Michel266bc8f2007-12-04 22:23:35 +0000389 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000390
Scott Michel266bc8f2007-12-04 22:23:35 +0000391 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000392 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000393 setTargetDAGCombine(ISD::ZERO_EXTEND);
394 setTargetDAGCombine(ISD::SIGN_EXTEND);
395 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000396
Scott Michel266bc8f2007-12-04 22:23:35 +0000397 computeRegisterProperties();
398}
399
400const char *
401SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
402{
403 if (node_names.empty()) {
404 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
405 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
406 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
407 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000408 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000409 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000410 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
411 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
412 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
413 node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
414 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
415 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
416 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
Gabor Greif93c53e52008-08-31 15:37:04 +0000417 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED]
418 = "SPUISD::EXTRACT_ELT0_CHAINED";
Scott Michel266bc8f2007-12-04 22:23:35 +0000419 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
420 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
421 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
422 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
423 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
424 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
425 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
426 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michela59d4692008-02-23 18:41:37 +0000427 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
428 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000429 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
430 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
431 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
432 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
433 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michela59d4692008-02-23 18:41:37 +0000434 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
435 "SPUISD::ROTQUAD_RZ_BYTES";
436 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
437 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel266bc8f2007-12-04 22:23:35 +0000438 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
439 "SPUISD::ROTBYTES_RIGHT_S";
440 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
441 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
442 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel8bf61e82008-06-02 22:18:03 +0000443 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
444 "SPUISD::ROTBYTES_LEFT_BITS";
445 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000446 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000447 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
448 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
449 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
450 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000451 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
452 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
453 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
454 }
455
456 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
457
458 return ((i != node_names.end()) ? i->second : 0);
459}
460
Dan Gohman475871a2008-07-27 21:46:04 +0000461MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000462 MVT VT = Op.getValueType();
463 if (VT.isInteger())
Scott Michel405fba12008-03-10 23:49:09 +0000464 return VT;
465 else
466 return MVT::i32;
Scott Michel78c47fa2008-03-10 16:58:52 +0000467}
468
Scott Michel266bc8f2007-12-04 22:23:35 +0000469//===----------------------------------------------------------------------===//
470// Calling convention code:
471//===----------------------------------------------------------------------===//
472
473#include "SPUGenCallingConv.inc"
474
475//===----------------------------------------------------------------------===//
476// LowerOperation implementation
477//===----------------------------------------------------------------------===//
478
Scott Michel9de5d0d2008-01-11 02:53:15 +0000479/// Aligned load common code for CellSPU
480/*!
481 \param[in] Op The SelectionDAG load or store operand
482 \param[in] DAG The selection DAG
483 \param[in] ST CellSPU subtarget information structure
484 \param[in,out] alignment Caller initializes this to the load or store node's
485 value from getAlignment(), may be updated while generating the aligned load
486 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
487 offset (divisible by 16, modulo 16 == 0)
488 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
489 offset of the preferred slot (modulo 16 != 0)
490 \param[in,out] VT Caller initializes this value type to the the load or store
491 node's loaded or stored value type; may be updated if an i1-extended load or
492 store.
493 \param[out] was16aligned true if the base pointer had 16-byte alignment,
494 otherwise false. Can help to determine if the chunk needs to be rotated.
495
496 Both load and store lowering load a block of data aligned on a 16-byte
497 boundary. This is the common aligned load code shared between both.
498 */
Dan Gohman475871a2008-07-27 21:46:04 +0000499static SDValue
500AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Michel9de5d0d2008-01-11 02:53:15 +0000501 LSBaseSDNode *LSN,
502 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000503 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000504{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000505 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000506 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman475871a2008-07-27 21:46:04 +0000507 SDValue basePtr = LSN->getBasePtr();
508 SDValue chain = LSN->getChain();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000509
510 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000511 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000512
Gabor Greif93c53e52008-08-31 15:37:04 +0000513 if (Op1.getOpcode() == ISD::Constant
514 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000515 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000516
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000517 alignOffs = (int) CN->getZExtValue();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000518 prefSlotOffs = (int) (alignOffs & 0xf);
519
520 // Adjust the rotation amount to ensure that the final result ends up in
521 // the preferred slot:
522 prefSlotOffs -= vtm->prefslot_byte;
523 basePtr = basePtr.getOperand(0);
524
Scott Michel58c58182008-01-17 20:38:41 +0000525 // Loading from memory, can we adjust alignment?
526 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +0000527 SDValue APtr = basePtr.getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000528 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
529 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
530 alignment = GSDN->getGlobal()->getAlignment();
531 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000532 }
533 } else {
534 alignOffs = 0;
535 prefSlotOffs = -vtm->prefslot_byte;
536 }
Scott Michel203b2d62008-04-30 00:30:08 +0000537 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
538 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
539 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
540 prefSlotOffs = (int) (alignOffs & 0xf);
541 prefSlotOffs -= vtm->prefslot_byte;
542 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000543 } else {
544 alignOffs = 0;
545 prefSlotOffs = -vtm->prefslot_byte;
546 }
547
548 if (alignment == 16) {
549 // Realign the base pointer as a D-Form address:
550 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000551 basePtr = DAG.getNode(ISD::ADD, PtrVT,
552 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000553 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000554 }
555
556 // Emit the vector load:
557 was16aligned = true;
558 return DAG.getLoad(MVT::v16i8, chain, basePtr,
559 LSN->getSrcValue(), LSN->getSrcValueOffset(),
560 LSN->isVolatile(), 16);
561 }
562
563 // Unaligned load or we're using the "large memory" model, which means that
564 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000565 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greif93c53e52008-08-31 15:37:04 +0000566 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
567 DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000568 }
569
570 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000571 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000572 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000573 was16aligned = false;
574 return DAG.getLoad(MVT::v16i8, chain, basePtr,
575 LSN->getSrcValue(), LSN->getSrcValueOffset(),
576 LSN->isVolatile(), 16);
577}
578
Scott Michel266bc8f2007-12-04 22:23:35 +0000579/// Custom lower loads for CellSPU
580/*!
581 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
582 within a 16-byte block, we have to rotate to extract the requested element.
583 */
Dan Gohman475871a2008-07-27 21:46:04 +0000584static SDValue
585LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000586 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000587 SDValue the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000588 MVT VT = LN->getMemoryVT();
Gabor Greifba36cb52008-08-28 21:40:38 +0000589 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000590 ISD::LoadExtType ExtType = LN->getExtensionType();
591 unsigned alignment = LN->getAlignment();
Dan Gohman475871a2008-07-27 21:46:04 +0000592 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000593
Scott Michel266bc8f2007-12-04 22:23:35 +0000594 switch (LN->getAddressingMode()) {
595 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000596 int offset, rotamt;
597 bool was16aligned;
Dan Gohman475871a2008-07-27 21:46:04 +0000598 SDValue result =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000599 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000600
Gabor Greifba36cb52008-08-28 21:40:38 +0000601 if (result.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000602 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000603
604 the_chain = result.getValue(1);
605 // Rotate the chunk if necessary
606 if (rotamt < 0)
607 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000608 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000609 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
610
Scott Michel58c58182008-01-17 20:38:41 +0000611 Ops[0] = the_chain;
612 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000613 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000614 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
615 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000616 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000617 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000618 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000619 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000620 }
621
622 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
623 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000624 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000625
626 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
627 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000628 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000629
Scott Michel9de5d0d2008-01-11 02:53:15 +0000630 // Convert the loaded v16i8 vector to the appropriate vector type
631 // specified by the operand:
632 if (OpVT == VT) {
633 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000634 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000635 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000636 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000637
638 Ops[0] = the_chain;
639 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
640 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
641 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
642 the_chain = result.getValue(1);
643 } else {
644 // Handle the sign and zero-extending loads for i1 and i8:
645 unsigned NewOpC;
646
647 if (ExtType == ISD::SEXTLOAD) {
648 NewOpC = (OpVT == MVT::i1
649 ? SPUISD::EXTRACT_I1_SEXT
650 : SPUISD::EXTRACT_I8_SEXT);
651 } else {
652 assert(ExtType == ISD::ZEXTLOAD);
653 NewOpC = (OpVT == MVT::i1
654 ? SPUISD::EXTRACT_I1_ZEXT
655 : SPUISD::EXTRACT_I8_ZEXT);
656 }
657
658 result = DAG.getNode(NewOpC, OpVT, result);
659 }
660
661 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000662 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000663 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000664 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000665 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000666
Scott Michel58c58182008-01-17 20:38:41 +0000667 result = DAG.getNode(SPUISD::LDRESULT, retvts,
668 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000669 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000670 }
671 case ISD::PRE_INC:
672 case ISD::PRE_DEC:
673 case ISD::POST_INC:
674 case ISD::POST_DEC:
675 case ISD::LAST_INDEXED_MODE:
676 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
677 "UNINDEXED\n";
678 cerr << (unsigned) LN->getAddressingMode() << "\n";
679 abort();
680 /*NOTREACHED*/
681 }
682
Dan Gohman475871a2008-07-27 21:46:04 +0000683 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000684}
685
686/// Custom lower stores for CellSPU
687/*!
688 All CellSPU stores are aligned to 16-byte boundaries, so for elements
689 within a 16-byte block, we have to generate a shuffle to insert the
690 requested element into its place, then store the resulting block.
691 */
Dan Gohman475871a2008-07-27 21:46:04 +0000692static SDValue
693LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000694 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000695 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000696 MVT VT = Value.getValueType();
697 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
698 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000699 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000700
701 switch (SN->getAddressingMode()) {
702 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000703 int chunk_offset, slot_offset;
704 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000705
706 // The vector type we really want to load from the 16-byte chunk, except
707 // in the case of MVT::i1, which has to be v16i8.
Duncan Sands83ec4b62008-06-06 12:08:01 +0000708 MVT vecVT, stVecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000709
Scott Michel266bc8f2007-12-04 22:23:35 +0000710 if (StVT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000711 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
712 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000713
Dan Gohman475871a2008-07-27 21:46:04 +0000714 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000715 AlignedLoad(Op, DAG, ST, SN, alignment,
716 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000717
Gabor Greifba36cb52008-08-28 21:40:38 +0000718 if (alignLoadVec.getNode() == 0)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000719 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000720
Scott Michel9de5d0d2008-01-11 02:53:15 +0000721 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000722 SDValue basePtr = LN->getBasePtr();
723 SDValue the_chain = alignLoadVec.getValue(1);
724 SDValue theValue = SN->getValue();
725 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000726
727 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000728 && (theValue.getOpcode() == ISD::AssertZext
729 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000730 // Drill down and get the value for zero- and sign-extended
731 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000732 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000733 }
734
Scott Michel9de5d0d2008-01-11 02:53:15 +0000735 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000736
Dan Gohman475871a2008-07-27 21:46:04 +0000737 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
738 SDValue insertEltPtr;
739 SDValue insertEltOp;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000740
741 // If the base pointer is already a D-form address, then just create
742 // a new D-form address with a slot offset and the orignal base pointer.
743 // Otherwise generate a D-form address with the slot offset relative
744 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000745 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greifba36cb52008-08-28 21:40:38 +0000746 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michel497e8882008-01-11 21:01:19 +0000747 DEBUG(cerr << "\n");
748
Scott Michel053c1da2008-01-29 02:16:57 +0000749 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
750 (basePtr.getOpcode() == ISD::ADD
751 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000752 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000753 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000754 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000755 }
756
757 insertEltOp = DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000758 result = DAG.getNode(SPUISD::SHUFB, vecVT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000759 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue),
760 alignLoadVec,
761 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000762
Scott Michel9de5d0d2008-01-11 02:53:15 +0000763 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000764 LN->getSrcValue(), LN->getSrcValueOffset(),
765 LN->isVolatile(), LN->getAlignment());
766
767 return result;
768 /*UNREACHED*/
769 }
770 case ISD::PRE_INC:
771 case ISD::PRE_DEC:
772 case ISD::POST_INC:
773 case ISD::POST_DEC:
774 case ISD::LAST_INDEXED_MODE:
775 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
776 "UNINDEXED\n";
777 cerr << (unsigned) SN->getAddressingMode() << "\n";
778 abort();
779 /*NOTREACHED*/
780 }
781
Dan Gohman475871a2008-07-27 21:46:04 +0000782 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000783}
784
785/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000786static SDValue
787LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000788 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000789 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
790 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000791 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
792 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000793 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000794
795 if (TM.getRelocationModel() == Reloc::Static) {
796 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000797 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000798 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000799 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000800 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
801 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000802 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000803 }
804 }
805
806 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000807 "LowerConstantPool: Relocation model other than static"
808 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000809 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000810}
811
Dan Gohman475871a2008-07-27 21:46:04 +0000812static SDValue
813LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000814 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000815 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000816 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
817 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000818 const TargetMachine &TM = DAG.getTarget();
819
820 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000821 if (!ST->usingLargeMem()) {
822 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
823 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000824 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
825 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000826 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
827 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000828 }
829
830 assert(0 &&
831 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000832 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000833}
834
Dan Gohman475871a2008-07-27 21:46:04 +0000835static SDValue
836LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000837 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000838 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
839 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000840 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000841 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000842 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000843
Scott Michel266bc8f2007-12-04 22:23:35 +0000844 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000845 if (!ST->usingLargeMem()) {
846 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
847 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000848 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
849 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000850 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
851 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000852 } else {
853 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000854 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000855 abort();
856 /*NOTREACHED*/
857 }
858
Dan Gohman475871a2008-07-27 21:46:04 +0000859 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000860}
861
862//! Custom lower i64 integer constants
863/*!
864 This code inserts all of the necessary juggling that needs to occur to load
865 a 64-bit constant into a register.
866 */
Dan Gohman475871a2008-07-27 21:46:04 +0000867static SDValue
868LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000869 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000870 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000871
872 if (VT == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000873 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +0000874 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000875 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000876 } else {
877 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000878 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000879 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000880 abort();
881 /*NOTREACHED*/
882 }
883
Dan Gohman475871a2008-07-27 21:46:04 +0000884 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000885}
886
Nate Begemanccef5802008-02-14 18:43:04 +0000887//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000888static SDValue
889LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000890 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000891 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000892
893 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000894 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000895
Nate Begemanccef5802008-02-14 18:43:04 +0000896 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000897 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000898 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000899 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000900 }
901
Dan Gohman475871a2008-07-27 21:46:04 +0000902 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000903}
904
Scott Michel58c58182008-01-17 20:38:41 +0000905//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000906static SDValue
907LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000908{
Dan Gohman475871a2008-07-27 21:46:04 +0000909 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000910 MVT CondVT = Cond.getValueType();
911 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000912
913 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
914 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
915 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
916 Op.getOperand(0),
917 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
918 Op.getOperand(2));
919 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000920 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000921}
922
Dan Gohman475871a2008-07-27 21:46:04 +0000923static SDValue
924LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000925{
926 MachineFunction &MF = DAG.getMachineFunction();
927 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000928 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +0000929 SmallVector<SDValue, 8> ArgValues;
930 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000931 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000932
933 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
934 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000935
Scott Michel266bc8f2007-12-04 22:23:35 +0000936 unsigned ArgOffset = SPUFrameInfo::minStackSize();
937 unsigned ArgRegIdx = 0;
938 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000939
Duncan Sands83ec4b62008-06-06 12:08:01 +0000940 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000941
Scott Michel266bc8f2007-12-04 22:23:35 +0000942 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000943 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
944 ArgNo != e; ++ArgNo) {
Dan Gohman475871a2008-07-27 21:46:04 +0000945 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000946 bool needsLoad = false;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000947 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
948 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michel266bc8f2007-12-04 22:23:35 +0000949
Duncan Sands83ec4b62008-06-06 12:08:01 +0000950 switch (ObjectVT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000951 default: {
952 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000953 << ObjectVT.getMVTString()
Scott Michel266bc8f2007-12-04 22:23:35 +0000954 << "\n";
955 abort();
956 }
957 case MVT::i8:
958 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000959 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R8CRegClass);
960 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000961 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i8);
962 ++ArgRegIdx;
963 } else {
964 needsLoad = true;
965 }
966 break;
967 case MVT::i16:
968 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000969 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
970 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000971 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i16);
972 ++ArgRegIdx;
973 } else {
974 needsLoad = true;
975 }
976 break;
977 case MVT::i32:
978 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000979 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
980 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000981 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
982 ++ArgRegIdx;
983 } else {
984 needsLoad = true;
985 }
986 break;
987 case MVT::i64:
988 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000989 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64CRegClass);
990 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000991 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64);
992 ++ArgRegIdx;
993 } else {
994 needsLoad = true;
995 }
996 break;
997 case MVT::f32:
998 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000999 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
1000 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001001 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f32);
1002 ++ArgRegIdx;
1003 } else {
1004 needsLoad = true;
1005 }
1006 break;
1007 case MVT::f64:
1008 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001009 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64FPRegClass);
1010 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001011 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f64);
1012 ++ArgRegIdx;
1013 } else {
1014 needsLoad = true;
1015 }
1016 break;
1017 case MVT::v2f64:
1018 case MVT::v4f32:
Scott Michelad2715e2008-03-05 23:02:02 +00001019 case MVT::v2i64:
Scott Michel266bc8f2007-12-04 22:23:35 +00001020 case MVT::v4i32:
1021 case MVT::v8i16:
1022 case MVT::v16i8:
1023 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001024 unsigned VReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1025 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001026 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1027 ++ArgRegIdx;
1028 } else {
1029 needsLoad = true;
1030 }
1031 break;
1032 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001033
Scott Michel266bc8f2007-12-04 22:23:35 +00001034 // We need to load the argument to a virtual register if we determined above
1035 // that we ran out of physical registers of the appropriate type
1036 if (needsLoad) {
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001037 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001038 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001039 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001040 ArgOffset += StackSlotSize;
1041 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001042
Scott Michel266bc8f2007-12-04 22:23:35 +00001043 ArgValues.push_back(ArgVal);
1044 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001045
Scott Michel266bc8f2007-12-04 22:23:35 +00001046 // If the function takes variable number of arguments, make a frame index for
1047 // the start of the first vararg value... for expansion of llvm.va_start.
1048 if (isVarArg) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001049 VarArgsFrameIndex = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8,
Scott Michel266bc8f2007-12-04 22:23:35 +00001050 ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001051 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001052 // If this function is vararg, store any remaining integer argument regs to
1053 // their spots on the stack so that they may be loaded by deferencing the
1054 // result of va_next.
Dan Gohman475871a2008-07-27 21:46:04 +00001055 SmallVector<SDValue, 8> MemOps;
Scott Michel266bc8f2007-12-04 22:23:35 +00001056 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001057 unsigned VReg = RegInfo.createVirtualRegister(&SPU::GPRCRegClass);
1058 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Dan Gohman475871a2008-07-27 21:46:04 +00001059 SDValue Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
1060 SDValue Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001061 MemOps.push_back(Store);
1062 // Increment the address by four for the next argument to store
Dan Gohman475871a2008-07-27 21:46:04 +00001063 SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001064 FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
1065 }
1066 if (!MemOps.empty())
1067 Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
1068 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001069
Scott Michel266bc8f2007-12-04 22:23:35 +00001070 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001071
Scott Michel266bc8f2007-12-04 22:23:35 +00001072 // Return the new list of results.
Gabor Greifba36cb52008-08-28 21:40:38 +00001073 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf9516202008-06-30 10:19:09 +00001074 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001075}
1076
1077/// isLSAAddress - Return the immediate to use if the specified
1078/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001079static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001080 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
1081 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001082
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001083 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001084 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1085 (Addr << 14 >> 14) != Addr)
1086 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001087
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001088 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001089}
1090
1091static
Dan Gohman475871a2008-07-27 21:46:04 +00001092SDValue
1093LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman095cc292008-09-13 01:54:27 +00001094 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1095 SDValue Chain = TheCall->getChain();
Scott Michel266bc8f2007-12-04 22:23:35 +00001096#if 0
Dan Gohman095cc292008-09-13 01:54:27 +00001097 bool isVarArg = TheCall->isVarArg();
1098 bool isTailCall = TheCall->isTailCall();
Scott Michel266bc8f2007-12-04 22:23:35 +00001099#endif
Dan Gohman095cc292008-09-13 01:54:27 +00001100 SDValue Callee = TheCall->getCallee();
1101 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001102 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1103 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1104 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1105
1106 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001107 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001108
Scott Michel266bc8f2007-12-04 22:23:35 +00001109 // Accumulate how many bytes are to be pushed on the stack, including the
1110 // linkage area, and parameter passing area. According to the SPU ABI,
1111 // we minimally need space for [LR] and [SP]
1112 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001113
Scott Michel266bc8f2007-12-04 22:23:35 +00001114 // Set up a copy of the stack pointer for use loading and storing any
1115 // arguments that may not fit in the registers available for argument
1116 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001117 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001118
Scott Michel266bc8f2007-12-04 22:23:35 +00001119 // Figure out which arguments are going to go in registers, and which in
1120 // memory.
1121 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1122 unsigned ArgRegIdx = 0;
1123
1124 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001125 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001126 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001127 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001128
1129 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001130 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001131
Scott Michel266bc8f2007-12-04 22:23:35 +00001132 // PtrOff will be used to store the current argument to the stack if a
1133 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001134 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001135 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1136
Duncan Sands83ec4b62008-06-06 12:08:01 +00001137 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001138 default: assert(0 && "Unexpected ValueType for argument!");
1139 case MVT::i32:
1140 case MVT::i64:
1141 case MVT::i128:
1142 if (ArgRegIdx != NumArgRegs) {
1143 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1144 } else {
1145 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001146 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001147 }
1148 break;
1149 case MVT::f32:
1150 case MVT::f64:
1151 if (ArgRegIdx != NumArgRegs) {
1152 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1153 } else {
1154 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001155 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001156 }
1157 break;
1158 case MVT::v4f32:
1159 case MVT::v4i32:
1160 case MVT::v8i16:
1161 case MVT::v16i8:
1162 if (ArgRegIdx != NumArgRegs) {
1163 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1164 } else {
1165 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001166 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001167 }
1168 break;
1169 }
1170 }
1171
1172 // Update number of stack bytes actually used, insert a call sequence start
1173 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnere563bbc2008-10-11 22:08:30 +00001174 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1175 true));
Scott Michel266bc8f2007-12-04 22:23:35 +00001176
1177 if (!MemOpChains.empty()) {
1178 // Adjust the stack pointer for the stack arguments.
1179 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1180 &MemOpChains[0], MemOpChains.size());
1181 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001182
Scott Michel266bc8f2007-12-04 22:23:35 +00001183 // Build a sequence of copy-to-reg nodes chained together with token chain
1184 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001185 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001186 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1187 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1188 InFlag);
1189 InFlag = Chain.getValue(1);
1190 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001191
Dan Gohman475871a2008-07-27 21:46:04 +00001192 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001193 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001194
Bill Wendling056292f2008-09-16 21:48:12 +00001195 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1196 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1197 // node so that legalize doesn't hack it.
Scott Michel266bc8f2007-12-04 22:23:35 +00001198 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1199 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001200 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001201 SDValue Zero = DAG.getConstant(0, PtrVT);
1202 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001203
Scott Michel9de5d0d2008-01-11 02:53:15 +00001204 if (!ST->usingLargeMem()) {
1205 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1206 // style calls, otherwise, external symbols are BRASL calls. This assumes
1207 // that declared/defined symbols are in the same compilation unit and can
1208 // be reached through PC-relative jumps.
1209 //
1210 // NOTE:
1211 // This may be an unsafe assumption for JIT and really large compilation
1212 // units.
1213 if (GV->isDeclaration()) {
1214 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1215 } else {
1216 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1217 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001218 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001219 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1220 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001221 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001222 }
Bill Wendling056292f2008-09-16 21:48:12 +00001223 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
1224 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001225 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001226 // If this is an absolute destination address that appears to be a legal
1227 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001228 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001229 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001230
1231 Ops.push_back(Chain);
1232 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001233
Scott Michel266bc8f2007-12-04 22:23:35 +00001234 // Add argument registers to the end of the list so that they are known live
1235 // into the call.
1236 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001237 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001238 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001239
Gabor Greifba36cb52008-08-28 21:40:38 +00001240 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001241 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001242 // Returns a chain and a flag for retval copy to use.
1243 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1244 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001245 InFlag = Chain.getValue(1);
1246
Chris Lattnere563bbc2008-10-11 22:08:30 +00001247 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1248 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001249 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001250 InFlag = Chain.getValue(1);
1251
Dan Gohman475871a2008-07-27 21:46:04 +00001252 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001253 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001254
Scott Michel266bc8f2007-12-04 22:23:35 +00001255 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001256 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001257 default: assert(0 && "Unexpected ret value!");
1258 case MVT::Other: break;
1259 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001260 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001261 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1262 ResultVals[0] = Chain.getValue(0);
1263 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1264 Chain.getValue(2)).getValue(1);
1265 ResultVals[1] = Chain.getValue(0);
1266 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001267 } else {
1268 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1269 ResultVals[0] = Chain.getValue(0);
1270 NumResults = 1;
1271 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001272 break;
1273 case MVT::i64:
1274 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1275 ResultVals[0] = Chain.getValue(0);
1276 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001277 break;
1278 case MVT::f32:
1279 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001280 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001281 InFlag).getValue(1);
1282 ResultVals[0] = Chain.getValue(0);
1283 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001284 break;
1285 case MVT::v2f64:
1286 case MVT::v4f32:
1287 case MVT::v4i32:
1288 case MVT::v8i16:
1289 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001290 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001291 InFlag).getValue(1);
1292 ResultVals[0] = Chain.getValue(0);
1293 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001294 break;
1295 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001296
Scott Michel266bc8f2007-12-04 22:23:35 +00001297 // If the function returns void, just return the chain.
1298 if (NumResults == 0)
1299 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001300
Scott Michel266bc8f2007-12-04 22:23:35 +00001301 // Otherwise, merge everything together with a MERGE_VALUES node.
1302 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001303 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001304 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001305}
1306
Dan Gohman475871a2008-07-27 21:46:04 +00001307static SDValue
1308LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001309 SmallVector<CCValAssign, 16> RVLocs;
1310 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1311 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1312 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001313 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001314
Scott Michel266bc8f2007-12-04 22:23:35 +00001315 // If this is the first return lowered for this function, add the regs to the
1316 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001317 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001318 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001319 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001320 }
1321
Dan Gohman475871a2008-07-27 21:46:04 +00001322 SDValue Chain = Op.getOperand(0);
1323 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001324
Scott Michel266bc8f2007-12-04 22:23:35 +00001325 // Copy the result values into the output registers.
1326 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1327 CCValAssign &VA = RVLocs[i];
1328 assert(VA.isRegLoc() && "Can only return in registers!");
1329 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1330 Flag = Chain.getValue(1);
1331 }
1332
Gabor Greifba36cb52008-08-28 21:40:38 +00001333 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001334 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1335 else
1336 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1337}
1338
1339
1340//===----------------------------------------------------------------------===//
1341// Vector related lowering:
1342//===----------------------------------------------------------------------===//
1343
1344static ConstantSDNode *
1345getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001346 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001347
Scott Michel266bc8f2007-12-04 22:23:35 +00001348 // Check to see if this buildvec has a single non-undef value in its elements.
1349 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1350 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001351 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001352 OpVal = N->getOperand(i);
1353 else if (OpVal != N->getOperand(i))
1354 return 0;
1355 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001356
Gabor Greifba36cb52008-08-28 21:40:38 +00001357 if (OpVal.getNode() != 0) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001358 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1359 return CN;
1360 }
1361 }
1362
1363 return 0; // All UNDEF: use implicit def.; not Constant node
1364}
1365
1366/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1367/// and the value fits into an unsigned 18-bit constant, and if so, return the
1368/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001369SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001370 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001371 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001372 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001373 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001374 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001375 uint32_t upper = uint32_t(UValue >> 32);
1376 uint32_t lower = uint32_t(UValue);
1377 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001378 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001379 Value = Value >> 32;
1380 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001381 if (Value <= 0x3ffff)
1382 return DAG.getConstant(Value, ValueType);
1383 }
1384
Dan Gohman475871a2008-07-27 21:46:04 +00001385 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001386}
1387
1388/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1389/// and the value fits into a signed 16-bit constant, and if so, return the
1390/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001391SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001392 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001393 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001394 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001395 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001396 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001397 uint32_t upper = uint32_t(UValue >> 32);
1398 uint32_t lower = uint32_t(UValue);
1399 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001400 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001401 Value = Value >> 32;
1402 }
Scott Michelad2715e2008-03-05 23:02:02 +00001403 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
1404 return DAG.getConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001405 }
1406 }
1407
Dan Gohman475871a2008-07-27 21:46:04 +00001408 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001409}
1410
1411/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1412/// and the value fits into a signed 10-bit constant, and if so, return the
1413/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001414SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001415 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001416 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001417 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001418 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001419 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001420 uint32_t upper = uint32_t(UValue >> 32);
1421 uint32_t lower = uint32_t(UValue);
1422 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001423 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001424 Value = Value >> 32;
1425 }
Scott Michelad2715e2008-03-05 23:02:02 +00001426 if (isS10Constant(Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001427 return DAG.getConstant(Value, ValueType);
1428 }
1429
Dan Gohman475871a2008-07-27 21:46:04 +00001430 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001431}
1432
1433/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1434/// and the value fits into a signed 8-bit constant, and if so, return the
1435/// constant.
1436///
1437/// @note: The incoming vector is v16i8 because that's the only way we can load
1438/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1439/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001440SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001441 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001442 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001443 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001444 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001445 && Value <= 0xffff /* truncated from uint64_t */
1446 && ((short) Value >> 8) == ((short) Value & 0xff))
Scott Michel266bc8f2007-12-04 22:23:35 +00001447 return DAG.getConstant(Value & 0xff, ValueType);
1448 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001449 && (Value & 0xff) == Value)
Scott Michel266bc8f2007-12-04 22:23:35 +00001450 return DAG.getConstant(Value, ValueType);
1451 }
1452
Dan Gohman475871a2008-07-27 21:46:04 +00001453 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001454}
1455
1456/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1457/// and the value fits into a signed 16-bit constant, and if so, return the
1458/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001459SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001460 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001461 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001462 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001463 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001464 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1465 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001466 return DAG.getConstant(Value >> 16, ValueType);
1467 }
1468
Dan Gohman475871a2008-07-27 21:46:04 +00001469 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001470}
1471
1472/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001473SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001474 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001475 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001476 }
1477
Dan Gohman475871a2008-07-27 21:46:04 +00001478 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001479}
1480
1481/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001482SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001483 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001484 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001485 }
1486
Dan Gohman475871a2008-07-27 21:46:04 +00001487 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001488}
1489
1490// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001491// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001492// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1493// zero. Return true if this is not an array of constants, false if it is.
1494//
1495static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1496 uint64_t UndefBits[2]) {
1497 // Start with zero'd results.
1498 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001499
Duncan Sands83ec4b62008-06-06 12:08:01 +00001500 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001501 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001502 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001503
Scott Michel266bc8f2007-12-04 22:23:35 +00001504 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1505 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1506
1507 uint64_t EltBits = 0;
1508 if (OpVal.getOpcode() == ISD::UNDEF) {
1509 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1510 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1511 continue;
1512 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001513 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00001514 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
1515 const APFloat &apf = CN->getValueAPF();
1516 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001517 ? FloatToBits(apf.convertToFloat())
1518 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001519 } else {
1520 // Nonconstant element.
1521 return true;
1522 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001523
Scott Michel266bc8f2007-12-04 22:23:35 +00001524 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1525 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001526
1527 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001528 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1529 return false;
1530}
1531
1532/// If this is a splat (repetition) of a value across the whole vector, return
1533/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001534/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001535/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001536static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001537 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001538 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001539 uint64_t &SplatBits, uint64_t &SplatUndef,
1540 int &SplatSize) {
1541 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1542 // the same as the lower 64-bits, ignoring undefs.
1543 uint64_t Bits64 = Bits128[0] | Bits128[1];
1544 uint64_t Undef64 = Undef128[0] & Undef128[1];
1545 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1546 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1547 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1548 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1549
1550 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1551 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001552
Scott Michel266bc8f2007-12-04 22:23:35 +00001553 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1554 // undefs.
1555 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001556 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001557
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001558 // If the top 16-bits are different than the lower 16-bits, ignoring
1559 // undefs, we have an i32 splat.
1560 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1561 if (MinSplatBits < 16) {
1562 // If the top 8-bits are different than the lower 8-bits, ignoring
1563 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001564 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1565 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001566 // Otherwise, we have an 8-bit splat.
1567 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1568 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1569 SplatSize = 1;
1570 return true;
1571 }
1572 } else {
1573 SplatBits = Bits16;
1574 SplatUndef = Undef16;
1575 SplatSize = 2;
1576 return true;
1577 }
1578 }
1579 } else {
1580 SplatBits = Bits32;
1581 SplatUndef = Undef32;
1582 SplatSize = 4;
1583 return true;
1584 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001585 }
1586 } else {
1587 SplatBits = Bits128[0];
1588 SplatUndef = Undef128[0];
1589 SplatSize = 8;
1590 return true;
1591 }
1592 }
1593
1594 return false; // Can't be a splat if two pieces don't match.
1595}
1596
1597// If this is a case we can't handle, return null and let the default
1598// expansion code take care of it. If we CAN select this case, and if it
1599// selects to a single instruction, return Op. Otherwise, if we can codegen
1600// this case more efficiently than a constant pool load, lower it to the
1601// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001602static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001603 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001604 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001605 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001606 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001607 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001608 uint64_t VectorBits[2];
1609 uint64_t UndefBits[2];
1610 uint64_t SplatBits, SplatUndef;
1611 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001612 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001613 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001614 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001615 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001616 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001617
Duncan Sands83ec4b62008-06-06 12:08:01 +00001618 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001619 default:
1620 case MVT::v4f32: {
1621 uint32_t Value32 = SplatBits;
1622 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001623 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001624 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001625 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001626 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001627 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001628 break;
1629 }
1630 case MVT::v2f64: {
1631 uint64_t f64val = SplatBits;
1632 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001633 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001634 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001635 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001636 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001637 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001638 break;
1639 }
1640 case MVT::v16i8: {
1641 // 8-bit constants have to be expanded to 16-bits
1642 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001643 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001644 for (int i = 0; i < 8; ++i)
1645 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1646 return DAG.getNode(ISD::BIT_CONVERT, VT,
1647 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1648 }
1649 case MVT::v8i16: {
1650 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001651 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001652 Value16 = (unsigned short) (SplatBits & 0xffff);
1653 else
1654 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001655 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1656 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001657 for (int i = 0; i < 8; ++i) Ops[i] = T;
1658 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1659 }
1660 case MVT::v4i32: {
1661 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001662 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001663 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1664 }
1665 case MVT::v2i64: {
1666 uint64_t val = SplatBits;
1667 uint32_t upper = uint32_t(val >> 32);
1668 uint32_t lower = uint32_t(val);
1669
Scott Michel4cb8bd82008-03-06 04:02:54 +00001670 if (upper == lower) {
1671 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001672 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001673 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001674 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001675 SDValue LO32;
1676 SDValue HI32;
1677 SmallVector<SDValue, 16> ShufBytes;
1678 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001679 bool upper_special, lower_special;
1680
1681 // NOTE: This code creates common-case shuffle masks that can be easily
1682 // detected as common expressions. It is not attempting to create highly
1683 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1684
1685 // Detect if the upper or lower half is a special shuffle mask pattern:
1686 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1687 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1688
1689 // Create lower vector if not a special pattern
1690 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001691 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001692 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1693 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1694 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001695 }
1696
1697 // Create upper vector if not a special pattern
1698 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001699 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001700 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1701 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1702 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001703 }
1704
1705 // If either upper or lower are special, then the two input operands are
1706 // the same (basically, one of them is a "don't care")
1707 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001708 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001709 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001710 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001711 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001712 // Unhappy situation... both upper and lower are special, so punt with
1713 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001714 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001715 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001716 Zero, Zero);
1717 }
1718
1719 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001720 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001721 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001722 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001723 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001724 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001725 process_upper = (upper_special && (i & 1) == 0);
1726 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001727
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001728 if (process_upper || process_lower) {
1729 if ((process_upper && upper == 0)
1730 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001731 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001732 else if ((process_upper && upper == 0xffffffff)
1733 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001734 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001735 else if ((process_upper && upper == 0x80000000)
1736 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001737 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001738 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001739 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001740 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001741
1742 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001743 }
1744
1745 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001746 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001747 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001748 }
1749 }
1750 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001751
Dan Gohman475871a2008-07-27 21:46:04 +00001752 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001753}
1754
1755/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1756/// which the Cell can operate. The code inspects V3 to ascertain whether the
1757/// permutation vector, V3, is monotonically increasing with one "exception"
1758/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1759/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1760/// In either case, the net result is going to eventually invoke SHUFB to
1761/// permute/shuffle the bytes from V1 and V2.
1762/// \note
1763/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1764/// control word for byte/halfword/word insertion. This takes care of a single
1765/// element move from V2 into V1.
1766/// \note
1767/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001768static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1769 SDValue V1 = Op.getOperand(0);
1770 SDValue V2 = Op.getOperand(1);
1771 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001772
Scott Michel266bc8f2007-12-04 22:23:35 +00001773 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001774
Scott Michel266bc8f2007-12-04 22:23:35 +00001775 // If we have a single element being moved from V1 to V2, this can be handled
1776 // using the C*[DX] compute mask instructions, but the vector elements have
1777 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001778 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001779 unsigned EltsFromV2 = 0;
1780 unsigned V2Elt = 0;
1781 unsigned V2EltIdx0 = 0;
1782 unsigned CurrElt = 0;
1783 bool monotonic = true;
1784 if (EltVT == MVT::i8)
1785 V2EltIdx0 = 16;
1786 else if (EltVT == MVT::i16)
1787 V2EltIdx0 = 8;
1788 else if (EltVT == MVT::i32)
1789 V2EltIdx0 = 4;
1790 else
1791 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1792
1793 for (unsigned i = 0, e = PermMask.getNumOperands();
1794 EltsFromV2 <= 1 && monotonic && i != e;
1795 ++i) {
1796 unsigned SrcElt;
1797 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1798 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001799 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001800 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001801
1802 if (SrcElt >= V2EltIdx0) {
1803 ++EltsFromV2;
1804 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1805 } else if (CurrElt != SrcElt) {
1806 monotonic = false;
1807 }
1808
1809 ++CurrElt;
1810 }
1811
1812 if (EltsFromV2 == 1 && monotonic) {
1813 // Compute mask and shuffle
1814 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001815 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1816 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001817 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001818 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001819 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001820 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1821 // Copy register's contents as index in INSERT_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001822 SDValue ShufMaskOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001823 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001824 DAG.getTargetConstant(V2Elt, MVT::i32),
1825 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001826 // Use shuffle mask in SHUFB synthetic instruction:
1827 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1828 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001829 // Convert the SHUFFLE_VECTOR mask's input element units to the
1830 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001831 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001832
Dan Gohman475871a2008-07-27 21:46:04 +00001833 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001834 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1835 unsigned SrcElt;
1836 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001837 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001838 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001839 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001840
Scott Michela59d4692008-02-23 18:41:37 +00001841 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001842 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1843 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001844 }
1845 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001846
Dan Gohman475871a2008-07-27 21:46:04 +00001847 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001848 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001849 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1850 }
1851}
1852
Dan Gohman475871a2008-07-27 21:46:04 +00001853static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1854 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001855
Gabor Greifba36cb52008-08-28 21:40:38 +00001856 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001857 // For a constant, build the appropriate constant vector, which will
1858 // eventually simplify to a vector register load.
1859
Gabor Greifba36cb52008-08-28 21:40:38 +00001860 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001861 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001862 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001863 size_t n_copies;
1864
1865 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001866 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001867 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001868 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001869 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1870 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1871 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1872 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1873 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1874 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1875 }
1876
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001877 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001878 for (size_t j = 0; j < n_copies; ++j)
1879 ConstVecValues.push_back(CValue);
1880
1881 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001882 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001883 } else {
1884 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001885 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001886 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1887 case MVT::i8:
1888 case MVT::i16:
1889 case MVT::i32:
1890 case MVT::i64:
1891 case MVT::f32:
1892 case MVT::f64:
1893 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1894 }
1895 }
1896
Dan Gohman475871a2008-07-27 21:46:04 +00001897 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001898}
1899
Dan Gohman475871a2008-07-27 21:46:04 +00001900static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001901 switch (Op.getValueType().getSimpleVT()) {
1902 default:
1903 cerr << "CellSPU: Unknown vector multiplication, got "
1904 << Op.getValueType().getMVTString()
1905 << "\n";
1906 abort();
1907 /*NOTREACHED*/
1908
Scott Michel266bc8f2007-12-04 22:23:35 +00001909 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001910 SDValue rA = Op.getOperand(0);
1911 SDValue rB = Op.getOperand(1);
1912 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1913 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1914 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1915 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001916
1917 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1918 break;
1919 }
1920
1921 // Multiply two v8i16 vectors (pipeline friendly version):
1922 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1923 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1924 // c) Use SELB to select upper and lower halves from the intermediate results
1925 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001926 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001927 // dual-issue. This code does manage to do this, even if it's a little on
1928 // the wacky side
1929 case MVT::v8i16: {
1930 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001931 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001932 SDValue Chain = Op.getOperand(0);
1933 SDValue rA = Op.getOperand(0);
1934 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001935 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1936 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001937
Dan Gohman475871a2008-07-27 21:46:04 +00001938 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001939 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001940 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001941 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001942
Dan Gohman475871a2008-07-27 21:46:04 +00001943 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001944 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001945 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001946
Dan Gohman475871a2008-07-27 21:46:04 +00001947 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001948 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001949 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001950
1951 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001952 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1953 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1954 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1955 HHProd_v4i32,
1956 DAG.getConstant(16, MVT::i16))),
1957 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001958 }
1959
1960 // This M00sE is N@stI! (apologies to Monty Python)
1961 //
1962 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1963 // is to break it all apart, sign extend, and reassemble the various
1964 // intermediate products.
1965 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001966 SDValue rA = Op.getOperand(0);
1967 SDValue rB = Op.getOperand(1);
1968 SDValue c8 = DAG.getConstant(8, MVT::i32);
1969 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001970
Dan Gohman475871a2008-07-27 21:46:04 +00001971 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001972 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001973 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1974 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001975
Dan Gohman475871a2008-07-27 21:46:04 +00001976 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001977
Dan Gohman475871a2008-07-27 21:46:04 +00001978 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001979
Dan Gohman475871a2008-07-27 21:46:04 +00001980 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001981 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001982 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001983
Dan Gohman475871a2008-07-27 21:46:04 +00001984 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001985 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001986
Dan Gohman475871a2008-07-27 21:46:04 +00001987 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001988 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1989 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1990 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001991
Dan Gohman475871a2008-07-27 21:46:04 +00001992 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001993
Dan Gohman475871a2008-07-27 21:46:04 +00001994 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001995 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00001996 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001997 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1998 LoProdMask, LoProdMask,
1999 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002000
Dan Gohman475871a2008-07-27 21:46:04 +00002001 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002002 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002003 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002004
Dan Gohman475871a2008-07-27 21:46:04 +00002005 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002006 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002007 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002008
Dan Gohman475871a2008-07-27 21:46:04 +00002009 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002010 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002011 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2012 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00002013
Dan Gohman475871a2008-07-27 21:46:04 +00002014 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002015 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002016 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002017 DAG.getNode(SPUISD::VEC_SRA,
2018 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002019 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002020 DAG.getNode(SPUISD::VEC_SRA,
2021 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002022
Dan Gohman475871a2008-07-27 21:46:04 +00002023 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00002024 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2025 HLProd,
2026 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2027 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002028
Dan Gohman475871a2008-07-27 21:46:04 +00002029 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002030 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002031
2032 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002033 DAG.getNode(ISD::OR, MVT::v4i32,
2034 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002035 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002036 }
2037
Dan Gohman475871a2008-07-27 21:46:04 +00002038 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002039}
2040
Dan Gohman475871a2008-07-27 21:46:04 +00002041static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002042 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002043 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002044
Dan Gohman475871a2008-07-27 21:46:04 +00002045 SDValue A = Op.getOperand(0);
2046 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002047 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002048
2049 unsigned VRegBR, VRegC;
2050
2051 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002052 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2053 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002054 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002055 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2056 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002057 }
2058 // TODO: make sure we're feeding FPInterp the right arguments
2059 // Right now: fi B, frest(B)
2060
2061 // Computes BRcpl =
2062 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002063 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002064 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2065 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002066 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002067
Scott Michel266bc8f2007-12-04 22:23:35 +00002068 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002069 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002070 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002071 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002072 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002073 // What's the Chain variable do? It's magic!
2074 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002075
2076 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002077 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002078 DAG.getNode(ISD::FMUL, VT,
2079 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002080 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002081 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002082 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002083}
2084
Dan Gohman475871a2008-07-27 21:46:04 +00002085static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002086 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002087 SDValue N = Op.getOperand(0);
2088 SDValue Elt = Op.getOperand(1);
2089 SDValue ShufMask[16];
Scott Michel266bc8f2007-12-04 22:23:35 +00002090 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
2091
2092 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2093
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002094 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002095
2096 // sanity checks:
2097 if (VT == MVT::i8 && EltNo >= 16)
2098 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2099 else if (VT == MVT::i16 && EltNo >= 8)
2100 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2101 else if (VT == MVT::i32 && EltNo >= 4)
2102 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2103 else if (VT == MVT::i64 && EltNo >= 2)
2104 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2105
2106 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2107 // i32 and i64: Element 0 is the preferred slot
2108 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2109 }
2110
2111 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002112 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002113 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002114
Duncan Sands83ec4b62008-06-06 12:08:01 +00002115 switch (VT.getSimpleVT()) {
2116 default:
2117 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002118 case MVT::i8: {
2119 prefslot_begin = prefslot_end = 3;
2120 break;
2121 }
2122 case MVT::i16: {
2123 prefslot_begin = 2; prefslot_end = 3;
2124 break;
2125 }
2126 case MVT::i32: {
2127 prefslot_begin = 0; prefslot_end = 3;
2128 break;
2129 }
2130 case MVT::i64: {
2131 prefslot_begin = 0; prefslot_end = 7;
2132 break;
2133 }
2134 }
2135
Scott Michel0e5665b2007-12-19 21:17:42 +00002136 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002137 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002138
Scott Michel266bc8f2007-12-04 22:23:35 +00002139 for (int i = 0; i < 16; ++i) {
2140 // zero fill uppper part of preferred slot, don't care about the
2141 // other slots:
2142 unsigned int mask_val;
2143
2144 if (i <= prefslot_end) {
2145 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002146 ((i < prefslot_begin)
2147 ? 0x80
2148 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002149
Scott Michel0e5665b2007-12-19 21:17:42 +00002150 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002151 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002152 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2153 }
2154
Dan Gohman475871a2008-07-27 21:46:04 +00002155 SDValue ShufMaskVec =
Scott Michel266bc8f2007-12-04 22:23:35 +00002156 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002157 &ShufMask[0],
2158 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002159
2160 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002161 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2162 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002163
Scott Michel266bc8f2007-12-04 22:23:35 +00002164}
2165
Dan Gohman475871a2008-07-27 21:46:04 +00002166static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2167 SDValue VecOp = Op.getOperand(0);
2168 SDValue ValOp = Op.getOperand(1);
2169 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002170 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002171
2172 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2173 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2174
Duncan Sands83ec4b62008-06-06 12:08:01 +00002175 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002176 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002177 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002178
Dan Gohman475871a2008-07-27 21:46:04 +00002179 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002180 DAG.getNode(SPUISD::SHUFB, VT,
2181 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2182 VecOp,
2183 DAG.getNode(SPUISD::INSERT_MASK, VT,
2184 DAG.getNode(ISD::ADD, PtrVT,
2185 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002186 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002187 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002188
2189 return result;
2190}
2191
Dan Gohman475871a2008-07-27 21:46:04 +00002192static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002193{
Dan Gohman475871a2008-07-27 21:46:04 +00002194 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002195
2196 assert(Op.getValueType() == MVT::i8);
2197 switch (Opc) {
2198 default:
2199 assert(0 && "Unhandled i8 math operator");
2200 /*NOTREACHED*/
2201 break;
2202 case ISD::SUB: {
2203 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2204 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002205 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002206 N0 = (N0.getOpcode() != ISD::Constant
2207 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002208 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2209 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002210 N1 = (N1.getOpcode() != ISD::Constant
2211 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002212 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2213 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002214 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002215 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002216 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002217 case ISD::ROTR:
2218 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002219 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002220 unsigned N1Opc;
2221 N0 = (N0.getOpcode() != ISD::Constant
2222 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002223 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2224 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002225 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2226 ? ISD::ZERO_EXTEND
2227 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002228 N1 = (N1.getOpcode() != ISD::Constant
2229 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002230 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2231 MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002232 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002233 DAG.getNode(ISD::OR, MVT::i16, N0,
2234 DAG.getNode(ISD::SHL, MVT::i16,
2235 N0, DAG.getConstant(8, MVT::i16)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002236 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002237 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2238 }
2239 case ISD::SRL:
2240 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002241 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002242 unsigned N1Opc;
2243 N0 = (N0.getOpcode() != ISD::Constant
2244 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002245 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2246 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002247 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2248 ? ISD::ZERO_EXTEND
2249 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002250 N1 = (N1.getOpcode() != ISD::Constant
2251 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002252 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2253 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002254 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002255 DAG.getNode(Opc, MVT::i16, N0, N1));
2256 }
2257 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002258 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002259 unsigned N1Opc;
2260 N0 = (N0.getOpcode() != ISD::Constant
2261 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002262 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2263 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002264 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2265 ? ISD::SIGN_EXTEND
2266 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002267 N1 = (N1.getOpcode() != ISD::Constant
2268 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002269 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2270 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002271 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002272 DAG.getNode(Opc, MVT::i16, N0, N1));
2273 }
2274 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002275 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002276 unsigned N1Opc;
2277 N0 = (N0.getOpcode() != ISD::Constant
2278 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002279 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2280 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002281 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002282 N1 = (N1.getOpcode() != ISD::Constant
2283 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002284 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2285 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002286 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002287 DAG.getNode(Opc, MVT::i16, N0, N1));
2288 break;
2289 }
2290 }
2291
Dan Gohman475871a2008-07-27 21:46:04 +00002292 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002293}
2294
Dan Gohman475871a2008-07-27 21:46:04 +00002295static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002296{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002297 MVT VT = Op.getValueType();
2298 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002299
Dan Gohman475871a2008-07-27 21:46:04 +00002300 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002301
2302 switch (Opc) {
2303 case ISD::ZERO_EXTEND:
2304 case ISD::SIGN_EXTEND:
2305 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002306 MVT Op0VT = Op0.getValueType();
2307 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002308
2309 assert(Op0VT == MVT::i32
2310 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002311 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002312
2313 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2314 ? SPUISD::ROTBYTES_RIGHT_S
2315 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002316 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002317 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2318
2319 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2320 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2321 DAG.getNode(NewOpc, Op0VecVT,
2322 PromoteScalar,
2323 DAG.getConstant(4, MVT::i32))));
2324 }
2325
Scott Michel8bf61e82008-06-02 22:18:03 +00002326 case ISD::ADD: {
2327 // Turn operands into vectors to satisfy type checking (shufb works on
2328 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002329 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002330 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002331 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002332 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002333 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002334
2335 // Create the shuffle mask for "rotating" the borrow up one register slot
2336 // once the borrow is generated.
2337 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2338 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2339 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2340 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2341
Dan Gohman475871a2008-07-27 21:46:04 +00002342 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002343 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002344 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002345 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2346 CarryGen, CarryGen,
2347 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2348 &ShufBytes[0], ShufBytes.size()));
2349
2350 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2351 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2352 Op0, Op1, ShiftedCarry));
2353 }
2354
2355 case ISD::SUB: {
2356 // Turn operands into vectors to satisfy type checking (shufb works on
2357 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002358 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002359 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002360 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002361 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002362 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002363
2364 // Create the shuffle mask for "rotating" the borrow up one register slot
2365 // once the borrow is generated.
2366 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2367 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2368 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2369 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2370
Dan Gohman475871a2008-07-27 21:46:04 +00002371 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002372 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002373 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002374 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2375 BorrowGen, BorrowGen,
2376 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2377 &ShufBytes[0], ShufBytes.size()));
2378
2379 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2380 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2381 Op0, Op1, ShiftedBorrow));
2382 }
2383
Scott Michela59d4692008-02-23 18:41:37 +00002384 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002385 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002386 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002387 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2388 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002389 DAG.getNode(SPUISD::SELB, VecVT,
2390 Op0Vec,
2391 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002392 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002393 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002394 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002395 DAG.getNode(ISD::SRL, ShiftAmtVT,
2396 ShiftAmt,
2397 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002398 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002399 DAG.getNode(ISD::AND, ShiftAmtVT,
2400 ShiftAmt,
2401 DAG.getConstant(7, ShiftAmtVT));
2402
2403 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2404 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2405 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2406 MaskLower, ShiftAmtBytes),
2407 ShiftAmtBits));
2408 }
2409
2410 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002411 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002412 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002413 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002414 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002415 DAG.getNode(ISD::SRL, ShiftAmtVT,
2416 ShiftAmt,
2417 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002418 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002419 DAG.getNode(ISD::AND, ShiftAmtVT,
2420 ShiftAmt,
2421 DAG.getConstant(7, ShiftAmtVT));
2422
2423 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2424 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2425 Op0, ShiftAmtBytes),
2426 ShiftAmtBits);
2427 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002428
2429 case ISD::SRA: {
2430 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002431 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002432 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002433 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002434 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002435
2436 // Negate variable shift amounts
2437 if (!isa<ConstantSDNode>(ShiftAmt)) {
2438 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2439 DAG.getConstant(0, ShiftVT), ShiftAmt);
2440 }
2441
Dan Gohman475871a2008-07-27 21:46:04 +00002442 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002443 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2444 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2445 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2446 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002447 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002448 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002449 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002450 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2451 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002452 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002453 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2454 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002455 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002456 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2457 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002458 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002459 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2460 RotateLeftBytes, ShiftAmt);
2461
2462 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2463 RotateLeftBits);
2464 }
Scott Michela59d4692008-02-23 18:41:37 +00002465 }
2466
Dan Gohman475871a2008-07-27 21:46:04 +00002467 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002468}
2469
Scott Michel266bc8f2007-12-04 22:23:35 +00002470//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002471static SDValue
2472LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2473 SDValue ConstVec;
2474 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002475 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002476
2477 ConstVec = Op.getOperand(0);
2478 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002479 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2480 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002481 ConstVec = ConstVec.getOperand(0);
2482 } else {
2483 ConstVec = Op.getOperand(1);
2484 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002485 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002486 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002487 }
2488 }
2489 }
2490
Gabor Greifba36cb52008-08-28 21:40:38 +00002491 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002492 uint64_t VectorBits[2];
2493 uint64_t UndefBits[2];
2494 uint64_t SplatBits, SplatUndef;
2495 int SplatSize;
2496
Gabor Greifba36cb52008-08-28 21:40:38 +00002497 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002498 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002499 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002500 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002501 SDValue tcVec[16];
2502 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002503 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2504
2505 // Turn the BUILD_VECTOR into a set of target constants:
2506 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002507 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002508
Gabor Greifba36cb52008-08-28 21:40:38 +00002509 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002510 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002511 }
2512 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002513 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2514 // lowered. Return the operation, rather than a null SDValue.
2515 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002516}
2517
2518//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002519static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002520 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002521 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002522 default:
2523 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002524 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002525 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002526 abort();
2527 /*NOTREACHED*/
2528
2529 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002530 SDValue rA = Op.getOperand(0);
2531 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002532
2533 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002534 DAG.getNode(ISD::ADD, MVT::i32,
2535 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2536 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2537 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002538 }
2539 }
2540
Dan Gohman475871a2008-07-27 21:46:04 +00002541 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002542}
2543
2544//! Custom lowering for CTPOP (count population)
2545/*!
2546 Custom lowering code that counts the number ones in the input
2547 operand. SPU has such an instruction, but it counts the number of
2548 ones per byte, which then have to be accumulated.
2549*/
Dan Gohman475871a2008-07-27 21:46:04 +00002550static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002551 MVT VT = Op.getValueType();
2552 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002553
Duncan Sands83ec4b62008-06-06 12:08:01 +00002554 switch (VT.getSimpleVT()) {
2555 default:
2556 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002557 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002558 SDValue N = Op.getOperand(0);
2559 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002560
Dan Gohman475871a2008-07-27 21:46:04 +00002561 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2562 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002563
2564 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2565 }
2566
2567 case MVT::i16: {
2568 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002569 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002570
Chris Lattner84bc5422007-12-31 04:13:23 +00002571 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002572
Dan Gohman475871a2008-07-27 21:46:04 +00002573 SDValue N = Op.getOperand(0);
2574 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2575 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
2576 SDValue Shift1 = DAG.getConstant(8, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002577
Dan Gohman475871a2008-07-27 21:46:04 +00002578 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2579 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002580
2581 // CNTB_result becomes the chain to which all of the virtual registers
2582 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002583 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002584 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002585
Dan Gohman475871a2008-07-27 21:46:04 +00002586 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002587 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2588
Dan Gohman475871a2008-07-27 21:46:04 +00002589 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002590
2591 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002592 DAG.getNode(ISD::ADD, MVT::i16,
2593 DAG.getNode(ISD::SRL, MVT::i16,
2594 Tmp1, Shift1),
2595 Tmp1),
2596 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002597 }
2598
2599 case MVT::i32: {
2600 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002601 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002602
Chris Lattner84bc5422007-12-31 04:13:23 +00002603 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2604 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002605
Dan Gohman475871a2008-07-27 21:46:04 +00002606 SDValue N = Op.getOperand(0);
2607 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2608 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2609 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2610 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002611
Dan Gohman475871a2008-07-27 21:46:04 +00002612 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2613 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002614
2615 // CNTB_result becomes the chain to which all of the virtual registers
2616 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002617 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002618 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002619
Dan Gohman475871a2008-07-27 21:46:04 +00002620 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002621 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2622
Dan Gohman475871a2008-07-27 21:46:04 +00002623 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002624 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002625 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002626
Dan Gohman475871a2008-07-27 21:46:04 +00002627 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002628 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002629 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002630
Dan Gohman475871a2008-07-27 21:46:04 +00002631 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002632 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2633
Dan Gohman475871a2008-07-27 21:46:04 +00002634 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002635 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002636 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2637 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002638 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002639 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002640 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002641
2642 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2643 }
2644
2645 case MVT::i64:
2646 break;
2647 }
2648
Dan Gohman475871a2008-07-27 21:46:04 +00002649 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002650}
2651
2652/// LowerOperation - Provide custom lowering hooks for some operations.
2653///
Dan Gohman475871a2008-07-27 21:46:04 +00002654SDValue
2655SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002656{
Scott Michela59d4692008-02-23 18:41:37 +00002657 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002658 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002659
2660 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002661 default: {
2662 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002663 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002664 cerr << "*Op.getNode():\n";
2665 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002666 abort();
2667 }
2668 case ISD::LOAD:
2669 case ISD::SEXTLOAD:
2670 case ISD::ZEXTLOAD:
2671 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2672 case ISD::STORE:
2673 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2674 case ISD::ConstantPool:
2675 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2676 case ISD::GlobalAddress:
2677 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2678 case ISD::JumpTable:
2679 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2680 case ISD::Constant:
2681 return LowerConstant(Op, DAG);
2682 case ISD::ConstantFP:
2683 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002684 case ISD::BRCOND:
2685 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002686 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002687 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002688 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002689 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002690 case ISD::RET:
2691 return LowerRET(Op, DAG, getTargetMachine());
2692
Scott Michela59d4692008-02-23 18:41:37 +00002693
2694 // i8, i64 math ops:
2695 case ISD::ZERO_EXTEND:
2696 case ISD::SIGN_EXTEND:
2697 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002698 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002699 case ISD::SUB:
2700 case ISD::ROTR:
2701 case ISD::ROTL:
2702 case ISD::SRL:
2703 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002704 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002705 if (VT == MVT::i8)
2706 return LowerI8Math(Op, DAG, Opc);
2707 else if (VT == MVT::i64)
2708 return LowerI64Math(Op, DAG, Opc);
2709 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002710 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002711
2712 // Vector-related lowering.
2713 case ISD::BUILD_VECTOR:
2714 return LowerBUILD_VECTOR(Op, DAG);
2715 case ISD::SCALAR_TO_VECTOR:
2716 return LowerSCALAR_TO_VECTOR(Op, DAG);
2717 case ISD::VECTOR_SHUFFLE:
2718 return LowerVECTOR_SHUFFLE(Op, DAG);
2719 case ISD::EXTRACT_VECTOR_ELT:
2720 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2721 case ISD::INSERT_VECTOR_ELT:
2722 return LowerINSERT_VECTOR_ELT(Op, DAG);
2723
2724 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2725 case ISD::AND:
2726 case ISD::OR:
2727 case ISD::XOR:
2728 return LowerByteImmed(Op, DAG);
2729
2730 // Vector and i8 multiply:
2731 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002732 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002733 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002734 else if (VT == MVT::i8)
2735 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002736 else
Scott Michela59d4692008-02-23 18:41:37 +00002737 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002738
2739 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002740 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002741 return LowerFDIVf32(Op, DAG);
2742// else if (Op.getValueType() == MVT::f64)
2743// return LowerFDIVf64(Op, DAG);
2744 else
2745 assert(0 && "Calling FDIV on unsupported MVT");
2746
2747 case ISD::CTPOP:
2748 return LowerCTPOP(Op, DAG);
2749 }
2750
Dan Gohman475871a2008-07-27 21:46:04 +00002751 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002752}
2753
2754//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002755// Target Optimization Hooks
2756//===----------------------------------------------------------------------===//
2757
Dan Gohman475871a2008-07-27 21:46:04 +00002758SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002759SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2760{
2761#if 0
2762 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002763#endif
2764 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002765 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002766 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2767 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002768
2769 switch (N->getOpcode()) {
2770 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002771 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002772 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002773
Scott Michel8bf61e82008-06-02 22:18:03 +00002774 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002775 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002776 if (Op01.getOpcode() == ISD::Constant
2777 || Op01.getOpcode() == ISD::TargetConstant) {
2778 // (add <const>, (SPUindirect <arg>, <const>)) ->
2779 // (SPUindirect <arg>, <const + const>)
2780 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2781 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002782 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002783 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002784 Op0.getValueType());
2785
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002786 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2787 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002788 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002789 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002790 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2791 Op0.getOperand(0), combinedConst);
2792 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002793 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002794 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002795 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002796 if (Op11.getOpcode() == ISD::Constant
2797 || Op11.getOpcode() == ISD::TargetConstant) {
2798 // (add (SPUindirect <arg>, <const>), <const>) ->
2799 // (SPUindirect <arg>, <const + const>)
2800 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2801 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002802 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002803 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002804 Op0.getValueType());
2805
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002806 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2807 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002808 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002809 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002810
2811 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2812 Op1.getOperand(0), combinedConst);
2813 }
2814 }
Scott Michela59d4692008-02-23 18:41:37 +00002815 break;
2816 }
2817 case ISD::SIGN_EXTEND:
2818 case ISD::ZERO_EXTEND:
2819 case ISD::ANY_EXTEND: {
2820 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2821 N->getValueType(0) == Op0.getValueType()) {
2822 // (any_extend (SPUextract_elt0 <arg>)) ->
2823 // (SPUextract_elt0 <arg>)
2824 // Types must match, however...
2825 DEBUG(cerr << "Replace: ");
2826 DEBUG(N->dump(&DAG));
2827 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002828 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002829 DEBUG(cerr << "\n");
2830
2831 return Op0;
2832 }
2833 break;
2834 }
2835 case SPUISD::IndirectAddr: {
2836 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2837 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002838 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002839 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2840 // (SPUaform <addr>, 0)
2841
2842 DEBUG(cerr << "Replace: ");
2843 DEBUG(N->dump(&DAG));
2844 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002845 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002846 DEBUG(cerr << "\n");
2847
2848 return Op0;
2849 }
2850 }
2851 break;
2852 }
2853 case SPUISD::SHLQUAD_L_BITS:
2854 case SPUISD::SHLQUAD_L_BYTES:
2855 case SPUISD::VEC_SHL:
2856 case SPUISD::VEC_SRL:
2857 case SPUISD::VEC_SRA:
2858 case SPUISD::ROTQUAD_RZ_BYTES:
2859 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002860 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002861
2862 if (isa<ConstantSDNode>(Op1)) {
2863 // Kill degenerate vector shifts:
2864 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2865
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002866 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002867 Result = Op0;
2868 }
2869 }
2870 break;
2871 }
2872 case SPUISD::PROMOTE_SCALAR: {
2873 switch (Op0.getOpcode()) {
2874 default:
2875 break;
2876 case ISD::ANY_EXTEND:
2877 case ISD::ZERO_EXTEND:
2878 case ISD::SIGN_EXTEND: {
2879 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2880 // <arg>
2881 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002882 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002883 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00002884 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002885 if (Op000.getValueType() == N->getValueType(0)) {
2886 Result = Op000;
2887 }
2888 }
2889 break;
2890 }
2891 case SPUISD::EXTRACT_ELT0: {
2892 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2893 // <arg>
2894 Result = Op0.getOperand(0);
2895 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002896 }
Scott Michela59d4692008-02-23 18:41:37 +00002897 }
2898 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002899 }
2900 }
Scott Michel58c58182008-01-17 20:38:41 +00002901 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002902#if 1
Gabor Greifba36cb52008-08-28 21:40:38 +00002903 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00002904 DEBUG(cerr << "\nReplace.SPU: ");
2905 DEBUG(N->dump(&DAG));
2906 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002907 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002908 DEBUG(cerr << "\n");
2909 }
2910#endif
2911
2912 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002913}
2914
2915//===----------------------------------------------------------------------===//
2916// Inline Assembly Support
2917//===----------------------------------------------------------------------===//
2918
2919/// getConstraintType - Given a constraint letter, return the type of
2920/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002921SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002922SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2923 if (ConstraintLetter.size() == 1) {
2924 switch (ConstraintLetter[0]) {
2925 default: break;
2926 case 'b':
2927 case 'r':
2928 case 'f':
2929 case 'v':
2930 case 'y':
2931 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002932 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002933 }
2934 return TargetLowering::getConstraintType(ConstraintLetter);
2935}
2936
Scott Michel5af8f0e2008-07-16 17:17:29 +00002937std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002938SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002939 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002940{
2941 if (Constraint.size() == 1) {
2942 // GCC RS6000 Constraint Letters
2943 switch (Constraint[0]) {
2944 case 'b': // R1-R31
2945 case 'r': // R0-R31
2946 if (VT == MVT::i64)
2947 return std::make_pair(0U, SPU::R64CRegisterClass);
2948 return std::make_pair(0U, SPU::R32CRegisterClass);
2949 case 'f':
2950 if (VT == MVT::f32)
2951 return std::make_pair(0U, SPU::R32FPRegisterClass);
2952 else if (VT == MVT::f64)
2953 return std::make_pair(0U, SPU::R64FPRegisterClass);
2954 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002955 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002956 return std::make_pair(0U, SPU::GPRCRegisterClass);
2957 }
2958 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002959
Scott Michel266bc8f2007-12-04 22:23:35 +00002960 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2961}
2962
Scott Michela59d4692008-02-23 18:41:37 +00002963//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002964void
Dan Gohman475871a2008-07-27 21:46:04 +00002965SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002966 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002967 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002968 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002969 const SelectionDAG &DAG,
2970 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002971#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002972 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002973#endif
Scott Michela59d4692008-02-23 18:41:37 +00002974
2975 switch (Op.getOpcode()) {
2976 default:
2977 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2978 break;
2979
2980#if 0
2981 case CALL:
2982 case SHUFB:
2983 case INSERT_MASK:
2984 case CNTB:
2985#endif
2986
2987 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00002988 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002989 MVT Op0VT = Op0.getValueType();
2990 unsigned Op0VTBits = Op0VT.getSizeInBits();
2991 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002992 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2993 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002994 break;
2995 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002996
Scott Michela59d4692008-02-23 18:41:37 +00002997 case SPUISD::LDRESULT:
2998 case SPUISD::EXTRACT_ELT0:
2999 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00003000 MVT OpVT = Op.getValueType();
3001 unsigned OpVTBits = OpVT.getSizeInBits();
3002 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003003 KnownZero |= APInt(OpVTBits, ~InMask, false);
3004 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003005 break;
3006 }
3007
3008#if 0
3009 case EXTRACT_I1_ZEXT:
3010 case EXTRACT_I1_SEXT:
3011 case EXTRACT_I8_ZEXT:
3012 case EXTRACT_I8_SEXT:
3013 case MPY:
3014 case MPYU:
3015 case MPYH:
3016 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003017 case SPUISD::SHLQUAD_L_BITS:
3018 case SPUISD::SHLQUAD_L_BYTES:
3019 case SPUISD::VEC_SHL:
3020 case SPUISD::VEC_SRL:
3021 case SPUISD::VEC_SRA:
3022 case SPUISD::VEC_ROTL:
3023 case SPUISD::VEC_ROTR:
3024 case SPUISD::ROTQUAD_RZ_BYTES:
3025 case SPUISD::ROTQUAD_RZ_BITS:
3026 case SPUISD::ROTBYTES_RIGHT_S:
3027 case SPUISD::ROTBYTES_LEFT:
3028 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003029 case SPUISD::SELECT_MASK:
3030 case SPUISD::SELB:
3031 case SPUISD::FPInterp:
3032 case SPUISD::FPRecipEst:
3033 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003034#endif
3035 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003036}
3037
Scott Michel203b2d62008-04-30 00:30:08 +00003038// LowerAsmOperandForConstraint
3039void
Dan Gohman475871a2008-07-27 21:46:04 +00003040SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003041 char ConstraintLetter,
Evan Chengda43bcf2008-09-24 00:05:32 +00003042 bool hasMemory,
Dan Gohman475871a2008-07-27 21:46:04 +00003043 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003044 SelectionDAG &DAG) const {
3045 // Default, for the time being, to the base class handler
Evan Chengda43bcf2008-09-24 00:05:32 +00003046 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3047 Ops, DAG);
Scott Michel203b2d62008-04-30 00:30:08 +00003048}
3049
Scott Michel266bc8f2007-12-04 22:23:35 +00003050/// isLegalAddressImmediate - Return true if the integer value can be used
3051/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003052bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3053 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003054 // SPU's addresses are 256K:
3055 return (V > -(1 << 18) && V < (1 << 18) - 1);
3056}
3057
3058bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003059 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003060}
Dan Gohman6520e202008-10-18 02:06:02 +00003061
3062bool
3063SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3064 // The SPU target isn't yet aware of offsets.
3065 return false;
3066}