blob: 2fd72511baac43e6579ed86181477b932c7c1fc7 [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
95 || Opc == ISD::ExternalSymbol
96 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
100 || Opc == ISD::TargetExternalSymbol
Scott Michel9de5d0d2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000102 }
Scott Michel58c58182008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman475871a2008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel58c58182008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel58c58182008-01-17 20:38:41 +0000110 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000111}
112
113SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
114 : TargetLowering(TM),
115 SPUTM(TM)
116{
117 // Fold away setcc operations if possible.
118 setPow2DivIsCheap();
119
120 // Use _setjmp/_longjmp instead of setjmp/longjmp.
121 setUseUnderscoreSetJmp(true);
122 setUseUnderscoreLongJmp(true);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000123
Scott Michel266bc8f2007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel504c3692007-12-17 22:32:34 +0000125 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
126 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
127 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
128 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
129 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
130 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel266bc8f2007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000132
Scott Michel266bc8f2007-12-04 22:23:35 +0000133 // SPU has no sign or zero extended loads for i1, i8, i16:
Scott Michel58c58182008-01-17 20:38:41 +0000134 setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +0000135 setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote);
136 setLoadXAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Chris Lattnerddf89562008-01-17 19:59:44 +0000137 setTruncStoreAction(MVT::i8, MVT::i1, Custom);
138 setTruncStoreAction(MVT::i16, MVT::i1, Custom);
139 setTruncStoreAction(MVT::i32, MVT::i1, Custom);
140 setTruncStoreAction(MVT::i64, MVT::i1, Custom);
141 setTruncStoreAction(MVT::i128, MVT::i1, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000142
143 setLoadXAction(ISD::EXTLOAD, MVT::i8, Custom);
144 setLoadXAction(ISD::SEXTLOAD, MVT::i8, Custom);
145 setLoadXAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Chris Lattnerddf89562008-01-17 19:59:44 +0000146 setTruncStoreAction(MVT::i8 , MVT::i8, Custom);
147 setTruncStoreAction(MVT::i16 , MVT::i8, Custom);
148 setTruncStoreAction(MVT::i32 , MVT::i8, Custom);
149 setTruncStoreAction(MVT::i64 , MVT::i8, Custom);
150 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000151
Scott Michel266bc8f2007-12-04 22:23:35 +0000152 setLoadXAction(ISD::EXTLOAD, MVT::i16, Custom);
153 setLoadXAction(ISD::SEXTLOAD, MVT::i16, Custom);
154 setLoadXAction(ISD::ZEXTLOAD, MVT::i16, Custom);
155
156 // SPU constant load actions are custom lowered:
157 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begemanccef5802008-02-14 18:43:04 +0000158 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000159 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
160
161 // SPU's loads and stores have to be custom lowered:
162 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
163 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000164 MVT VT = (MVT::SimpleValueType)sctype;
165
166 setOperationAction(ISD::LOAD, VT, Custom);
167 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000168 }
169
Scott Michel58c58182008-01-17 20:38:41 +0000170 // Custom lower BRCOND for i1, i8 to "promote" the result to
171 // i32 and i16, respectively.
172 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000173
174 // Expand the jumptable branches
175 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
176 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000177 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000178
179 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000180 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
181
Scott Michel266bc8f2007-12-04 22:23:35 +0000182 // PowerPC has no SREM/UREM instructions
183 setOperationAction(ISD::SREM, MVT::i32, Expand);
184 setOperationAction(ISD::UREM, MVT::i32, Expand);
185 setOperationAction(ISD::SREM, MVT::i64, Expand);
186 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000187
Scott Michel266bc8f2007-12-04 22:23:35 +0000188 // We don't support sin/cos/sqrt/fmod
189 setOperationAction(ISD::FSIN , MVT::f64, Expand);
190 setOperationAction(ISD::FCOS , MVT::f64, Expand);
191 setOperationAction(ISD::FREM , MVT::f64, Expand);
192 setOperationAction(ISD::FSIN , MVT::f32, Expand);
193 setOperationAction(ISD::FCOS , MVT::f32, Expand);
194 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000195
Scott Michel266bc8f2007-12-04 22:23:35 +0000196 // If we're enabling GP optimizations, use hardware square root
197 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
198 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000199
Scott Michel266bc8f2007-12-04 22:23:35 +0000200 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
201 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
202
203 // SPU can do rotate right and left, so legalize it... but customize for i8
204 // because instructions don't exist.
205 setOperationAction(ISD::ROTR, MVT::i32, Legal);
206 setOperationAction(ISD::ROTR, MVT::i16, Legal);
207 setOperationAction(ISD::ROTR, MVT::i8, Custom);
208 setOperationAction(ISD::ROTL, MVT::i32, Legal);
209 setOperationAction(ISD::ROTL, MVT::i16, Legal);
210 setOperationAction(ISD::ROTL, MVT::i8, Custom);
211 // SPU has no native version of shift left/right for i8
212 setOperationAction(ISD::SHL, MVT::i8, Custom);
213 setOperationAction(ISD::SRL, MVT::i8, Custom);
214 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michela59d4692008-02-23 18:41:37 +0000215 // And SPU needs custom lowering for shift left/right for i64
216 setOperationAction(ISD::SHL, MVT::i64, Custom);
217 setOperationAction(ISD::SRL, MVT::i64, Custom);
218 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000219
Scott Michel5af8f0e2008-07-16 17:17:29 +0000220 // Custom lower i8, i32 and i64 multiplications
221 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000222 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000223 setOperationAction(ISD::MUL, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000224
Scott Michel8bf61e82008-06-02 22:18:03 +0000225 // Need to custom handle (some) common i8, i64 math ops
226 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000227 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel8bf61e82008-06-02 22:18:03 +0000228 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000229
Scott Michel266bc8f2007-12-04 22:23:35 +0000230 // SPU does not have BSWAP. It does have i32 support CTLZ.
231 // CTPOP has to be custom lowered.
232 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
233 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
234
235 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
236 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
237 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
238 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
239
240 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
241 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
242
243 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000244
Scott Michel8bf61e82008-06-02 22:18:03 +0000245 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000246 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000247 setOperationAction(ISD::SELECT, MVT::i1, Promote);
248 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000249 setOperationAction(ISD::SELECT, MVT::i16, Legal);
250 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000251 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000252
Scott Michel78c47fa2008-03-10 16:58:52 +0000253 setOperationAction(ISD::SETCC, MVT::i1, Promote);
254 setOperationAction(ISD::SETCC, MVT::i8, Legal);
255 setOperationAction(ISD::SETCC, MVT::i16, Legal);
256 setOperationAction(ISD::SETCC, MVT::i32, Legal);
257 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michelad2715e2008-03-05 23:02:02 +0000258
Scott Michela59d4692008-02-23 18:41:37 +0000259 // Zero extension and sign extension for i64 have to be
260 // custom legalized
261 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
262 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
263 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000264
Scott Michel266bc8f2007-12-04 22:23:35 +0000265 // SPU has a legal FP -> signed INT instruction
266 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
267 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
268 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
269 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
270
271 // FDIV on SPU requires custom lowering
272 setOperationAction(ISD::FDIV, MVT::f32, Custom);
273 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
274
275 // SPU has [U|S]INT_TO_FP
276 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
277 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
278 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
279 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
280 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
281 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
282 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
283 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
284
Scott Michel86c041f2007-12-20 00:44:13 +0000285 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
286 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
287 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
288 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000289
290 // We cannot sextinreg(i1). Expand to shifts.
291 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000292
Scott Michel266bc8f2007-12-04 22:23:35 +0000293 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000294 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000295 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000296
297 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000298 // appropriate instructions to materialize the address.
Scott Michel053c1da2008-01-29 02:16:57 +0000299 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
300 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000301 MVT VT = (MVT::SimpleValueType)sctype;
302
303 setOperationAction(ISD::GlobalAddress, VT, Custom);
304 setOperationAction(ISD::ConstantPool, VT, Custom);
305 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000306 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000307
308 // RET must be custom lowered, to meet ABI requirements
309 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000310
Scott Michel266bc8f2007-12-04 22:23:35 +0000311 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
312 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000313
Scott Michel266bc8f2007-12-04 22:23:35 +0000314 // Use the default implementation.
315 setOperationAction(ISD::VAARG , MVT::Other, Expand);
316 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
317 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000318 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000319 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
320 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
321 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
322
323 // Cell SPU has instructions for converting between i64 and fp.
324 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
325 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000326
Scott Michel266bc8f2007-12-04 22:23:35 +0000327 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
328 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
329
330 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
331 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
332
333 // First set operation action for all vector types to expand. Then we
334 // will selectively turn on ones that can be effectively codegen'd.
335 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
336 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
337 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
338 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
339 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
340 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
341
Duncan Sands83ec4b62008-06-06 12:08:01 +0000342 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
343 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
344 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000345
Duncan Sands83ec4b62008-06-06 12:08:01 +0000346 // add/sub are legal for all supported vector VT's.
347 setOperationAction(ISD::ADD , VT, Legal);
348 setOperationAction(ISD::SUB , VT, Legal);
349 // mul has to be custom lowered.
350 setOperationAction(ISD::MUL , VT, Custom);
351
352 setOperationAction(ISD::AND , VT, Legal);
353 setOperationAction(ISD::OR , VT, Legal);
354 setOperationAction(ISD::XOR , VT, Legal);
355 setOperationAction(ISD::LOAD , VT, Legal);
356 setOperationAction(ISD::SELECT, VT, Legal);
357 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000358
Scott Michel266bc8f2007-12-04 22:23:35 +0000359 // These operations need to be expanded:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000360 setOperationAction(ISD::SDIV, VT, Expand);
361 setOperationAction(ISD::SREM, VT, Expand);
362 setOperationAction(ISD::UDIV, VT, Expand);
363 setOperationAction(ISD::UREM, VT, Expand);
364 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000365
366 // Custom lower build_vector, constant pool spills, insert and
367 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000368 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
369 setOperationAction(ISD::ConstantPool, VT, Custom);
370 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
371 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
372 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
373 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000374 }
375
376 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
377 setOperationAction(ISD::AND, MVT::v16i8, Custom);
378 setOperationAction(ISD::OR, MVT::v16i8, Custom);
379 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
380 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000381
Scott Michel266bc8f2007-12-04 22:23:35 +0000382 setShiftAmountType(MVT::i32);
383 setSetCCResultContents(ZeroOrOneSetCCResult);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000384
Scott Michel266bc8f2007-12-04 22:23:35 +0000385 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000386
Scott Michel266bc8f2007-12-04 22:23:35 +0000387 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000388 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000389 setTargetDAGCombine(ISD::ZERO_EXTEND);
390 setTargetDAGCombine(ISD::SIGN_EXTEND);
391 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000392
Scott Michel266bc8f2007-12-04 22:23:35 +0000393 computeRegisterProperties();
394}
395
396const char *
397SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
398{
399 if (node_names.empty()) {
400 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
401 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
402 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
403 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000404 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000405 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000406 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
407 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
408 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
409 node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
410 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
411 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
412 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
413 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED] = "SPUISD::EXTRACT_ELT0_CHAINED";
414 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
415 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
416 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
417 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
418 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
419 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
420 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
421 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michela59d4692008-02-23 18:41:37 +0000422 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
423 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000424 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
425 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
426 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
427 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
428 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michela59d4692008-02-23 18:41:37 +0000429 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
430 "SPUISD::ROTQUAD_RZ_BYTES";
431 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
432 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel266bc8f2007-12-04 22:23:35 +0000433 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
434 "SPUISD::ROTBYTES_RIGHT_S";
435 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
436 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
437 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel8bf61e82008-06-02 22:18:03 +0000438 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
439 "SPUISD::ROTBYTES_LEFT_BITS";
440 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000441 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000442 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
443 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
444 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
445 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000446 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
447 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
448 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
449 }
450
451 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
452
453 return ((i != node_names.end()) ? i->second : 0);
454}
455
Dan Gohman475871a2008-07-27 21:46:04 +0000456MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000457 MVT VT = Op.getValueType();
458 if (VT.isInteger())
Scott Michel405fba12008-03-10 23:49:09 +0000459 return VT;
460 else
461 return MVT::i32;
Scott Michel78c47fa2008-03-10 16:58:52 +0000462}
463
Scott Michel266bc8f2007-12-04 22:23:35 +0000464//===----------------------------------------------------------------------===//
465// Calling convention code:
466//===----------------------------------------------------------------------===//
467
468#include "SPUGenCallingConv.inc"
469
470//===----------------------------------------------------------------------===//
471// LowerOperation implementation
472//===----------------------------------------------------------------------===//
473
Scott Michel9de5d0d2008-01-11 02:53:15 +0000474/// Aligned load common code for CellSPU
475/*!
476 \param[in] Op The SelectionDAG load or store operand
477 \param[in] DAG The selection DAG
478 \param[in] ST CellSPU subtarget information structure
479 \param[in,out] alignment Caller initializes this to the load or store node's
480 value from getAlignment(), may be updated while generating the aligned load
481 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
482 offset (divisible by 16, modulo 16 == 0)
483 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
484 offset of the preferred slot (modulo 16 != 0)
485 \param[in,out] VT Caller initializes this value type to the the load or store
486 node's loaded or stored value type; may be updated if an i1-extended load or
487 store.
488 \param[out] was16aligned true if the base pointer had 16-byte alignment,
489 otherwise false. Can help to determine if the chunk needs to be rotated.
490
491 Both load and store lowering load a block of data aligned on a 16-byte
492 boundary. This is the common aligned load code shared between both.
493 */
Dan Gohman475871a2008-07-27 21:46:04 +0000494static SDValue
495AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Michel9de5d0d2008-01-11 02:53:15 +0000496 LSBaseSDNode *LSN,
497 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000498 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000499{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000500 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000501 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman475871a2008-07-27 21:46:04 +0000502 SDValue basePtr = LSN->getBasePtr();
503 SDValue chain = LSN->getChain();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000504
505 if (basePtr.getOpcode() == ISD::ADD) {
Dan Gohman475871a2008-07-27 21:46:04 +0000506 SDValue Op1 = basePtr.Val->getOperand(1);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000507
508 if (Op1.getOpcode() == ISD::Constant || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000509 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000510
511 alignOffs = (int) CN->getValue();
512 prefSlotOffs = (int) (alignOffs & 0xf);
513
514 // Adjust the rotation amount to ensure that the final result ends up in
515 // the preferred slot:
516 prefSlotOffs -= vtm->prefslot_byte;
517 basePtr = basePtr.getOperand(0);
518
Scott Michel58c58182008-01-17 20:38:41 +0000519 // Loading from memory, can we adjust alignment?
520 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +0000521 SDValue APtr = basePtr.getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000522 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
523 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
524 alignment = GSDN->getGlobal()->getAlignment();
525 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000526 }
527 } else {
528 alignOffs = 0;
529 prefSlotOffs = -vtm->prefslot_byte;
530 }
Scott Michel203b2d62008-04-30 00:30:08 +0000531 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
532 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
533 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
534 prefSlotOffs = (int) (alignOffs & 0xf);
535 prefSlotOffs -= vtm->prefslot_byte;
536 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000537 } else {
538 alignOffs = 0;
539 prefSlotOffs = -vtm->prefslot_byte;
540 }
541
542 if (alignment == 16) {
543 // Realign the base pointer as a D-Form address:
544 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000545 basePtr = DAG.getNode(ISD::ADD, PtrVT,
546 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000547 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000548 }
549
550 // Emit the vector load:
551 was16aligned = true;
552 return DAG.getLoad(MVT::v16i8, chain, basePtr,
553 LSN->getSrcValue(), LSN->getSrcValueOffset(),
554 LSN->isVolatile(), 16);
555 }
556
557 // Unaligned load or we're using the "large memory" model, which means that
558 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000559 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Scott Michel053c1da2008-01-29 02:16:57 +0000560 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr, DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000561 }
562
563 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000564 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000565 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000566 was16aligned = false;
567 return DAG.getLoad(MVT::v16i8, chain, basePtr,
568 LSN->getSrcValue(), LSN->getSrcValueOffset(),
569 LSN->isVolatile(), 16);
570}
571
Scott Michel266bc8f2007-12-04 22:23:35 +0000572/// Custom lower loads for CellSPU
573/*!
574 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
575 within a 16-byte block, we have to rotate to extract the requested element.
576 */
Dan Gohman475871a2008-07-27 21:46:04 +0000577static SDValue
578LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000579 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000580 SDValue the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000581 MVT VT = LN->getMemoryVT();
582 MVT OpVT = Op.Val->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000583 ISD::LoadExtType ExtType = LN->getExtensionType();
584 unsigned alignment = LN->getAlignment();
Dan Gohman475871a2008-07-27 21:46:04 +0000585 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000586
Scott Michel266bc8f2007-12-04 22:23:35 +0000587 switch (LN->getAddressingMode()) {
588 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000589 int offset, rotamt;
590 bool was16aligned;
Dan Gohman475871a2008-07-27 21:46:04 +0000591 SDValue result =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000592 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000593
Scott Michel9de5d0d2008-01-11 02:53:15 +0000594 if (result.Val == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000595 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000596
597 the_chain = result.getValue(1);
598 // Rotate the chunk if necessary
599 if (rotamt < 0)
600 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000601 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000602 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
603
Scott Michel58c58182008-01-17 20:38:41 +0000604 Ops[0] = the_chain;
605 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000606 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000607 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
608 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000609 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000610 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000611 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000612 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000613 }
614
615 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
616 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000617 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000618
619 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
620 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000621 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000622
Scott Michel9de5d0d2008-01-11 02:53:15 +0000623 // Convert the loaded v16i8 vector to the appropriate vector type
624 // specified by the operand:
625 if (OpVT == VT) {
626 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000627 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000628 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000629 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000630
631 Ops[0] = the_chain;
632 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
633 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
634 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
635 the_chain = result.getValue(1);
636 } else {
637 // Handle the sign and zero-extending loads for i1 and i8:
638 unsigned NewOpC;
639
640 if (ExtType == ISD::SEXTLOAD) {
641 NewOpC = (OpVT == MVT::i1
642 ? SPUISD::EXTRACT_I1_SEXT
643 : SPUISD::EXTRACT_I8_SEXT);
644 } else {
645 assert(ExtType == ISD::ZEXTLOAD);
646 NewOpC = (OpVT == MVT::i1
647 ? SPUISD::EXTRACT_I1_ZEXT
648 : SPUISD::EXTRACT_I8_ZEXT);
649 }
650
651 result = DAG.getNode(NewOpC, OpVT, result);
652 }
653
654 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000655 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000656 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000657 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000658 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000659
Scott Michel58c58182008-01-17 20:38:41 +0000660 result = DAG.getNode(SPUISD::LDRESULT, retvts,
661 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000662 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000663 }
664 case ISD::PRE_INC:
665 case ISD::PRE_DEC:
666 case ISD::POST_INC:
667 case ISD::POST_DEC:
668 case ISD::LAST_INDEXED_MODE:
669 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
670 "UNINDEXED\n";
671 cerr << (unsigned) LN->getAddressingMode() << "\n";
672 abort();
673 /*NOTREACHED*/
674 }
675
Dan Gohman475871a2008-07-27 21:46:04 +0000676 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000677}
678
679/// Custom lower stores for CellSPU
680/*!
681 All CellSPU stores are aligned to 16-byte boundaries, so for elements
682 within a 16-byte block, we have to generate a shuffle to insert the
683 requested element into its place, then store the resulting block.
684 */
Dan Gohman475871a2008-07-27 21:46:04 +0000685static SDValue
686LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000687 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000688 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000689 MVT VT = Value.getValueType();
690 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
691 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000692 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000693
694 switch (SN->getAddressingMode()) {
695 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000696 int chunk_offset, slot_offset;
697 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000698
699 // The vector type we really want to load from the 16-byte chunk, except
700 // in the case of MVT::i1, which has to be v16i8.
Duncan Sands83ec4b62008-06-06 12:08:01 +0000701 MVT vecVT, stVecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000702
Scott Michel266bc8f2007-12-04 22:23:35 +0000703 if (StVT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000704 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
705 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000706
Dan Gohman475871a2008-07-27 21:46:04 +0000707 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000708 AlignedLoad(Op, DAG, ST, SN, alignment,
709 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000710
Scott Michel9de5d0d2008-01-11 02:53:15 +0000711 if (alignLoadVec.Val == 0)
712 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000713
Scott Michel9de5d0d2008-01-11 02:53:15 +0000714 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000715 SDValue basePtr = LN->getBasePtr();
716 SDValue the_chain = alignLoadVec.getValue(1);
717 SDValue theValue = SN->getValue();
718 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000719
720 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000721 && (theValue.getOpcode() == ISD::AssertZext
722 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000723 // Drill down and get the value for zero- and sign-extended
724 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000725 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000726 }
727
Scott Michel9de5d0d2008-01-11 02:53:15 +0000728 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000729
Dan Gohman475871a2008-07-27 21:46:04 +0000730 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
731 SDValue insertEltPtr;
732 SDValue insertEltOp;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000733
734 // If the base pointer is already a D-form address, then just create
735 // a new D-form address with a slot offset and the orignal base pointer.
736 // Otherwise generate a D-form address with the slot offset relative
737 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000738 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
739 DEBUG(basePtr.Val->dump(&DAG));
740 DEBUG(cerr << "\n");
741
Scott Michel053c1da2008-01-29 02:16:57 +0000742 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
743 (basePtr.getOpcode() == ISD::ADD
744 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000745 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000746 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000747 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000748 }
749
750 insertEltOp = DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000751 result = DAG.getNode(SPUISD::SHUFB, vecVT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000752 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue),
753 alignLoadVec,
754 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000755
Scott Michel9de5d0d2008-01-11 02:53:15 +0000756 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000757 LN->getSrcValue(), LN->getSrcValueOffset(),
758 LN->isVolatile(), LN->getAlignment());
759
760 return result;
761 /*UNREACHED*/
762 }
763 case ISD::PRE_INC:
764 case ISD::PRE_DEC:
765 case ISD::POST_INC:
766 case ISD::POST_DEC:
767 case ISD::LAST_INDEXED_MODE:
768 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
769 "UNINDEXED\n";
770 cerr << (unsigned) SN->getAddressingMode() << "\n";
771 abort();
772 /*NOTREACHED*/
773 }
774
Dan Gohman475871a2008-07-27 21:46:04 +0000775 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000776}
777
778/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000779static SDValue
780LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000781 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000782 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
783 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000784 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
785 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000786 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000787
788 if (TM.getRelocationModel() == Reloc::Static) {
789 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000790 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000791 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000792 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000793 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
794 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000795 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000796 }
797 }
798
799 assert(0 &&
800 "LowerConstantPool: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000801 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000802}
803
Dan Gohman475871a2008-07-27 21:46:04 +0000804static SDValue
805LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000806 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000807 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000808 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
809 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000810 const TargetMachine &TM = DAG.getTarget();
811
812 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000813 if (!ST->usingLargeMem()) {
814 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
815 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000816 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
817 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000818 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
819 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000820 }
821
822 assert(0 &&
823 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000824 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000825}
826
Dan Gohman475871a2008-07-27 21:46:04 +0000827static SDValue
828LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000829 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000830 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
831 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000832 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000833 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000834 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000835
Scott Michel266bc8f2007-12-04 22:23:35 +0000836 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000837 if (!ST->usingLargeMem()) {
838 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
839 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000840 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
841 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000842 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
843 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000844 } else {
845 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000846 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000847 abort();
848 /*NOTREACHED*/
849 }
850
Dan Gohman475871a2008-07-27 21:46:04 +0000851 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000852}
853
854//! Custom lower i64 integer constants
855/*!
856 This code inserts all of the necessary juggling that needs to occur to load
857 a 64-bit constant into a register.
858 */
Dan Gohman475871a2008-07-27 21:46:04 +0000859static SDValue
860LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000861 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000862 ConstantSDNode *CN = cast<ConstantSDNode>(Op.Val);
863
864 if (VT == MVT::i64) {
Dan Gohman475871a2008-07-27 21:46:04 +0000865 SDValue T = DAG.getConstant(CN->getValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +0000866 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000867 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000868 } else {
869 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000870 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000871 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000872 abort();
873 /*NOTREACHED*/
874 }
875
Dan Gohman475871a2008-07-27 21:46:04 +0000876 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000877}
878
Nate Begemanccef5802008-02-14 18:43:04 +0000879//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000880static SDValue
881LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000882 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000883 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.Val);
884
885 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000886 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000887
Nate Begemanccef5802008-02-14 18:43:04 +0000888 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000889 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000890 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000891 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000892 }
893
Dan Gohman475871a2008-07-27 21:46:04 +0000894 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000895}
896
Scott Michel58c58182008-01-17 20:38:41 +0000897//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000898static SDValue
899LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000900{
Dan Gohman475871a2008-07-27 21:46:04 +0000901 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000902 MVT CondVT = Cond.getValueType();
903 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000904
905 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
906 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
907 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
908 Op.getOperand(0),
909 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
910 Op.getOperand(2));
911 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000912 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000913}
914
Dan Gohman475871a2008-07-27 21:46:04 +0000915static SDValue
916LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000917{
918 MachineFunction &MF = DAG.getMachineFunction();
919 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000920 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +0000921 SmallVector<SDValue, 8> ArgValues;
922 SDValue Root = Op.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000923 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
924
925 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
926 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000927
Scott Michel266bc8f2007-12-04 22:23:35 +0000928 unsigned ArgOffset = SPUFrameInfo::minStackSize();
929 unsigned ArgRegIdx = 0;
930 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000931
Duncan Sands83ec4b62008-06-06 12:08:01 +0000932 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000933
Scott Michel266bc8f2007-12-04 22:23:35 +0000934 // Add DAG nodes to load the arguments or copy them out of registers.
935 for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
Dan Gohman475871a2008-07-27 21:46:04 +0000936 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000937 bool needsLoad = false;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000938 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
939 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michel266bc8f2007-12-04 22:23:35 +0000940
Duncan Sands83ec4b62008-06-06 12:08:01 +0000941 switch (ObjectVT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000942 default: {
943 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000944 << ObjectVT.getMVTString()
Scott Michel266bc8f2007-12-04 22:23:35 +0000945 << "\n";
946 abort();
947 }
948 case MVT::i8:
949 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000950 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R8CRegClass);
951 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000952 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i8);
953 ++ArgRegIdx;
954 } else {
955 needsLoad = true;
956 }
957 break;
958 case MVT::i16:
959 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000960 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
961 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000962 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i16);
963 ++ArgRegIdx;
964 } else {
965 needsLoad = true;
966 }
967 break;
968 case MVT::i32:
969 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000970 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
971 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000972 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
973 ++ArgRegIdx;
974 } else {
975 needsLoad = true;
976 }
977 break;
978 case MVT::i64:
979 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000980 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64CRegClass);
981 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000982 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64);
983 ++ArgRegIdx;
984 } else {
985 needsLoad = true;
986 }
987 break;
988 case MVT::f32:
989 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000990 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
991 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000992 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f32);
993 ++ArgRegIdx;
994 } else {
995 needsLoad = true;
996 }
997 break;
998 case MVT::f64:
999 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001000 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64FPRegClass);
1001 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001002 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f64);
1003 ++ArgRegIdx;
1004 } else {
1005 needsLoad = true;
1006 }
1007 break;
1008 case MVT::v2f64:
1009 case MVT::v4f32:
Scott Michelad2715e2008-03-05 23:02:02 +00001010 case MVT::v2i64:
Scott Michel266bc8f2007-12-04 22:23:35 +00001011 case MVT::v4i32:
1012 case MVT::v8i16:
1013 case MVT::v16i8:
1014 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001015 unsigned VReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1016 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001017 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1018 ++ArgRegIdx;
1019 } else {
1020 needsLoad = true;
1021 }
1022 break;
1023 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001024
Scott Michel266bc8f2007-12-04 22:23:35 +00001025 // We need to load the argument to a virtual register if we determined above
1026 // that we ran out of physical registers of the appropriate type
1027 if (needsLoad) {
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001028 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001029 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001030 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001031 ArgOffset += StackSlotSize;
1032 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001033
Scott Michel266bc8f2007-12-04 22:23:35 +00001034 ArgValues.push_back(ArgVal);
1035 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001036
Scott Michel266bc8f2007-12-04 22:23:35 +00001037 // If the function takes variable number of arguments, make a frame index for
1038 // the start of the first vararg value... for expansion of llvm.va_start.
1039 if (isVarArg) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001040 VarArgsFrameIndex = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8,
Scott Michel266bc8f2007-12-04 22:23:35 +00001041 ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001042 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001043 // If this function is vararg, store any remaining integer argument regs to
1044 // their spots on the stack so that they may be loaded by deferencing the
1045 // result of va_next.
Dan Gohman475871a2008-07-27 21:46:04 +00001046 SmallVector<SDValue, 8> MemOps;
Scott Michel266bc8f2007-12-04 22:23:35 +00001047 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001048 unsigned VReg = RegInfo.createVirtualRegister(&SPU::GPRCRegClass);
1049 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Dan Gohman475871a2008-07-27 21:46:04 +00001050 SDValue Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
1051 SDValue Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001052 MemOps.push_back(Store);
1053 // Increment the address by four for the next argument to store
Dan Gohman475871a2008-07-27 21:46:04 +00001054 SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001055 FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
1056 }
1057 if (!MemOps.empty())
1058 Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
1059 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001060
Scott Michel266bc8f2007-12-04 22:23:35 +00001061 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001062
Scott Michel266bc8f2007-12-04 22:23:35 +00001063 // Return the new list of results.
Duncan Sandsf9516202008-06-30 10:19:09 +00001064 return DAG.getMergeValues(Op.Val->getVTList(), &ArgValues[0],
1065 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001066}
1067
1068/// isLSAAddress - Return the immediate to use if the specified
1069/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001070static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001071 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
1072 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001073
Scott Michel266bc8f2007-12-04 22:23:35 +00001074 int Addr = C->getValue();
1075 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1076 (Addr << 14 >> 14) != Addr)
1077 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001078
Scott Michel266bc8f2007-12-04 22:23:35 +00001079 return DAG.getConstant((int)C->getValue() >> 2, MVT::i32).Val;
1080}
1081
1082static
Dan Gohman475871a2008-07-27 21:46:04 +00001083SDValue
1084LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
1085 SDValue Chain = Op.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001086#if 0
1087 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
1088 bool isTailCall = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
1089#endif
Dan Gohman475871a2008-07-27 21:46:04 +00001090 SDValue Callee = Op.getOperand(4);
Scott Michel266bc8f2007-12-04 22:23:35 +00001091 unsigned NumOps = (Op.getNumOperands() - 5) / 2;
1092 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1093 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1094 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1095
1096 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001097 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001098
Scott Michel266bc8f2007-12-04 22:23:35 +00001099 // Accumulate how many bytes are to be pushed on the stack, including the
1100 // linkage area, and parameter passing area. According to the SPU ABI,
1101 // we minimally need space for [LR] and [SP]
1102 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001103
Scott Michel266bc8f2007-12-04 22:23:35 +00001104 // Set up a copy of the stack pointer for use loading and storing any
1105 // arguments that may not fit in the registers available for argument
1106 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001107 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001108
Scott Michel266bc8f2007-12-04 22:23:35 +00001109 // Figure out which arguments are going to go in registers, and which in
1110 // memory.
1111 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1112 unsigned ArgRegIdx = 0;
1113
1114 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001115 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001116 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001117 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001118
1119 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001120 SDValue Arg = Op.getOperand(5+2*i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001121
Scott Michel266bc8f2007-12-04 22:23:35 +00001122 // PtrOff will be used to store the current argument to the stack if a
1123 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001124 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001125 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1126
Duncan Sands83ec4b62008-06-06 12:08:01 +00001127 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001128 default: assert(0 && "Unexpected ValueType for argument!");
1129 case MVT::i32:
1130 case MVT::i64:
1131 case MVT::i128:
1132 if (ArgRegIdx != NumArgRegs) {
1133 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1134 } else {
1135 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001136 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001137 }
1138 break;
1139 case MVT::f32:
1140 case MVT::f64:
1141 if (ArgRegIdx != NumArgRegs) {
1142 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1143 } else {
1144 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001145 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001146 }
1147 break;
1148 case MVT::v4f32:
1149 case MVT::v4i32:
1150 case MVT::v8i16:
1151 case MVT::v16i8:
1152 if (ArgRegIdx != NumArgRegs) {
1153 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1154 } else {
1155 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001156 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001157 }
1158 break;
1159 }
1160 }
1161
1162 // Update number of stack bytes actually used, insert a call sequence start
1163 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
1164 Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumStackBytes, PtrVT));
1165
1166 if (!MemOpChains.empty()) {
1167 // Adjust the stack pointer for the stack arguments.
1168 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1169 &MemOpChains[0], MemOpChains.size());
1170 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001171
Scott Michel266bc8f2007-12-04 22:23:35 +00001172 // Build a sequence of copy-to-reg nodes chained together with token chain
1173 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001174 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001175 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1176 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1177 InFlag);
1178 InFlag = Chain.getValue(1);
1179 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001180
Dan Gohman475871a2008-07-27 21:46:04 +00001181 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001182 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001183
Scott Michel266bc8f2007-12-04 22:23:35 +00001184 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1185 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1186 // node so that legalize doesn't hack it.
1187 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1188 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001189 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001190 SDValue Zero = DAG.getConstant(0, PtrVT);
1191 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001192
Scott Michel9de5d0d2008-01-11 02:53:15 +00001193 if (!ST->usingLargeMem()) {
1194 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1195 // style calls, otherwise, external symbols are BRASL calls. This assumes
1196 // that declared/defined symbols are in the same compilation unit and can
1197 // be reached through PC-relative jumps.
1198 //
1199 // NOTE:
1200 // This may be an unsafe assumption for JIT and really large compilation
1201 // units.
1202 if (GV->isDeclaration()) {
1203 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1204 } else {
1205 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1206 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001207 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001208 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1209 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001210 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001211 }
1212 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
1213 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001214 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001215 // If this is an absolute destination address that appears to be a legal
1216 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001217 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001218 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001219
1220 Ops.push_back(Chain);
1221 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001222
Scott Michel266bc8f2007-12-04 22:23:35 +00001223 // Add argument registers to the end of the list so that they are known live
1224 // into the call.
1225 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001226 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001227 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001228
Scott Michel266bc8f2007-12-04 22:23:35 +00001229 if (InFlag.Val)
1230 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001231 // Returns a chain and a flag for retval copy to use.
1232 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1233 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001234 InFlag = Chain.getValue(1);
1235
Evan Chengebaaa912008-02-05 22:44:06 +00001236 Chain = DAG.getCALLSEQ_END(Chain,
1237 DAG.getConstant(NumStackBytes, PtrVT),
1238 DAG.getConstant(0, PtrVT),
1239 InFlag);
1240 if (Op.Val->getValueType(0) != MVT::Other)
1241 InFlag = Chain.getValue(1);
1242
Dan Gohman475871a2008-07-27 21:46:04 +00001243 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001244 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001245
Scott Michel266bc8f2007-12-04 22:23:35 +00001246 // If the call has results, copy the values out of the ret val registers.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001247 switch (Op.Val->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001248 default: assert(0 && "Unexpected ret value!");
1249 case MVT::Other: break;
1250 case MVT::i32:
1251 if (Op.Val->getValueType(1) == MVT::i32) {
1252 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1253 ResultVals[0] = Chain.getValue(0);
1254 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1255 Chain.getValue(2)).getValue(1);
1256 ResultVals[1] = Chain.getValue(0);
1257 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001258 } else {
1259 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1260 ResultVals[0] = Chain.getValue(0);
1261 NumResults = 1;
1262 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001263 break;
1264 case MVT::i64:
1265 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1266 ResultVals[0] = Chain.getValue(0);
1267 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001268 break;
1269 case MVT::f32:
1270 case MVT::f64:
1271 Chain = DAG.getCopyFromReg(Chain, SPU::R3, Op.Val->getValueType(0),
1272 InFlag).getValue(1);
1273 ResultVals[0] = Chain.getValue(0);
1274 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001275 break;
1276 case MVT::v2f64:
1277 case MVT::v4f32:
1278 case MVT::v4i32:
1279 case MVT::v8i16:
1280 case MVT::v16i8:
1281 Chain = DAG.getCopyFromReg(Chain, SPU::R3, Op.Val->getValueType(0),
1282 InFlag).getValue(1);
1283 ResultVals[0] = Chain.getValue(0);
1284 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001285 break;
1286 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001287
Scott Michel266bc8f2007-12-04 22:23:35 +00001288 // If the function returns void, just return the chain.
1289 if (NumResults == 0)
1290 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001291
Scott Michel266bc8f2007-12-04 22:23:35 +00001292 // Otherwise, merge everything together with a MERGE_VALUES node.
1293 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001294 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Scott Michel266bc8f2007-12-04 22:23:35 +00001295 return Res.getValue(Op.ResNo);
1296}
1297
Dan Gohman475871a2008-07-27 21:46:04 +00001298static SDValue
1299LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001300 SmallVector<CCValAssign, 16> RVLocs;
1301 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1302 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1303 CCState CCInfo(CC, isVarArg, TM, RVLocs);
1304 CCInfo.AnalyzeReturn(Op.Val, RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001305
Scott Michel266bc8f2007-12-04 22:23:35 +00001306 // If this is the first return lowered for this function, add the regs to the
1307 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001308 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001309 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001310 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001311 }
1312
Dan Gohman475871a2008-07-27 21:46:04 +00001313 SDValue Chain = Op.getOperand(0);
1314 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001315
Scott Michel266bc8f2007-12-04 22:23:35 +00001316 // Copy the result values into the output registers.
1317 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1318 CCValAssign &VA = RVLocs[i];
1319 assert(VA.isRegLoc() && "Can only return in registers!");
1320 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1321 Flag = Chain.getValue(1);
1322 }
1323
1324 if (Flag.Val)
1325 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1326 else
1327 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1328}
1329
1330
1331//===----------------------------------------------------------------------===//
1332// Vector related lowering:
1333//===----------------------------------------------------------------------===//
1334
1335static ConstantSDNode *
1336getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001337 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001338
Scott Michel266bc8f2007-12-04 22:23:35 +00001339 // Check to see if this buildvec has a single non-undef value in its elements.
1340 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1341 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
1342 if (OpVal.Val == 0)
1343 OpVal = N->getOperand(i);
1344 else if (OpVal != N->getOperand(i))
1345 return 0;
1346 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001347
Scott Michel266bc8f2007-12-04 22:23:35 +00001348 if (OpVal.Val != 0) {
1349 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1350 return CN;
1351 }
1352 }
1353
1354 return 0; // All UNDEF: use implicit def.; not Constant node
1355}
1356
1357/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1358/// and the value fits into an unsigned 18-bit constant, and if so, return the
1359/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001360SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001361 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001362 if (ConstantSDNode *CN = getVecImm(N)) {
1363 uint64_t Value = CN->getValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001364 if (ValueType == MVT::i64) {
1365 uint64_t UValue = CN->getValue();
1366 uint32_t upper = uint32_t(UValue >> 32);
1367 uint32_t lower = uint32_t(UValue);
1368 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001369 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001370 Value = Value >> 32;
1371 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001372 if (Value <= 0x3ffff)
1373 return DAG.getConstant(Value, ValueType);
1374 }
1375
Dan Gohman475871a2008-07-27 21:46:04 +00001376 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001377}
1378
1379/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1380/// and the value fits into a signed 16-bit constant, and if so, return the
1381/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001382SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001383 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001384 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001385 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001386 if (ValueType == MVT::i64) {
1387 uint64_t UValue = CN->getValue();
1388 uint32_t upper = uint32_t(UValue >> 32);
1389 uint32_t lower = uint32_t(UValue);
1390 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001391 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001392 Value = Value >> 32;
1393 }
Scott Michelad2715e2008-03-05 23:02:02 +00001394 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
1395 return DAG.getConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001396 }
1397 }
1398
Dan Gohman475871a2008-07-27 21:46:04 +00001399 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001400}
1401
1402/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1403/// and the value fits into a signed 10-bit constant, and if so, return the
1404/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001405SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001406 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001407 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001408 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001409 if (ValueType == MVT::i64) {
1410 uint64_t UValue = CN->getValue();
1411 uint32_t upper = uint32_t(UValue >> 32);
1412 uint32_t lower = uint32_t(UValue);
1413 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001414 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001415 Value = Value >> 32;
1416 }
Scott Michelad2715e2008-03-05 23:02:02 +00001417 if (isS10Constant(Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001418 return DAG.getConstant(Value, ValueType);
1419 }
1420
Dan Gohman475871a2008-07-27 21:46:04 +00001421 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001422}
1423
1424/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1425/// and the value fits into a signed 8-bit constant, and if so, return the
1426/// constant.
1427///
1428/// @note: The incoming vector is v16i8 because that's the only way we can load
1429/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1430/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001431SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001432 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001433 if (ConstantSDNode *CN = getVecImm(N)) {
1434 int Value = (int) CN->getValue();
1435 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001436 && Value <= 0xffff /* truncated from uint64_t */
1437 && ((short) Value >> 8) == ((short) Value & 0xff))
Scott Michel266bc8f2007-12-04 22:23:35 +00001438 return DAG.getConstant(Value & 0xff, ValueType);
1439 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001440 && (Value & 0xff) == Value)
Scott Michel266bc8f2007-12-04 22:23:35 +00001441 return DAG.getConstant(Value, ValueType);
1442 }
1443
Dan Gohman475871a2008-07-27 21:46:04 +00001444 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001445}
1446
1447/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1448/// and the value fits into a signed 16-bit constant, and if so, return the
1449/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001450SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001451 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001452 if (ConstantSDNode *CN = getVecImm(N)) {
1453 uint64_t Value = CN->getValue();
1454 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001455 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1456 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001457 return DAG.getConstant(Value >> 16, ValueType);
1458 }
1459
Dan Gohman475871a2008-07-27 21:46:04 +00001460 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001461}
1462
1463/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001464SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001465 if (ConstantSDNode *CN = getVecImm(N)) {
1466 return DAG.getConstant((unsigned) CN->getValue(), MVT::i32);
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 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001473SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001474 if (ConstantSDNode *CN = getVecImm(N)) {
1475 return DAG.getConstant((unsigned) CN->getValue(), MVT::i64);
1476 }
1477
Dan Gohman475871a2008-07-27 21:46:04 +00001478 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001479}
1480
1481// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001482// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001483// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1484// zero. Return true if this is not an array of constants, false if it is.
1485//
1486static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1487 uint64_t UndefBits[2]) {
1488 // Start with zero'd results.
1489 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001490
Duncan Sands83ec4b62008-06-06 12:08:01 +00001491 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001492 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001493 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001494
Scott Michel266bc8f2007-12-04 22:23:35 +00001495 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1496 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1497
1498 uint64_t EltBits = 0;
1499 if (OpVal.getOpcode() == ISD::UNDEF) {
1500 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1501 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1502 continue;
1503 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1504 EltBits = CN->getValue() & (~0ULL >> (64-EltBitSize));
1505 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
1506 const APFloat &apf = CN->getValueAPF();
1507 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001508 ? FloatToBits(apf.convertToFloat())
1509 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001510 } else {
1511 // Nonconstant element.
1512 return true;
1513 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001514
Scott Michel266bc8f2007-12-04 22:23:35 +00001515 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1516 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001517
1518 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001519 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1520 return false;
1521}
1522
1523/// If this is a splat (repetition) of a value across the whole vector, return
1524/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001525/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001526/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001527static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001528 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001529 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001530 uint64_t &SplatBits, uint64_t &SplatUndef,
1531 int &SplatSize) {
1532 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1533 // the same as the lower 64-bits, ignoring undefs.
1534 uint64_t Bits64 = Bits128[0] | Bits128[1];
1535 uint64_t Undef64 = Undef128[0] & Undef128[1];
1536 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1537 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1538 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1539 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1540
1541 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1542 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001543
Scott Michel266bc8f2007-12-04 22:23:35 +00001544 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1545 // undefs.
1546 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001547 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001548
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001549 // If the top 16-bits are different than the lower 16-bits, ignoring
1550 // undefs, we have an i32 splat.
1551 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1552 if (MinSplatBits < 16) {
1553 // If the top 8-bits are different than the lower 8-bits, ignoring
1554 // undefs, we have an i16 splat.
1555 if ((Bits16 & (uint16_t(~Undef16) >> 8)) == ((Bits16 >> 8) & ~Undef16)) {
1556 // Otherwise, we have an 8-bit splat.
1557 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1558 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1559 SplatSize = 1;
1560 return true;
1561 }
1562 } else {
1563 SplatBits = Bits16;
1564 SplatUndef = Undef16;
1565 SplatSize = 2;
1566 return true;
1567 }
1568 }
1569 } else {
1570 SplatBits = Bits32;
1571 SplatUndef = Undef32;
1572 SplatSize = 4;
1573 return true;
1574 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001575 }
1576 } else {
1577 SplatBits = Bits128[0];
1578 SplatUndef = Undef128[0];
1579 SplatSize = 8;
1580 return true;
1581 }
1582 }
1583
1584 return false; // Can't be a splat if two pieces don't match.
1585}
1586
1587// If this is a case we can't handle, return null and let the default
1588// expansion code take care of it. If we CAN select this case, and if it
1589// selects to a single instruction, return Op. Otherwise, if we can codegen
1590// this case more efficiently than a constant pool load, lower it to the
1591// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001592static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001593 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001594 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001595 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001596 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001597 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001598 uint64_t VectorBits[2];
1599 uint64_t UndefBits[2];
1600 uint64_t SplatBits, SplatUndef;
1601 int SplatSize;
1602 if (GetConstantBuildVectorBits(Op.Val, VectorBits, UndefBits)
1603 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001604 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001605 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001606 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001607
Duncan Sands83ec4b62008-06-06 12:08:01 +00001608 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001609 default:
1610 case MVT::v4f32: {
1611 uint32_t Value32 = SplatBits;
1612 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001613 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001614 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001615 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001616 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001617 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001618 break;
1619 }
1620 case MVT::v2f64: {
1621 uint64_t f64val = SplatBits;
1622 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001623 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
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(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001626 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001627 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001628 break;
1629 }
1630 case MVT::v16i8: {
1631 // 8-bit constants have to be expanded to 16-bits
1632 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001633 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001634 for (int i = 0; i < 8; ++i)
1635 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1636 return DAG.getNode(ISD::BIT_CONVERT, VT,
1637 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1638 }
1639 case MVT::v8i16: {
1640 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001641 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001642 Value16 = (unsigned short) (SplatBits & 0xffff);
1643 else
1644 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001645 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1646 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001647 for (int i = 0; i < 8; ++i) Ops[i] = T;
1648 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1649 }
1650 case MVT::v4i32: {
1651 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001652 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001653 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1654 }
1655 case MVT::v2i64: {
1656 uint64_t val = SplatBits;
1657 uint32_t upper = uint32_t(val >> 32);
1658 uint32_t lower = uint32_t(val);
1659
Scott Michel4cb8bd82008-03-06 04:02:54 +00001660 if (upper == lower) {
1661 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001662 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001663 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001664 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001665 SDValue LO32;
1666 SDValue HI32;
1667 SmallVector<SDValue, 16> ShufBytes;
1668 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001669 bool upper_special, lower_special;
1670
1671 // NOTE: This code creates common-case shuffle masks that can be easily
1672 // detected as common expressions. It is not attempting to create highly
1673 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1674
1675 // Detect if the upper or lower half is a special shuffle mask pattern:
1676 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1677 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1678
1679 // Create lower vector if not a special pattern
1680 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001681 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001682 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1683 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1684 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001685 }
1686
1687 // Create upper vector if not a special pattern
1688 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001689 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001690 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1691 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1692 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001693 }
1694
1695 // If either upper or lower are special, then the two input operands are
1696 // the same (basically, one of them is a "don't care")
1697 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001698 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001699 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001700 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001701 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001702 // Unhappy situation... both upper and lower are special, so punt with
1703 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001704 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001705 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001706 Zero, Zero);
1707 }
1708
1709 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001710 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001711 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001712 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001713 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001714 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001715 process_upper = (upper_special && (i & 1) == 0);
1716 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001717
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001718 if (process_upper || process_lower) {
1719 if ((process_upper && upper == 0)
1720 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001721 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001722 else if ((process_upper && upper == 0xffffffff)
1723 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001724 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001725 else if ((process_upper && upper == 0x80000000)
1726 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001727 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001728 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001729 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001730 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001731
1732 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001733 }
1734
1735 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001736 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001737 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001738 }
1739 }
1740 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001741
Dan Gohman475871a2008-07-27 21:46:04 +00001742 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001743}
1744
1745/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1746/// which the Cell can operate. The code inspects V3 to ascertain whether the
1747/// permutation vector, V3, is monotonically increasing with one "exception"
1748/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1749/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1750/// In either case, the net result is going to eventually invoke SHUFB to
1751/// permute/shuffle the bytes from V1 and V2.
1752/// \note
1753/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1754/// control word for byte/halfword/word insertion. This takes care of a single
1755/// element move from V2 into V1.
1756/// \note
1757/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001758static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1759 SDValue V1 = Op.getOperand(0);
1760 SDValue V2 = Op.getOperand(1);
1761 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001762
Scott Michel266bc8f2007-12-04 22:23:35 +00001763 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001764
Scott Michel266bc8f2007-12-04 22:23:35 +00001765 // If we have a single element being moved from V1 to V2, this can be handled
1766 // using the C*[DX] compute mask instructions, but the vector elements have
1767 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001768 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001769 unsigned EltsFromV2 = 0;
1770 unsigned V2Elt = 0;
1771 unsigned V2EltIdx0 = 0;
1772 unsigned CurrElt = 0;
1773 bool monotonic = true;
1774 if (EltVT == MVT::i8)
1775 V2EltIdx0 = 16;
1776 else if (EltVT == MVT::i16)
1777 V2EltIdx0 = 8;
1778 else if (EltVT == MVT::i32)
1779 V2EltIdx0 = 4;
1780 else
1781 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1782
1783 for (unsigned i = 0, e = PermMask.getNumOperands();
1784 EltsFromV2 <= 1 && monotonic && i != e;
1785 ++i) {
1786 unsigned SrcElt;
1787 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1788 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001789 else
Scott Michel266bc8f2007-12-04 22:23:35 +00001790 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getValue();
1791
1792 if (SrcElt >= V2EltIdx0) {
1793 ++EltsFromV2;
1794 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1795 } else if (CurrElt != SrcElt) {
1796 monotonic = false;
1797 }
1798
1799 ++CurrElt;
1800 }
1801
1802 if (EltsFromV2 == 1 && monotonic) {
1803 // Compute mask and shuffle
1804 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001805 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1806 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001807 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001808 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001809 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001810 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1811 // Copy register's contents as index in INSERT_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001812 SDValue ShufMaskOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001813 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001814 DAG.getTargetConstant(V2Elt, MVT::i32),
1815 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001816 // Use shuffle mask in SHUFB synthetic instruction:
1817 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1818 } else {
1819 // Convert the SHUFFLE_VECTOR mask's input element units to the actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001820 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001821
Dan Gohman475871a2008-07-27 21:46:04 +00001822 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001823 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1824 unsigned SrcElt;
1825 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001826 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001827 else
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001828 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001829
Scott Michela59d4692008-02-23 18:41:37 +00001830 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001831 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1832 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001833 }
1834 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001835
Dan Gohman475871a2008-07-27 21:46:04 +00001836 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001837 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001838 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1839 }
1840}
1841
Dan Gohman475871a2008-07-27 21:46:04 +00001842static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1843 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001844
1845 if (Op0.Val->getOpcode() == ISD::Constant) {
1846 // For a constant, build the appropriate constant vector, which will
1847 // eventually simplify to a vector register load.
1848
1849 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.Val);
Dan Gohman475871a2008-07-27 21:46:04 +00001850 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001851 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001852 size_t n_copies;
1853
1854 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001855 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001856 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001857 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001858 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1859 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1860 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1861 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1862 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1863 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1864 }
1865
Dan Gohman475871a2008-07-27 21:46:04 +00001866 SDValue CValue = DAG.getConstant(CN->getValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001867 for (size_t j = 0; j < n_copies; ++j)
1868 ConstVecValues.push_back(CValue);
1869
1870 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001871 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001872 } else {
1873 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001874 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001875 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1876 case MVT::i8:
1877 case MVT::i16:
1878 case MVT::i32:
1879 case MVT::i64:
1880 case MVT::f32:
1881 case MVT::f64:
1882 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1883 }
1884 }
1885
Dan Gohman475871a2008-07-27 21:46:04 +00001886 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001887}
1888
Dan Gohman475871a2008-07-27 21:46:04 +00001889static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001890 switch (Op.getValueType().getSimpleVT()) {
1891 default:
1892 cerr << "CellSPU: Unknown vector multiplication, got "
1893 << Op.getValueType().getMVTString()
1894 << "\n";
1895 abort();
1896 /*NOTREACHED*/
1897
Scott Michel266bc8f2007-12-04 22:23:35 +00001898 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001899 SDValue rA = Op.getOperand(0);
1900 SDValue rB = Op.getOperand(1);
1901 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1902 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1903 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1904 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001905
1906 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1907 break;
1908 }
1909
1910 // Multiply two v8i16 vectors (pipeline friendly version):
1911 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1912 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1913 // c) Use SELB to select upper and lower halves from the intermediate results
1914 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001915 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001916 // dual-issue. This code does manage to do this, even if it's a little on
1917 // the wacky side
1918 case MVT::v8i16: {
1919 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001920 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001921 SDValue Chain = Op.getOperand(0);
1922 SDValue rA = Op.getOperand(0);
1923 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001924 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1925 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001926
Dan Gohman475871a2008-07-27 21:46:04 +00001927 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001928 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001929 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001930 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001931
Dan Gohman475871a2008-07-27 21:46:04 +00001932 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001933 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001934 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001935
Dan Gohman475871a2008-07-27 21:46:04 +00001936 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001937 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001938 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001939
1940 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001941 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1942 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1943 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1944 HHProd_v4i32,
1945 DAG.getConstant(16, MVT::i16))),
1946 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001947 }
1948
1949 // This M00sE is N@stI! (apologies to Monty Python)
1950 //
1951 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1952 // is to break it all apart, sign extend, and reassemble the various
1953 // intermediate products.
1954 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001955 SDValue rA = Op.getOperand(0);
1956 SDValue rB = Op.getOperand(1);
1957 SDValue c8 = DAG.getConstant(8, MVT::i32);
1958 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001959
Dan Gohman475871a2008-07-27 21:46:04 +00001960 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001961 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001962 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1963 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001964
Dan Gohman475871a2008-07-27 21:46:04 +00001965 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001966
Dan Gohman475871a2008-07-27 21:46:04 +00001967 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001968
Dan Gohman475871a2008-07-27 21:46:04 +00001969 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001970 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001971 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001972
Dan Gohman475871a2008-07-27 21:46:04 +00001973 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001974 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001975
Dan Gohman475871a2008-07-27 21:46:04 +00001976 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001977 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1978 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1979 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001980
Dan Gohman475871a2008-07-27 21:46:04 +00001981 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001982
Dan Gohman475871a2008-07-27 21:46:04 +00001983 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001984 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00001985 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001986 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1987 LoProdMask, LoProdMask,
1988 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001989
Dan Gohman475871a2008-07-27 21:46:04 +00001990 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001991 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001992 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001993
Dan Gohman475871a2008-07-27 21:46:04 +00001994 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001995 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001996 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001997
Dan Gohman475871a2008-07-27 21:46:04 +00001998 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001999 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002000 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2001 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00002002
Dan Gohman475871a2008-07-27 21:46:04 +00002003 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002004 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002005 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
2006 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32, rAH, c8)),
2007 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
2008 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002009
Dan Gohman475871a2008-07-27 21:46:04 +00002010 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00002011 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2012 HLProd,
2013 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2014 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002015
Dan Gohman475871a2008-07-27 21:46:04 +00002016 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002017 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002018
2019 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002020 DAG.getNode(ISD::OR, MVT::v4i32,
2021 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002022 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002023 }
2024
Dan Gohman475871a2008-07-27 21:46:04 +00002025 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002026}
2027
Dan Gohman475871a2008-07-27 21:46:04 +00002028static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002029 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002030 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002031
Dan Gohman475871a2008-07-27 21:46:04 +00002032 SDValue A = Op.getOperand(0);
2033 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002034 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002035
2036 unsigned VRegBR, VRegC;
2037
2038 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002039 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2040 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002041 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002042 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2043 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002044 }
2045 // TODO: make sure we're feeding FPInterp the right arguments
2046 // Right now: fi B, frest(B)
2047
2048 // Computes BRcpl =
2049 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002050 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002051 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2052 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002053 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002054
Scott Michel266bc8f2007-12-04 22:23:35 +00002055 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002056 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002057 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002058 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002059 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002060 // What's the Chain variable do? It's magic!
2061 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002062
2063 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002064 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002065 DAG.getNode(ISD::FMUL, VT,
2066 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002067 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002068 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002069 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002070}
2071
Dan Gohman475871a2008-07-27 21:46:04 +00002072static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002073 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002074 SDValue N = Op.getOperand(0);
2075 SDValue Elt = Op.getOperand(1);
2076 SDValue ShufMask[16];
Scott Michel266bc8f2007-12-04 22:23:35 +00002077 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
2078
2079 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2080
2081 int EltNo = (int) C->getValue();
2082
2083 // sanity checks:
2084 if (VT == MVT::i8 && EltNo >= 16)
2085 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2086 else if (VT == MVT::i16 && EltNo >= 8)
2087 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2088 else if (VT == MVT::i32 && EltNo >= 4)
2089 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2090 else if (VT == MVT::i64 && EltNo >= 2)
2091 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2092
2093 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2094 // i32 and i64: Element 0 is the preferred slot
2095 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2096 }
2097
2098 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002099 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002100 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002101
Duncan Sands83ec4b62008-06-06 12:08:01 +00002102 switch (VT.getSimpleVT()) {
2103 default:
2104 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002105 case MVT::i8: {
2106 prefslot_begin = prefslot_end = 3;
2107 break;
2108 }
2109 case MVT::i16: {
2110 prefslot_begin = 2; prefslot_end = 3;
2111 break;
2112 }
2113 case MVT::i32: {
2114 prefslot_begin = 0; prefslot_end = 3;
2115 break;
2116 }
2117 case MVT::i64: {
2118 prefslot_begin = 0; prefslot_end = 7;
2119 break;
2120 }
2121 }
2122
Scott Michel0e5665b2007-12-19 21:17:42 +00002123 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002124 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002125
Scott Michel266bc8f2007-12-04 22:23:35 +00002126 for (int i = 0; i < 16; ++i) {
2127 // zero fill uppper part of preferred slot, don't care about the
2128 // other slots:
2129 unsigned int mask_val;
2130
2131 if (i <= prefslot_end) {
2132 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002133 ((i < prefslot_begin)
2134 ? 0x80
2135 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002136
Scott Michel0e5665b2007-12-19 21:17:42 +00002137 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002138 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002139 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2140 }
2141
Dan Gohman475871a2008-07-27 21:46:04 +00002142 SDValue ShufMaskVec =
Scott Michel266bc8f2007-12-04 22:23:35 +00002143 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002144 &ShufMask[0],
2145 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002146
2147 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002148 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2149 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002150
Scott Michel266bc8f2007-12-04 22:23:35 +00002151}
2152
Dan Gohman475871a2008-07-27 21:46:04 +00002153static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2154 SDValue VecOp = Op.getOperand(0);
2155 SDValue ValOp = Op.getOperand(1);
2156 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002157 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002158
2159 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2160 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2161
Duncan Sands83ec4b62008-06-06 12:08:01 +00002162 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002163 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002164 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002165
Dan Gohman475871a2008-07-27 21:46:04 +00002166 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002167 DAG.getNode(SPUISD::SHUFB, VT,
2168 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2169 VecOp,
2170 DAG.getNode(SPUISD::INSERT_MASK, VT,
2171 DAG.getNode(ISD::ADD, PtrVT,
2172 PtrBase,
2173 DAG.getConstant(CN->getValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002174 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002175
2176 return result;
2177}
2178
Dan Gohman475871a2008-07-27 21:46:04 +00002179static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002180{
Dan Gohman475871a2008-07-27 21:46:04 +00002181 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002182
2183 assert(Op.getValueType() == MVT::i8);
2184 switch (Opc) {
2185 default:
2186 assert(0 && "Unhandled i8 math operator");
2187 /*NOTREACHED*/
2188 break;
2189 case ISD::SUB: {
2190 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2191 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002192 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002193 N0 = (N0.getOpcode() != ISD::Constant
2194 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
2195 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
2196 N1 = (N1.getOpcode() != ISD::Constant
2197 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
2198 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002199 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002200 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002201 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002202 case ISD::ROTR:
2203 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002204 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002205 unsigned N1Opc;
2206 N0 = (N0.getOpcode() != ISD::Constant
2207 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
2208 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002209 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::ZERO_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002210 N1 = (N1.getOpcode() != ISD::Constant
2211 ? DAG.getNode(N1Opc, MVT::i16, N1)
2212 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002213 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002214 DAG.getNode(ISD::OR, MVT::i16, N0,
2215 DAG.getNode(ISD::SHL, MVT::i16,
2216 N0, DAG.getConstant(8, MVT::i16)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002217 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002218 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2219 }
2220 case ISD::SRL:
2221 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002222 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002223 unsigned N1Opc;
2224 N0 = (N0.getOpcode() != ISD::Constant
2225 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
2226 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002227 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::ZERO_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002228 N1 = (N1.getOpcode() != ISD::Constant
2229 ? DAG.getNode(N1Opc, MVT::i16, N1)
2230 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002231 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002232 DAG.getNode(Opc, MVT::i16, N0, N1));
2233 }
2234 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002235 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002236 unsigned N1Opc;
2237 N0 = (N0.getOpcode() != ISD::Constant
2238 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
2239 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002240 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002241 N1 = (N1.getOpcode() != ISD::Constant
2242 ? DAG.getNode(N1Opc, MVT::i16, N1)
2243 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002244 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002245 DAG.getNode(Opc, MVT::i16, N0, N1));
2246 }
2247 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002248 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002249 unsigned N1Opc;
2250 N0 = (N0.getOpcode() != ISD::Constant
2251 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
2252 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002253 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002254 N1 = (N1.getOpcode() != ISD::Constant
2255 ? DAG.getNode(N1Opc, MVT::i16, N1)
2256 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002257 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002258 DAG.getNode(Opc, MVT::i16, N0, N1));
2259 break;
2260 }
2261 }
2262
Dan Gohman475871a2008-07-27 21:46:04 +00002263 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002264}
2265
Dan Gohman475871a2008-07-27 21:46:04 +00002266static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002267{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002268 MVT VT = Op.getValueType();
2269 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002270
Dan Gohman475871a2008-07-27 21:46:04 +00002271 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002272
2273 switch (Opc) {
2274 case ISD::ZERO_EXTEND:
2275 case ISD::SIGN_EXTEND:
2276 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002277 MVT Op0VT = Op0.getValueType();
2278 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002279
2280 assert(Op0VT == MVT::i32
2281 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002282 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002283
2284 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2285 ? SPUISD::ROTBYTES_RIGHT_S
2286 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002287 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002288 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2289
2290 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2291 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2292 DAG.getNode(NewOpc, Op0VecVT,
2293 PromoteScalar,
2294 DAG.getConstant(4, MVT::i32))));
2295 }
2296
Scott Michel8bf61e82008-06-02 22:18:03 +00002297 case ISD::ADD: {
2298 // Turn operands into vectors to satisfy type checking (shufb works on
2299 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002300 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002301 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002302 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002303 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002304 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002305
2306 // Create the shuffle mask for "rotating" the borrow up one register slot
2307 // once the borrow is generated.
2308 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2309 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2310 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2311 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2312
Dan Gohman475871a2008-07-27 21:46:04 +00002313 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002314 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002315 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002316 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2317 CarryGen, CarryGen,
2318 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2319 &ShufBytes[0], ShufBytes.size()));
2320
2321 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2322 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2323 Op0, Op1, ShiftedCarry));
2324 }
2325
2326 case ISD::SUB: {
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(0xc0c0c0c0, MVT::i32));
2339 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2340 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2341
Dan Gohman475871a2008-07-27 21:46:04 +00002342 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002343 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002344 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002345 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2346 BorrowGen, BorrowGen,
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::SUB_EXTENDED, MVT::v2i64,
2352 Op0, Op1, ShiftedBorrow));
2353 }
2354
Scott Michela59d4692008-02-23 18:41:37 +00002355 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002356 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002357 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002358 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2359 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002360 DAG.getNode(SPUISD::SELB, VecVT,
2361 Op0Vec,
2362 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002363 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002364 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002365 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002366 DAG.getNode(ISD::SRL, ShiftAmtVT,
2367 ShiftAmt,
2368 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002369 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002370 DAG.getNode(ISD::AND, ShiftAmtVT,
2371 ShiftAmt,
2372 DAG.getConstant(7, ShiftAmtVT));
2373
2374 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2375 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2376 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2377 MaskLower, ShiftAmtBytes),
2378 ShiftAmtBits));
2379 }
2380
2381 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002382 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002383 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002384 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002385 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002386 DAG.getNode(ISD::SRL, ShiftAmtVT,
2387 ShiftAmt,
2388 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002389 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002390 DAG.getNode(ISD::AND, ShiftAmtVT,
2391 ShiftAmt,
2392 DAG.getConstant(7, ShiftAmtVT));
2393
2394 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2395 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2396 Op0, ShiftAmtBytes),
2397 ShiftAmtBits);
2398 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002399
2400 case ISD::SRA: {
2401 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002402 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002403 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002404 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002405 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002406
2407 // Negate variable shift amounts
2408 if (!isa<ConstantSDNode>(ShiftAmt)) {
2409 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2410 DAG.getConstant(0, ShiftVT), ShiftAmt);
2411 }
2412
Dan Gohman475871a2008-07-27 21:46:04 +00002413 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002414 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2415 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2416 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2417 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002418 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002419 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002420 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002421 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2422 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002423 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002424 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2425 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002426 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002427 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2428 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002429 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002430 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2431 RotateLeftBytes, ShiftAmt);
2432
2433 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2434 RotateLeftBits);
2435 }
Scott Michela59d4692008-02-23 18:41:37 +00002436 }
2437
Dan Gohman475871a2008-07-27 21:46:04 +00002438 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002439}
2440
Scott Michel266bc8f2007-12-04 22:23:35 +00002441//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002442static SDValue
2443LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2444 SDValue ConstVec;
2445 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002446 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002447
2448 ConstVec = Op.getOperand(0);
2449 Arg = Op.getOperand(1);
2450 if (ConstVec.Val->getOpcode() != ISD::BUILD_VECTOR) {
2451 if (ConstVec.Val->getOpcode() == ISD::BIT_CONVERT) {
2452 ConstVec = ConstVec.getOperand(0);
2453 } else {
2454 ConstVec = Op.getOperand(1);
2455 Arg = Op.getOperand(0);
2456 if (ConstVec.Val->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002457 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002458 }
2459 }
2460 }
2461
2462 if (ConstVec.Val->getOpcode() == ISD::BUILD_VECTOR) {
2463 uint64_t VectorBits[2];
2464 uint64_t UndefBits[2];
2465 uint64_t SplatBits, SplatUndef;
2466 int SplatSize;
2467
2468 if (!GetConstantBuildVectorBits(ConstVec.Val, VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002469 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002470 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002471 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002472 SDValue tcVec[16];
2473 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002474 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2475
2476 // Turn the BUILD_VECTOR into a set of target constants:
2477 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002478 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002479
2480 return DAG.getNode(Op.Val->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002481 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002482 }
2483 }
2484
Dan Gohman475871a2008-07-27 21:46:04 +00002485 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002486}
2487
2488//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002489static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002490 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002491 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002492 default:
2493 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002494 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002495 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002496 abort();
2497 /*NOTREACHED*/
2498
2499 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002500 SDValue rA = Op.getOperand(0);
2501 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002502
2503 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002504 DAG.getNode(ISD::ADD, MVT::i32,
2505 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2506 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2507 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002508 }
2509 }
2510
Dan Gohman475871a2008-07-27 21:46:04 +00002511 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002512}
2513
2514//! Custom lowering for CTPOP (count population)
2515/*!
2516 Custom lowering code that counts the number ones in the input
2517 operand. SPU has such an instruction, but it counts the number of
2518 ones per byte, which then have to be accumulated.
2519*/
Dan Gohman475871a2008-07-27 21:46:04 +00002520static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002521 MVT VT = Op.getValueType();
2522 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002523
Duncan Sands83ec4b62008-06-06 12:08:01 +00002524 switch (VT.getSimpleVT()) {
2525 default:
2526 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002527 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002528 SDValue N = Op.getOperand(0);
2529 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002530
Dan Gohman475871a2008-07-27 21:46:04 +00002531 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2532 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002533
2534 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2535 }
2536
2537 case MVT::i16: {
2538 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002539 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002540
Chris Lattner84bc5422007-12-31 04:13:23 +00002541 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002542
Dan Gohman475871a2008-07-27 21:46:04 +00002543 SDValue N = Op.getOperand(0);
2544 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2545 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
2546 SDValue Shift1 = DAG.getConstant(8, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002547
Dan Gohman475871a2008-07-27 21:46:04 +00002548 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2549 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002550
2551 // CNTB_result becomes the chain to which all of the virtual registers
2552 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002553 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002554 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002555
Dan Gohman475871a2008-07-27 21:46:04 +00002556 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002557 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2558
Dan Gohman475871a2008-07-27 21:46:04 +00002559 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002560
2561 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002562 DAG.getNode(ISD::ADD, MVT::i16,
2563 DAG.getNode(ISD::SRL, MVT::i16,
2564 Tmp1, Shift1),
2565 Tmp1),
2566 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002567 }
2568
2569 case MVT::i32: {
2570 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002571 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002572
Chris Lattner84bc5422007-12-31 04:13:23 +00002573 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2574 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002575
Dan Gohman475871a2008-07-27 21:46:04 +00002576 SDValue N = Op.getOperand(0);
2577 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2578 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2579 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2580 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002581
Dan Gohman475871a2008-07-27 21:46:04 +00002582 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2583 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002584
2585 // CNTB_result becomes the chain to which all of the virtual registers
2586 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002587 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002588 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002589
Dan Gohman475871a2008-07-27 21:46:04 +00002590 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002591 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2592
Dan Gohman475871a2008-07-27 21:46:04 +00002593 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002594 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002595 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002596
Dan Gohman475871a2008-07-27 21:46:04 +00002597 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002598 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002599 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002600
Dan Gohman475871a2008-07-27 21:46:04 +00002601 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002602 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2603
Dan Gohman475871a2008-07-27 21:46:04 +00002604 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002605 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002606 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2607 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002608 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002609 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002610 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002611
2612 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2613 }
2614
2615 case MVT::i64:
2616 break;
2617 }
2618
Dan Gohman475871a2008-07-27 21:46:04 +00002619 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002620}
2621
2622/// LowerOperation - Provide custom lowering hooks for some operations.
2623///
Dan Gohman475871a2008-07-27 21:46:04 +00002624SDValue
2625SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002626{
Scott Michela59d4692008-02-23 18:41:37 +00002627 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002628 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002629
2630 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002631 default: {
2632 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002633 cerr << "Op.getOpcode() = " << Opc << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002634 cerr << "*Op.Val:\n";
2635 Op.Val->dump();
2636 abort();
2637 }
2638 case ISD::LOAD:
2639 case ISD::SEXTLOAD:
2640 case ISD::ZEXTLOAD:
2641 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2642 case ISD::STORE:
2643 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2644 case ISD::ConstantPool:
2645 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2646 case ISD::GlobalAddress:
2647 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2648 case ISD::JumpTable:
2649 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2650 case ISD::Constant:
2651 return LowerConstant(Op, DAG);
2652 case ISD::ConstantFP:
2653 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002654 case ISD::BRCOND:
2655 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002656 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002657 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002658 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002659 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002660 case ISD::RET:
2661 return LowerRET(Op, DAG, getTargetMachine());
2662
Scott Michela59d4692008-02-23 18:41:37 +00002663
2664 // i8, i64 math ops:
2665 case ISD::ZERO_EXTEND:
2666 case ISD::SIGN_EXTEND:
2667 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002668 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002669 case ISD::SUB:
2670 case ISD::ROTR:
2671 case ISD::ROTL:
2672 case ISD::SRL:
2673 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002674 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002675 if (VT == MVT::i8)
2676 return LowerI8Math(Op, DAG, Opc);
2677 else if (VT == MVT::i64)
2678 return LowerI64Math(Op, DAG, Opc);
2679 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002680 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002681
2682 // Vector-related lowering.
2683 case ISD::BUILD_VECTOR:
2684 return LowerBUILD_VECTOR(Op, DAG);
2685 case ISD::SCALAR_TO_VECTOR:
2686 return LowerSCALAR_TO_VECTOR(Op, DAG);
2687 case ISD::VECTOR_SHUFFLE:
2688 return LowerVECTOR_SHUFFLE(Op, DAG);
2689 case ISD::EXTRACT_VECTOR_ELT:
2690 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2691 case ISD::INSERT_VECTOR_ELT:
2692 return LowerINSERT_VECTOR_ELT(Op, DAG);
2693
2694 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2695 case ISD::AND:
2696 case ISD::OR:
2697 case ISD::XOR:
2698 return LowerByteImmed(Op, DAG);
2699
2700 // Vector and i8 multiply:
2701 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002702 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002703 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002704 else if (VT == MVT::i8)
2705 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002706 else
Scott Michela59d4692008-02-23 18:41:37 +00002707 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002708
2709 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002710 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002711 return LowerFDIVf32(Op, DAG);
2712// else if (Op.getValueType() == MVT::f64)
2713// return LowerFDIVf64(Op, DAG);
2714 else
2715 assert(0 && "Calling FDIV on unsupported MVT");
2716
2717 case ISD::CTPOP:
2718 return LowerCTPOP(Op, DAG);
2719 }
2720
Dan Gohman475871a2008-07-27 21:46:04 +00002721 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002722}
2723
2724//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002725// Target Optimization Hooks
2726//===----------------------------------------------------------------------===//
2727
Dan Gohman475871a2008-07-27 21:46:04 +00002728SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002729SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2730{
2731#if 0
2732 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002733#endif
2734 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002735 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002736 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2737 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002738
2739 switch (N->getOpcode()) {
2740 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002741 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002742 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002743
Scott Michel8bf61e82008-06-02 22:18:03 +00002744 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002745 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002746 if (Op01.getOpcode() == ISD::Constant
2747 || Op01.getOpcode() == ISD::TargetConstant) {
2748 // (add <const>, (SPUindirect <arg>, <const>)) ->
2749 // (SPUindirect <arg>, <const + const>)
2750 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2751 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002752 SDValue combinedConst =
Scott Michel053c1da2008-01-29 02:16:57 +00002753 DAG.getConstant(CN0->getValue() + CN1->getValue(),
2754 Op0.getValueType());
2755
2756 DEBUG(cerr << "Replace: (add " << CN0->getValue() << ", "
2757 << "(SPUindirect <arg>, " << CN1->getValue() << "))\n");
2758 DEBUG(cerr << "With: (SPUindirect <arg>, "
2759 << CN0->getValue() + CN1->getValue() << ")\n");
2760 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2761 Op0.getOperand(0), combinedConst);
2762 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002763 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002764 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002765 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002766 if (Op11.getOpcode() == ISD::Constant
2767 || Op11.getOpcode() == ISD::TargetConstant) {
2768 // (add (SPUindirect <arg>, <const>), <const>) ->
2769 // (SPUindirect <arg>, <const + const>)
2770 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2771 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002772 SDValue combinedConst =
Scott Michel053c1da2008-01-29 02:16:57 +00002773 DAG.getConstant(CN0->getValue() + CN1->getValue(),
2774 Op0.getValueType());
2775
2776 DEBUG(cerr << "Replace: (add " << CN0->getValue() << ", "
2777 << "(SPUindirect <arg>, " << CN1->getValue() << "))\n");
2778 DEBUG(cerr << "With: (SPUindirect <arg>, "
2779 << CN0->getValue() + CN1->getValue() << ")\n");
2780
2781 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2782 Op1.getOperand(0), combinedConst);
2783 }
2784 }
Scott Michela59d4692008-02-23 18:41:37 +00002785 break;
2786 }
2787 case ISD::SIGN_EXTEND:
2788 case ISD::ZERO_EXTEND:
2789 case ISD::ANY_EXTEND: {
2790 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2791 N->getValueType(0) == Op0.getValueType()) {
2792 // (any_extend (SPUextract_elt0 <arg>)) ->
2793 // (SPUextract_elt0 <arg>)
2794 // Types must match, however...
2795 DEBUG(cerr << "Replace: ");
2796 DEBUG(N->dump(&DAG));
2797 DEBUG(cerr << "\nWith: ");
2798 DEBUG(Op0.Val->dump(&DAG));
2799 DEBUG(cerr << "\n");
2800
2801 return Op0;
2802 }
2803 break;
2804 }
2805 case SPUISD::IndirectAddr: {
2806 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2807 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
2808 if (CN->getValue() == 0) {
2809 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2810 // (SPUaform <addr>, 0)
2811
2812 DEBUG(cerr << "Replace: ");
2813 DEBUG(N->dump(&DAG));
2814 DEBUG(cerr << "\nWith: ");
2815 DEBUG(Op0.Val->dump(&DAG));
2816 DEBUG(cerr << "\n");
2817
2818 return Op0;
2819 }
2820 }
2821 break;
2822 }
2823 case SPUISD::SHLQUAD_L_BITS:
2824 case SPUISD::SHLQUAD_L_BYTES:
2825 case SPUISD::VEC_SHL:
2826 case SPUISD::VEC_SRL:
2827 case SPUISD::VEC_SRA:
2828 case SPUISD::ROTQUAD_RZ_BYTES:
2829 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002830 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002831
2832 if (isa<ConstantSDNode>(Op1)) {
2833 // Kill degenerate vector shifts:
2834 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2835
2836 if (CN->getValue() == 0) {
2837 Result = Op0;
2838 }
2839 }
2840 break;
2841 }
2842 case SPUISD::PROMOTE_SCALAR: {
2843 switch (Op0.getOpcode()) {
2844 default:
2845 break;
2846 case ISD::ANY_EXTEND:
2847 case ISD::ZERO_EXTEND:
2848 case ISD::SIGN_EXTEND: {
2849 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2850 // <arg>
2851 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002852 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002853 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00002854 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002855 if (Op000.getValueType() == N->getValueType(0)) {
2856 Result = Op000;
2857 }
2858 }
2859 break;
2860 }
2861 case SPUISD::EXTRACT_ELT0: {
2862 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2863 // <arg>
2864 Result = Op0.getOperand(0);
2865 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002866 }
Scott Michela59d4692008-02-23 18:41:37 +00002867 }
2868 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002869 }
2870 }
Scott Michel58c58182008-01-17 20:38:41 +00002871 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002872#if 1
Scott Michela59d4692008-02-23 18:41:37 +00002873 if (Result.Val) {
2874 DEBUG(cerr << "\nReplace.SPU: ");
2875 DEBUG(N->dump(&DAG));
2876 DEBUG(cerr << "\nWith: ");
2877 DEBUG(Result.Val->dump(&DAG));
2878 DEBUG(cerr << "\n");
2879 }
2880#endif
2881
2882 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002883}
2884
2885//===----------------------------------------------------------------------===//
2886// Inline Assembly Support
2887//===----------------------------------------------------------------------===//
2888
2889/// getConstraintType - Given a constraint letter, return the type of
2890/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002891SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002892SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2893 if (ConstraintLetter.size() == 1) {
2894 switch (ConstraintLetter[0]) {
2895 default: break;
2896 case 'b':
2897 case 'r':
2898 case 'f':
2899 case 'v':
2900 case 'y':
2901 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002902 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002903 }
2904 return TargetLowering::getConstraintType(ConstraintLetter);
2905}
2906
Scott Michel5af8f0e2008-07-16 17:17:29 +00002907std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002908SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002909 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002910{
2911 if (Constraint.size() == 1) {
2912 // GCC RS6000 Constraint Letters
2913 switch (Constraint[0]) {
2914 case 'b': // R1-R31
2915 case 'r': // R0-R31
2916 if (VT == MVT::i64)
2917 return std::make_pair(0U, SPU::R64CRegisterClass);
2918 return std::make_pair(0U, SPU::R32CRegisterClass);
2919 case 'f':
2920 if (VT == MVT::f32)
2921 return std::make_pair(0U, SPU::R32FPRegisterClass);
2922 else if (VT == MVT::f64)
2923 return std::make_pair(0U, SPU::R64FPRegisterClass);
2924 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002925 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002926 return std::make_pair(0U, SPU::GPRCRegisterClass);
2927 }
2928 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002929
Scott Michel266bc8f2007-12-04 22:23:35 +00002930 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2931}
2932
Scott Michela59d4692008-02-23 18:41:37 +00002933//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002934void
Dan Gohman475871a2008-07-27 21:46:04 +00002935SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002936 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002937 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002938 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002939 const SelectionDAG &DAG,
2940 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002941#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002942 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002943#endif
Scott Michela59d4692008-02-23 18:41:37 +00002944
2945 switch (Op.getOpcode()) {
2946 default:
2947 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2948 break;
2949
2950#if 0
2951 case CALL:
2952 case SHUFB:
2953 case INSERT_MASK:
2954 case CNTB:
2955#endif
2956
2957 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00002958 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002959 MVT Op0VT = Op0.getValueType();
2960 unsigned Op0VTBits = Op0VT.getSizeInBits();
2961 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002962 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2963 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002964 break;
2965 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002966
Scott Michela59d4692008-02-23 18:41:37 +00002967 case SPUISD::LDRESULT:
2968 case SPUISD::EXTRACT_ELT0:
2969 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002970 MVT OpVT = Op.getValueType();
2971 unsigned OpVTBits = OpVT.getSizeInBits();
2972 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002973 KnownZero |= APInt(OpVTBits, ~InMask, false);
2974 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002975 break;
2976 }
2977
2978#if 0
2979 case EXTRACT_I1_ZEXT:
2980 case EXTRACT_I1_SEXT:
2981 case EXTRACT_I8_ZEXT:
2982 case EXTRACT_I8_SEXT:
2983 case MPY:
2984 case MPYU:
2985 case MPYH:
2986 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00002987 case SPUISD::SHLQUAD_L_BITS:
2988 case SPUISD::SHLQUAD_L_BYTES:
2989 case SPUISD::VEC_SHL:
2990 case SPUISD::VEC_SRL:
2991 case SPUISD::VEC_SRA:
2992 case SPUISD::VEC_ROTL:
2993 case SPUISD::VEC_ROTR:
2994 case SPUISD::ROTQUAD_RZ_BYTES:
2995 case SPUISD::ROTQUAD_RZ_BITS:
2996 case SPUISD::ROTBYTES_RIGHT_S:
2997 case SPUISD::ROTBYTES_LEFT:
2998 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00002999 case SPUISD::SELECT_MASK:
3000 case SPUISD::SELB:
3001 case SPUISD::FPInterp:
3002 case SPUISD::FPRecipEst:
3003 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003004#endif
3005 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003006}
3007
Scott Michel203b2d62008-04-30 00:30:08 +00003008// LowerAsmOperandForConstraint
3009void
Dan Gohman475871a2008-07-27 21:46:04 +00003010SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003011 char ConstraintLetter,
Dan Gohman475871a2008-07-27 21:46:04 +00003012 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003013 SelectionDAG &DAG) const {
3014 // Default, for the time being, to the base class handler
3015 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, Ops, DAG);
3016}
3017
Scott Michel266bc8f2007-12-04 22:23:35 +00003018/// isLegalAddressImmediate - Return true if the integer value can be used
3019/// as the offset of the target addressing mode.
3020bool SPUTargetLowering::isLegalAddressImmediate(int64_t V, const Type *Ty) const {
3021 // SPU's addresses are 256K:
3022 return (V > -(1 << 18) && V < (1 << 18) - 1);
3023}
3024
3025bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003026 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003027}