blob: 184f0b23fa54bfd009401b0fe595ef8b143335f4 [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 {
Scott Michel7a1c9e92008-11-22 23:50:42 +000042 const MVT valtype;
43 const int prefslot_byte;
Scott Michel266bc8f2007-12-04 22:23:35 +000044 };
Scott Michel5af8f0e2008-07-16 17:17:29 +000045
Scott Michel266bc8f2007-12-04 22:23:35 +000046 const valtype_map_s valtype_map[] = {
47 { MVT::i1, 3 },
48 { MVT::i8, 3 },
49 { MVT::i16, 2 },
50 { MVT::i32, 0 },
51 { MVT::f32, 0 },
52 { MVT::i64, 0 },
53 { MVT::f64, 0 },
54 { MVT::i128, 0 }
55 };
56
57 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
58
Duncan Sands83ec4b62008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel266bc8f2007-12-04 22:23:35 +000060 const valtype_map_s *retval = 0;
61
62 for (size_t i = 0; i < n_valtype_map; ++i) {
63 if (valtype_map[i].valtype == VT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel266bc8f2007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands83ec4b62008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +000074 abort();
75 }
76#endif
77
78 return retval;
79 }
80
81 //! Predicate that returns true if operand is a memory target
82 /*!
83 \arg Op Operand to test
84 \return true if the operand is a memory target (i.e., global
Scott Michel9de5d0d2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel266bc8f2007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman475871a2008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel266bc8f2007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
Bill Wendling056292f2008-09-16 21:48:12 +000095 || Opc == ISD::ExternalSymbol
Scott Michel266bc8f2007-12-04 22:23:35 +000096 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
Bill Wendling056292f2008-09-16 21:48:12 +0000100 || Opc == ISD::TargetExternalSymbol
Scott Michel9de5d0d2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000102 }
Scott Michel58c58182008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman475871a2008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel58c58182008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel58c58182008-01-17 20:38:41 +0000110 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000111}
112
113SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
114 : TargetLowering(TM),
115 SPUTM(TM)
116{
117 // Fold away setcc operations if possible.
118 setPow2DivIsCheap();
119
120 // Use _setjmp/_longjmp instead of setjmp/longjmp.
121 setUseUnderscoreSetJmp(true);
122 setUseUnderscoreLongJmp(true);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000123
Scott Michel266bc8f2007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel504c3692007-12-17 22:32:34 +0000125 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
126 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
127 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
128 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
129 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
130 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel266bc8f2007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000132
Scott Micheldc91bea2008-11-20 16:36:33 +0000133 // Initialize libcalls:
134 setLibcallName(RTLIB::MUL_I64, "__muldi3");
135
Scott Michel266bc8f2007-12-04 22:23:35 +0000136 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng03294662008-10-14 21:26:46 +0000137 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
138 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
139 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +0000140
Evan Cheng03294662008-10-14 21:26:46 +0000141 setLoadExtAction(ISD::EXTLOAD, MVT::i8, Custom);
142 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Custom);
143 setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Scott Michela0e57692008-11-20 04:26:21 +0000144 setTruncStoreAction(MVT::i8, MVT::i8, Custom);
145 setTruncStoreAction(MVT::i16, MVT::i8, Custom);
146 setTruncStoreAction(MVT::i32, MVT::i8, Custom);
147 setTruncStoreAction(MVT::i64, MVT::i8, Custom);
148 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000149
Evan Cheng03294662008-10-14 21:26:46 +0000150 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Custom);
151 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Custom);
152 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000153
154 // SPU constant load actions are custom lowered:
155 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begemanccef5802008-02-14 18:43:04 +0000156 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000157 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
158
159 // SPU's loads and stores have to be custom lowered:
Scott Michel719b0e12008-11-19 17:45:08 +0000160 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel266bc8f2007-12-04 22:23:35 +0000161 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000162 MVT VT = (MVT::SimpleValueType)sctype;
163
164 setOperationAction(ISD::LOAD, VT, Custom);
165 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000166 }
167
Scott Michel9c0c6b22008-11-21 02:56:16 +0000168 // Custom lower BRCOND for i8 to "promote" the result to i16
Scott Michel58c58182008-01-17 20:38:41 +0000169 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000170
171 // Expand the jumptable branches
172 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
173 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel7a1c9e92008-11-22 23:50:42 +0000174
175 // Custom lower SELECT_CC for most cases, but expand by default
Scott Michel5af8f0e2008-07-16 17:17:29 +0000176 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel7a1c9e92008-11-22 23:50:42 +0000177 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
178 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
179 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
Scott Michel662165d2008-11-25 00:23:16 +0000180#if 0
Scott Michel7a1c9e92008-11-22 23:50:42 +0000181 setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
Scott Michel662165d2008-11-25 00:23:16 +0000182#endif
Scott Michel266bc8f2007-12-04 22:23:35 +0000183
184 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000185 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
186
Scott Michel266bc8f2007-12-04 22:23:35 +0000187 // PowerPC has no SREM/UREM instructions
188 setOperationAction(ISD::SREM, MVT::i32, Expand);
189 setOperationAction(ISD::UREM, MVT::i32, Expand);
190 setOperationAction(ISD::SREM, MVT::i64, Expand);
191 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000192
Scott Michel266bc8f2007-12-04 22:23:35 +0000193 // We don't support sin/cos/sqrt/fmod
194 setOperationAction(ISD::FSIN , MVT::f64, Expand);
195 setOperationAction(ISD::FCOS , MVT::f64, Expand);
196 setOperationAction(ISD::FREM , MVT::f64, Expand);
197 setOperationAction(ISD::FSIN , MVT::f32, Expand);
198 setOperationAction(ISD::FCOS , MVT::f32, Expand);
199 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000200
Scott Michel266bc8f2007-12-04 22:23:35 +0000201 // If we're enabling GP optimizations, use hardware square root
202 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
203 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000204
Scott Michel266bc8f2007-12-04 22:23:35 +0000205 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
206 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
207
208 // SPU can do rotate right and left, so legalize it... but customize for i8
209 // because instructions don't exist.
Bill Wendling9440e352008-08-31 02:59:23 +0000210
211 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
212 // .td files.
213 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
214 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
215 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
216
Scott Michel266bc8f2007-12-04 22:23:35 +0000217 setOperationAction(ISD::ROTL, MVT::i32, Legal);
218 setOperationAction(ISD::ROTL, MVT::i16, Legal);
219 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Micheldc91bea2008-11-20 16:36:33 +0000220
Scott Michel266bc8f2007-12-04 22:23:35 +0000221 // SPU has no native version of shift left/right for i8
222 setOperationAction(ISD::SHL, MVT::i8, Custom);
223 setOperationAction(ISD::SRL, MVT::i8, Custom);
224 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel9c0c6b22008-11-21 02:56:16 +0000225
226 // SPU needs custom lowering for shift left/right for i64
Scott Michela59d4692008-02-23 18:41:37 +0000227 setOperationAction(ISD::SHL, MVT::i64, Custom);
228 setOperationAction(ISD::SRL, MVT::i64, Custom);
229 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000230
Scott Michel5af8f0e2008-07-16 17:17:29 +0000231 // Custom lower i8, i32 and i64 multiplications
232 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000233 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel9c0c6b22008-11-21 02:56:16 +0000234 setOperationAction(ISD::MUL, MVT::i64, Expand); // libcall
235
236 // SMUL_LOHI, UMUL_LOHI
237 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
238 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
239 setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom);
240 setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000241
Scott Michel8bf61e82008-06-02 22:18:03 +0000242 // Need to custom handle (some) common i8, i64 math ops
243 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000244 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel8bf61e82008-06-02 22:18:03 +0000245 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000246
Scott Michel266bc8f2007-12-04 22:23:35 +0000247 // SPU does not have BSWAP. It does have i32 support CTLZ.
248 // CTPOP has to be custom lowered.
249 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
250 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
251
252 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
253 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
254 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
255 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
256
257 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
258 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
259
260 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000261
Scott Michel8bf61e82008-06-02 22:18:03 +0000262 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000263 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000264 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000265 setOperationAction(ISD::SELECT, MVT::i16, Legal);
266 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000267 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000268
Scott Michel78c47fa2008-03-10 16:58:52 +0000269 setOperationAction(ISD::SETCC, MVT::i8, Legal);
270 setOperationAction(ISD::SETCC, MVT::i16, Legal);
271 setOperationAction(ISD::SETCC, MVT::i32, Legal);
272 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michelad2715e2008-03-05 23:02:02 +0000273
Scott Michela59d4692008-02-23 18:41:37 +0000274 // Zero extension and sign extension for i64 have to be
275 // custom legalized
276 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
277 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
278 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000279
Scott Michel266bc8f2007-12-04 22:23:35 +0000280 // SPU has a legal FP -> signed INT instruction
281 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
282 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
283 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
284 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
285
286 // FDIV on SPU requires custom lowering
287 setOperationAction(ISD::FDIV, MVT::f32, Custom);
288 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
289
290 // SPU has [U|S]INT_TO_FP
291 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
292 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
293 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
294 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
295 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
296 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
297 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
298 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
299
Scott Michel86c041f2007-12-20 00:44:13 +0000300 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
301 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
302 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
303 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000304
305 // We cannot sextinreg(i1). Expand to shifts.
306 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000307
Scott Michel266bc8f2007-12-04 22:23:35 +0000308 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000309 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000310 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000311
312 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000313 // appropriate instructions to materialize the address.
Scott Michel9c0c6b22008-11-21 02:56:16 +0000314 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel053c1da2008-01-29 02:16:57 +0000315 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000316 MVT VT = (MVT::SimpleValueType)sctype;
317
318 setOperationAction(ISD::GlobalAddress, VT, Custom);
319 setOperationAction(ISD::ConstantPool, VT, Custom);
320 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000321 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000322
323 // RET must be custom lowered, to meet ABI requirements
324 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000325
Scott Michel266bc8f2007-12-04 22:23:35 +0000326 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
327 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000328
Scott Michel266bc8f2007-12-04 22:23:35 +0000329 // Use the default implementation.
330 setOperationAction(ISD::VAARG , MVT::Other, Expand);
331 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
332 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000333 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000334 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
335 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
336 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
337
338 // Cell SPU has instructions for converting between i64 and fp.
339 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
340 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000341
Scott Michel266bc8f2007-12-04 22:23:35 +0000342 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
343 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
344
345 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
346 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
347
348 // First set operation action for all vector types to expand. Then we
349 // will selectively turn on ones that can be effectively codegen'd.
350 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
351 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
352 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
353 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
354 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
355 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
356
Duncan Sands83ec4b62008-06-06 12:08:01 +0000357 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
358 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
359 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000360
Duncan Sands83ec4b62008-06-06 12:08:01 +0000361 // add/sub are legal for all supported vector VT's.
362 setOperationAction(ISD::ADD , VT, Legal);
363 setOperationAction(ISD::SUB , VT, Legal);
364 // mul has to be custom lowered.
365 setOperationAction(ISD::MUL , VT, Custom);
366
367 setOperationAction(ISD::AND , VT, Legal);
368 setOperationAction(ISD::OR , VT, Legal);
369 setOperationAction(ISD::XOR , VT, Legal);
370 setOperationAction(ISD::LOAD , VT, Legal);
371 setOperationAction(ISD::SELECT, VT, Legal);
372 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000373
Scott Michel266bc8f2007-12-04 22:23:35 +0000374 // These operations need to be expanded:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000375 setOperationAction(ISD::SDIV, VT, Expand);
376 setOperationAction(ISD::SREM, VT, Expand);
377 setOperationAction(ISD::UDIV, VT, Expand);
378 setOperationAction(ISD::UREM, VT, Expand);
379 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000380
381 // Custom lower build_vector, constant pool spills, insert and
382 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000383 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
384 setOperationAction(ISD::ConstantPool, VT, Custom);
385 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
386 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
387 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
388 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000389 }
390
391 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
392 setOperationAction(ISD::AND, MVT::v16i8, Custom);
393 setOperationAction(ISD::OR, MVT::v16i8, Custom);
394 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
395 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000396
Scott Michel266bc8f2007-12-04 22:23:35 +0000397 setShiftAmountType(MVT::i32);
Duncan Sands03228082008-11-23 15:47:28 +0000398 setBooleanContents(ZeroOrOneBooleanContent);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000399
Scott Michel266bc8f2007-12-04 22:23:35 +0000400 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000401
Scott Michel266bc8f2007-12-04 22:23:35 +0000402 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000403 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000404 setTargetDAGCombine(ISD::ZERO_EXTEND);
405 setTargetDAGCombine(ISD::SIGN_EXTEND);
406 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000407
Scott Michel266bc8f2007-12-04 22:23:35 +0000408 computeRegisterProperties();
Scott Michel7a1c9e92008-11-22 23:50:42 +0000409
410 // Set other properties:
411 setSchedulingPreference(SchedulingForLatency);
Scott Michel266bc8f2007-12-04 22:23:35 +0000412}
413
414const char *
415SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
416{
417 if (node_names.empty()) {
418 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
419 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
420 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
421 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000422 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000423 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000424 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
425 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
426 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel7a1c9e92008-11-22 23:50:42 +0000427 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000428 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
429 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
Scott Michel104de432008-11-24 17:11:17 +0000430 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
431 node_names[(unsigned) SPUISD::VEC2PREFSLOT_CHAINED]
432 = "SPUISD::VEC2PREFSLOT_CHAINED";
Scott Michel266bc8f2007-12-04 22:23:35 +0000433 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
434 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
435 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
436 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
437 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
438 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
439 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
440 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michela59d4692008-02-23 18:41:37 +0000441 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
442 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000443 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
444 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
445 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
446 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
447 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michela59d4692008-02-23 18:41:37 +0000448 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
449 "SPUISD::ROTQUAD_RZ_BYTES";
450 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
451 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel266bc8f2007-12-04 22:23:35 +0000452 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
453 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
454 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel8bf61e82008-06-02 22:18:03 +0000455 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
456 "SPUISD::ROTBYTES_LEFT_BITS";
457 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000458 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000459 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
460 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
461 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
462 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000463 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
464 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
465 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
466 }
467
468 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
469
470 return ((i != node_names.end()) ? i->second : 0);
471}
472
Dan Gohman475871a2008-07-27 21:46:04 +0000473MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000474 MVT VT = Op.getValueType();
Scott Micheld976c212008-10-30 01:51:48 +0000475 return (VT.isInteger() ? VT : MVT(MVT::i32));
Scott Michel78c47fa2008-03-10 16:58:52 +0000476}
477
Scott Michel266bc8f2007-12-04 22:23:35 +0000478//===----------------------------------------------------------------------===//
479// Calling convention code:
480//===----------------------------------------------------------------------===//
481
482#include "SPUGenCallingConv.inc"
483
484//===----------------------------------------------------------------------===//
485// LowerOperation implementation
486//===----------------------------------------------------------------------===//
487
Scott Michel9de5d0d2008-01-11 02:53:15 +0000488/// Aligned load common code for CellSPU
489/*!
490 \param[in] Op The SelectionDAG load or store operand
491 \param[in] DAG The selection DAG
492 \param[in] ST CellSPU subtarget information structure
493 \param[in,out] alignment Caller initializes this to the load or store node's
494 value from getAlignment(), may be updated while generating the aligned load
495 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
496 offset (divisible by 16, modulo 16 == 0)
497 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
498 offset of the preferred slot (modulo 16 != 0)
499 \param[in,out] VT Caller initializes this value type to the the load or store
500 node's loaded or stored value type; may be updated if an i1-extended load or
501 store.
502 \param[out] was16aligned true if the base pointer had 16-byte alignment,
503 otherwise false. Can help to determine if the chunk needs to be rotated.
504
505 Both load and store lowering load a block of data aligned on a 16-byte
506 boundary. This is the common aligned load code shared between both.
507 */
Dan Gohman475871a2008-07-27 21:46:04 +0000508static SDValue
509AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Michel9de5d0d2008-01-11 02:53:15 +0000510 LSBaseSDNode *LSN,
511 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000512 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000513{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000514 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000515 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman475871a2008-07-27 21:46:04 +0000516 SDValue basePtr = LSN->getBasePtr();
517 SDValue chain = LSN->getChain();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000518
519 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000520 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000521
Gabor Greif93c53e52008-08-31 15:37:04 +0000522 if (Op1.getOpcode() == ISD::Constant
523 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000524 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000525
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000526 alignOffs = (int) CN->getZExtValue();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000527 prefSlotOffs = (int) (alignOffs & 0xf);
528
529 // Adjust the rotation amount to ensure that the final result ends up in
530 // the preferred slot:
531 prefSlotOffs -= vtm->prefslot_byte;
532 basePtr = basePtr.getOperand(0);
533
Scott Michel58c58182008-01-17 20:38:41 +0000534 // Loading from memory, can we adjust alignment?
535 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +0000536 SDValue APtr = basePtr.getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000537 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
538 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
539 alignment = GSDN->getGlobal()->getAlignment();
540 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000541 }
542 } else {
543 alignOffs = 0;
544 prefSlotOffs = -vtm->prefslot_byte;
545 }
Scott Michel203b2d62008-04-30 00:30:08 +0000546 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
547 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
548 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
549 prefSlotOffs = (int) (alignOffs & 0xf);
550 prefSlotOffs -= vtm->prefslot_byte;
551 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000552 } else {
553 alignOffs = 0;
554 prefSlotOffs = -vtm->prefslot_byte;
555 }
556
557 if (alignment == 16) {
558 // Realign the base pointer as a D-Form address:
559 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000560 basePtr = DAG.getNode(ISD::ADD, PtrVT,
561 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000562 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000563 }
564
565 // Emit the vector load:
566 was16aligned = true;
567 return DAG.getLoad(MVT::v16i8, chain, basePtr,
568 LSN->getSrcValue(), LSN->getSrcValueOffset(),
569 LSN->isVolatile(), 16);
570 }
571
572 // Unaligned load or we're using the "large memory" model, which means that
573 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000574 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greif93c53e52008-08-31 15:37:04 +0000575 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
576 DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000577 }
578
579 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000580 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000581 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000582 was16aligned = false;
583 return DAG.getLoad(MVT::v16i8, chain, basePtr,
584 LSN->getSrcValue(), LSN->getSrcValueOffset(),
585 LSN->isVolatile(), 16);
586}
587
Scott Michel266bc8f2007-12-04 22:23:35 +0000588/// Custom lower loads for CellSPU
589/*!
590 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
591 within a 16-byte block, we have to rotate to extract the requested element.
592 */
Dan Gohman475871a2008-07-27 21:46:04 +0000593static SDValue
594LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000595 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000596 SDValue the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000597 MVT VT = LN->getMemoryVT();
Gabor Greifba36cb52008-08-28 21:40:38 +0000598 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000599 ISD::LoadExtType ExtType = LN->getExtensionType();
600 unsigned alignment = LN->getAlignment();
Dan Gohman475871a2008-07-27 21:46:04 +0000601 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000602
Scott Michel266bc8f2007-12-04 22:23:35 +0000603 switch (LN->getAddressingMode()) {
604 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000605 int offset, rotamt;
606 bool was16aligned;
Dan Gohman475871a2008-07-27 21:46:04 +0000607 SDValue result =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000608 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000609
Gabor Greifba36cb52008-08-28 21:40:38 +0000610 if (result.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000611 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000612
613 the_chain = result.getValue(1);
614 // Rotate the chunk if necessary
615 if (rotamt < 0)
616 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000617 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000618 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
619
Scott Michel58c58182008-01-17 20:38:41 +0000620 Ops[0] = the_chain;
621 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000622 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000623 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
624 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000625 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000626 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000627 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000628 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000629 }
630
631 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
632 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000633 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000634
635 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
636 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000637 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000638
Scott Michel9de5d0d2008-01-11 02:53:15 +0000639 // Convert the loaded v16i8 vector to the appropriate vector type
640 // specified by the operand:
641 if (OpVT == VT) {
642 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000643 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000644 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000645 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000646
647 Ops[0] = the_chain;
648 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
649 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
Scott Michel104de432008-11-24 17:11:17 +0000650 result = DAG.getNode(SPUISD::VEC2PREFSLOT_CHAINED, scalarvts, Ops, 2);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000651 the_chain = result.getValue(1);
652 } else {
653 // Handle the sign and zero-extending loads for i1 and i8:
654 unsigned NewOpC;
655
656 if (ExtType == ISD::SEXTLOAD) {
657 NewOpC = (OpVT == MVT::i1
658 ? SPUISD::EXTRACT_I1_SEXT
659 : SPUISD::EXTRACT_I8_SEXT);
660 } else {
661 assert(ExtType == ISD::ZEXTLOAD);
662 NewOpC = (OpVT == MVT::i1
663 ? SPUISD::EXTRACT_I1_ZEXT
664 : SPUISD::EXTRACT_I8_ZEXT);
665 }
666
667 result = DAG.getNode(NewOpC, OpVT, result);
668 }
669
670 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000671 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000672 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000673 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000674 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000675
Scott Michel58c58182008-01-17 20:38:41 +0000676 result = DAG.getNode(SPUISD::LDRESULT, retvts,
677 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000678 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000679 }
680 case ISD::PRE_INC:
681 case ISD::PRE_DEC:
682 case ISD::POST_INC:
683 case ISD::POST_DEC:
684 case ISD::LAST_INDEXED_MODE:
685 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
686 "UNINDEXED\n";
687 cerr << (unsigned) LN->getAddressingMode() << "\n";
688 abort();
689 /*NOTREACHED*/
690 }
691
Dan Gohman475871a2008-07-27 21:46:04 +0000692 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000693}
694
695/// Custom lower stores for CellSPU
696/*!
697 All CellSPU stores are aligned to 16-byte boundaries, so for elements
698 within a 16-byte block, we have to generate a shuffle to insert the
699 requested element into its place, then store the resulting block.
700 */
Dan Gohman475871a2008-07-27 21:46:04 +0000701static SDValue
702LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000703 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000704 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000705 MVT VT = Value.getValueType();
706 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
707 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000708 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000709
710 switch (SN->getAddressingMode()) {
711 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000712 int chunk_offset, slot_offset;
713 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000714
Scott Michel9c0c6b22008-11-21 02:56:16 +0000715 // The vector type we really want to load from the 16-byte chunk.
Scott Michel719b0e12008-11-19 17:45:08 +0000716 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
717 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000718
Dan Gohman475871a2008-07-27 21:46:04 +0000719 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000720 AlignedLoad(Op, DAG, ST, SN, alignment,
721 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000722
Gabor Greifba36cb52008-08-28 21:40:38 +0000723 if (alignLoadVec.getNode() == 0)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000724 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000725
Scott Michel9de5d0d2008-01-11 02:53:15 +0000726 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000727 SDValue basePtr = LN->getBasePtr();
728 SDValue the_chain = alignLoadVec.getValue(1);
729 SDValue theValue = SN->getValue();
730 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000731
732 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000733 && (theValue.getOpcode() == ISD::AssertZext
734 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000735 // Drill down and get the value for zero- and sign-extended
736 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000737 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000738 }
739
Scott Michel9de5d0d2008-01-11 02:53:15 +0000740 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000741
Dan Gohman475871a2008-07-27 21:46:04 +0000742 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
743 SDValue insertEltPtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000744
745 // If the base pointer is already a D-form address, then just create
746 // a new D-form address with a slot offset and the orignal base pointer.
747 // Otherwise generate a D-form address with the slot offset relative
748 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000749 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greifba36cb52008-08-28 21:40:38 +0000750 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michel497e8882008-01-11 21:01:19 +0000751 DEBUG(cerr << "\n");
752
Scott Michel053c1da2008-01-29 02:16:57 +0000753 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
754 (basePtr.getOpcode() == ISD::ADD
755 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000756 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000757 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000758 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000759 }
760
Scott Michel430a5552008-11-19 15:24:16 +0000761 SDValue insertEltOp =
Scott Michel7a1c9e92008-11-22 23:50:42 +0000762 DAG.getNode(SPUISD::SHUFFLE_MASK, stVecVT, insertEltPtr);
Scott Michel719b0e12008-11-19 17:45:08 +0000763 SDValue vectorizeOp =
764 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michel430a5552008-11-19 15:24:16 +0000765
766 result = DAG.getNode(SPUISD::SHUFB, vecVT, vectorizeOp, alignLoadVec,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000767 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000768
Scott Michel9de5d0d2008-01-11 02:53:15 +0000769 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000770 LN->getSrcValue(), LN->getSrcValueOffset(),
771 LN->isVolatile(), LN->getAlignment());
772
Scott Michel719b0e12008-11-19 17:45:08 +0000773#if 0 && defined(NDEBUG)
Scott Michel430a5552008-11-19 15:24:16 +0000774 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
775 const SDValue &currentRoot = DAG.getRoot();
776
777 DAG.setRoot(result);
778 cerr << "------- CellSPU:LowerStore result:\n";
779 DAG.dump();
780 cerr << "-------\n";
781 DAG.setRoot(currentRoot);
782 }
783#endif
784
Scott Michel266bc8f2007-12-04 22:23:35 +0000785 return result;
786 /*UNREACHED*/
787 }
788 case ISD::PRE_INC:
789 case ISD::PRE_DEC:
790 case ISD::POST_INC:
791 case ISD::POST_DEC:
792 case ISD::LAST_INDEXED_MODE:
793 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
794 "UNINDEXED\n";
795 cerr << (unsigned) SN->getAddressingMode() << "\n";
796 abort();
797 /*NOTREACHED*/
798 }
799
Dan Gohman475871a2008-07-27 21:46:04 +0000800 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000801}
802
803/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000804static SDValue
805LowerConstantPool(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 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
808 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000809 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
810 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000811 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000812
813 if (TM.getRelocationModel() == Reloc::Static) {
814 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000815 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000816 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000817 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000818 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
819 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000820 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000821 }
822 }
823
824 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000825 "LowerConstantPool: Relocation model other than static"
826 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000827 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000828}
829
Dan Gohman475871a2008-07-27 21:46:04 +0000830static SDValue
831LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000832 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000833 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000834 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
835 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000836 const TargetMachine &TM = DAG.getTarget();
837
838 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000839 if (!ST->usingLargeMem()) {
840 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
841 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000842 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
843 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000844 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
845 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000846 }
847
848 assert(0 &&
849 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000850 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000851}
852
Dan Gohman475871a2008-07-27 21:46:04 +0000853static SDValue
854LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000855 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000856 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
857 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000858 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000859 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000860 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000861
Scott Michel266bc8f2007-12-04 22:23:35 +0000862 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000863 if (!ST->usingLargeMem()) {
864 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
865 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000866 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
867 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000868 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
869 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000870 } else {
871 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000872 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000873 abort();
874 /*NOTREACHED*/
875 }
876
Dan Gohman475871a2008-07-27 21:46:04 +0000877 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000878}
879
880//! Custom lower i64 integer constants
881/*!
882 This code inserts all of the necessary juggling that needs to occur to load
883 a 64-bit constant into a register.
884 */
Dan Gohman475871a2008-07-27 21:46:04 +0000885static SDValue
886LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000887 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000888 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000889
890 if (VT == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000891 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel104de432008-11-24 17:11:17 +0000892 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000893 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000894 } else {
895 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000896 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000897 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000898 abort();
899 /*NOTREACHED*/
900 }
901
Dan Gohman475871a2008-07-27 21:46:04 +0000902 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000903}
904
Nate Begemanccef5802008-02-14 18:43:04 +0000905//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000906static SDValue
907LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000908 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000909 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000910
911 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000912 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000913
Nate Begemanccef5802008-02-14 18:43:04 +0000914 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000915 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000916 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000917 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000918 }
919
Dan Gohman475871a2008-07-27 21:46:04 +0000920 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000921}
922
Scott Michel9c0c6b22008-11-21 02:56:16 +0000923//! Lower MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000924static SDValue
925LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000926{
Dan Gohman475871a2008-07-27 21:46:04 +0000927 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000928 MVT CondVT = Cond.getValueType();
929 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000930
Scott Michel9c0c6b22008-11-21 02:56:16 +0000931 if (CondVT == MVT::i8) {
932 CondNVT = MVT::i16;
Scott Michel58c58182008-01-17 20:38:41 +0000933 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
934 Op.getOperand(0),
935 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
936 Op.getOperand(2));
937 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000938 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000939}
940
Dan Gohman475871a2008-07-27 21:46:04 +0000941static SDValue
942LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000943{
944 MachineFunction &MF = DAG.getMachineFunction();
945 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000946 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Micheld976c212008-10-30 01:51:48 +0000947 SmallVector<SDValue, 48> ArgValues;
Dan Gohman475871a2008-07-27 21:46:04 +0000948 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000949 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000950
951 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
952 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000953
Scott Michel266bc8f2007-12-04 22:23:35 +0000954 unsigned ArgOffset = SPUFrameInfo::minStackSize();
955 unsigned ArgRegIdx = 0;
956 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000957
Duncan Sands83ec4b62008-06-06 12:08:01 +0000958 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000959
Scott Michel266bc8f2007-12-04 22:23:35 +0000960 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000961 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
962 ArgNo != e; ++ArgNo) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000963 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
964 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Micheld976c212008-10-30 01:51:48 +0000965 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000966
Scott Micheld976c212008-10-30 01:51:48 +0000967 if (ArgRegIdx < NumArgRegs) {
968 const TargetRegisterClass *ArgRegClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000969
Scott Micheld976c212008-10-30 01:51:48 +0000970 switch (ObjectVT.getSimpleVT()) {
971 default: {
Scott Michel9c0c6b22008-11-21 02:56:16 +0000972 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
973 << ObjectVT.getMVTString()
974 << "\n";
975 abort();
Scott Micheld976c212008-10-30 01:51:48 +0000976 }
977 case MVT::i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000978 ArgRegClass = &SPU::R8CRegClass;
979 break;
Scott Micheld976c212008-10-30 01:51:48 +0000980 case MVT::i16:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000981 ArgRegClass = &SPU::R16CRegClass;
982 break;
Scott Micheld976c212008-10-30 01:51:48 +0000983 case MVT::i32:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000984 ArgRegClass = &SPU::R32CRegClass;
985 break;
Scott Micheld976c212008-10-30 01:51:48 +0000986 case MVT::i64:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000987 ArgRegClass = &SPU::R64CRegClass;
988 break;
Scott Micheld976c212008-10-30 01:51:48 +0000989 case MVT::f32:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000990 ArgRegClass = &SPU::R32FPRegClass;
991 break;
Scott Micheld976c212008-10-30 01:51:48 +0000992 case MVT::f64:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000993 ArgRegClass = &SPU::R64FPRegClass;
994 break;
Scott Micheld976c212008-10-30 01:51:48 +0000995 case MVT::v2f64:
996 case MVT::v4f32:
997 case MVT::v2i64:
998 case MVT::v4i32:
999 case MVT::v8i16:
1000 case MVT::v16i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +00001001 ArgRegClass = &SPU::VECREGRegClass;
1002 break;
Scott Micheld976c212008-10-30 01:51:48 +00001003 }
1004
1005 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
1006 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
1007 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1008 ++ArgRegIdx;
1009 } else {
1010 // We need to load the argument to a virtual register if we determined
1011 // above that we ran out of physical registers of the appropriate type
1012 // or we're forced to do vararg
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001013 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001014 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001015 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001016 ArgOffset += StackSlotSize;
1017 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001018
Scott Michel266bc8f2007-12-04 22:23:35 +00001019 ArgValues.push_back(ArgVal);
Scott Micheld976c212008-10-30 01:51:48 +00001020 // Update the chain
1021 Root = ArgVal.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001022 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001023
Scott Micheld976c212008-10-30 01:51:48 +00001024 // vararg handling:
Scott Michel266bc8f2007-12-04 22:23:35 +00001025 if (isVarArg) {
Scott Micheld976c212008-10-30 01:51:48 +00001026 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1027 // We will spill (79-3)+1 registers to the stack
1028 SmallVector<SDValue, 79-3+1> MemOps;
1029
1030 // Create the frame slot
1031
Scott Michel266bc8f2007-12-04 22:23:35 +00001032 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Micheld976c212008-10-30 01:51:48 +00001033 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1034 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1035 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1036 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1037 Root = Store.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001038 MemOps.push_back(Store);
Scott Micheld976c212008-10-30 01:51:48 +00001039
1040 // Increment address by stack slot size for the next stored argument
1041 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001042 }
1043 if (!MemOps.empty())
Scott Micheld976c212008-10-30 01:51:48 +00001044 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001045 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001046
Scott Michel266bc8f2007-12-04 22:23:35 +00001047 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001048
Scott Michel266bc8f2007-12-04 22:23:35 +00001049 // Return the new list of results.
Duncan Sandsaaffa052008-12-01 11:41:29 +00001050 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
1051 &ArgValues[0], ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001052}
1053
1054/// isLSAAddress - Return the immediate to use if the specified
1055/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001056static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001057 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +00001058 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001059
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001060 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001061 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1062 (Addr << 14 >> 14) != Addr)
1063 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001064
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001065 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001066}
1067
1068static
Dan Gohman475871a2008-07-27 21:46:04 +00001069SDValue
1070LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman095cc292008-09-13 01:54:27 +00001071 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1072 SDValue Chain = TheCall->getChain();
Dan Gohman095cc292008-09-13 01:54:27 +00001073 SDValue Callee = TheCall->getCallee();
1074 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001075 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1076 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1077 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1078
1079 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001080 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001081
Scott Michel266bc8f2007-12-04 22:23:35 +00001082 // Accumulate how many bytes are to be pushed on the stack, including the
1083 // linkage area, and parameter passing area. According to the SPU ABI,
1084 // we minimally need space for [LR] and [SP]
1085 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001086
Scott Michel266bc8f2007-12-04 22:23:35 +00001087 // Set up a copy of the stack pointer for use loading and storing any
1088 // arguments that may not fit in the registers available for argument
1089 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001090 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001091
Scott Michel266bc8f2007-12-04 22:23:35 +00001092 // Figure out which arguments are going to go in registers, and which in
1093 // memory.
1094 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1095 unsigned ArgRegIdx = 0;
1096
1097 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001098 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001099 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001100 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001101
1102 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001103 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001104
Scott Michel266bc8f2007-12-04 22:23:35 +00001105 // PtrOff will be used to store the current argument to the stack if a
1106 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001107 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001108 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1109
Duncan Sands83ec4b62008-06-06 12:08:01 +00001110 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001111 default: assert(0 && "Unexpected ValueType for argument!");
1112 case MVT::i32:
1113 case MVT::i64:
1114 case MVT::i128:
1115 if (ArgRegIdx != NumArgRegs) {
1116 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1117 } else {
1118 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001119 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001120 }
1121 break;
1122 case MVT::f32:
1123 case MVT::f64:
1124 if (ArgRegIdx != NumArgRegs) {
1125 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1126 } else {
1127 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001128 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001129 }
1130 break;
1131 case MVT::v4f32:
1132 case MVT::v4i32:
1133 case MVT::v8i16:
1134 case MVT::v16i8:
1135 if (ArgRegIdx != NumArgRegs) {
1136 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1137 } else {
1138 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001139 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001140 }
1141 break;
1142 }
1143 }
1144
1145 // Update number of stack bytes actually used, insert a call sequence start
1146 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnere563bbc2008-10-11 22:08:30 +00001147 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1148 true));
Scott Michel266bc8f2007-12-04 22:23:35 +00001149
1150 if (!MemOpChains.empty()) {
1151 // Adjust the stack pointer for the stack arguments.
1152 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1153 &MemOpChains[0], MemOpChains.size());
1154 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001155
Scott Michel266bc8f2007-12-04 22:23:35 +00001156 // Build a sequence of copy-to-reg nodes chained together with token chain
1157 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001158 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001159 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1160 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1161 InFlag);
1162 InFlag = Chain.getValue(1);
1163 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001164
Dan Gohman475871a2008-07-27 21:46:04 +00001165 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001166 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001167
Bill Wendling056292f2008-09-16 21:48:12 +00001168 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1169 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1170 // node so that legalize doesn't hack it.
Scott Michel19fd42a2008-11-11 03:06:06 +00001171 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001172 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001173 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001174 SDValue Zero = DAG.getConstant(0, PtrVT);
1175 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001176
Scott Michel9de5d0d2008-01-11 02:53:15 +00001177 if (!ST->usingLargeMem()) {
1178 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1179 // style calls, otherwise, external symbols are BRASL calls. This assumes
1180 // that declared/defined symbols are in the same compilation unit and can
1181 // be reached through PC-relative jumps.
1182 //
1183 // NOTE:
1184 // This may be an unsafe assumption for JIT and really large compilation
1185 // units.
1186 if (GV->isDeclaration()) {
1187 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1188 } else {
1189 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1190 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001191 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001192 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1193 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001194 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001195 }
Scott Michel19fd42a2008-11-11 03:06:06 +00001196 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Bill Wendling056292f2008-09-16 21:48:12 +00001197 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001198 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001199 // If this is an absolute destination address that appears to be a legal
1200 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001201 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001202 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001203
1204 Ops.push_back(Chain);
1205 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001206
Scott Michel266bc8f2007-12-04 22:23:35 +00001207 // Add argument registers to the end of the list so that they are known live
1208 // into the call.
1209 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001210 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001211 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001212
Gabor Greifba36cb52008-08-28 21:40:38 +00001213 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001214 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001215 // Returns a chain and a flag for retval copy to use.
1216 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1217 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001218 InFlag = Chain.getValue(1);
1219
Chris Lattnere563bbc2008-10-11 22:08:30 +00001220 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1221 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001222 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001223 InFlag = Chain.getValue(1);
1224
Dan Gohman475871a2008-07-27 21:46:04 +00001225 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001226 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001227
Scott Michel266bc8f2007-12-04 22:23:35 +00001228 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001229 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001230 default: assert(0 && "Unexpected ret value!");
1231 case MVT::Other: break;
1232 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001233 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001234 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1235 ResultVals[0] = Chain.getValue(0);
1236 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1237 Chain.getValue(2)).getValue(1);
1238 ResultVals[1] = Chain.getValue(0);
1239 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001240 } else {
1241 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1242 ResultVals[0] = Chain.getValue(0);
1243 NumResults = 1;
1244 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001245 break;
1246 case MVT::i64:
1247 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1248 ResultVals[0] = Chain.getValue(0);
1249 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001250 break;
1251 case MVT::f32:
1252 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001253 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001254 InFlag).getValue(1);
1255 ResultVals[0] = Chain.getValue(0);
1256 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001257 break;
1258 case MVT::v2f64:
1259 case MVT::v4f32:
1260 case MVT::v4i32:
1261 case MVT::v8i16:
1262 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001263 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001264 InFlag).getValue(1);
1265 ResultVals[0] = Chain.getValue(0);
1266 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001267 break;
1268 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001269
Scott Michel266bc8f2007-12-04 22:23:35 +00001270 // If the function returns void, just return the chain.
1271 if (NumResults == 0)
1272 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001273
Scott Michel266bc8f2007-12-04 22:23:35 +00001274 // Otherwise, merge everything together with a MERGE_VALUES node.
1275 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001276 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001277 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001278}
1279
Dan Gohman475871a2008-07-27 21:46:04 +00001280static SDValue
1281LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001282 SmallVector<CCValAssign, 16> RVLocs;
1283 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1284 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1285 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001286 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001287
Scott Michel266bc8f2007-12-04 22:23:35 +00001288 // If this is the first return lowered for this function, add the regs to the
1289 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001290 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001291 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001292 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001293 }
1294
Dan Gohman475871a2008-07-27 21:46:04 +00001295 SDValue Chain = Op.getOperand(0);
1296 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001297
Scott Michel266bc8f2007-12-04 22:23:35 +00001298 // Copy the result values into the output registers.
1299 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1300 CCValAssign &VA = RVLocs[i];
1301 assert(VA.isRegLoc() && "Can only return in registers!");
1302 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1303 Flag = Chain.getValue(1);
1304 }
1305
Gabor Greifba36cb52008-08-28 21:40:38 +00001306 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001307 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1308 else
1309 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1310}
1311
1312
1313//===----------------------------------------------------------------------===//
1314// Vector related lowering:
1315//===----------------------------------------------------------------------===//
1316
1317static ConstantSDNode *
1318getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001319 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001320
Scott Michel266bc8f2007-12-04 22:23:35 +00001321 // Check to see if this buildvec has a single non-undef value in its elements.
1322 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1323 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001324 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001325 OpVal = N->getOperand(i);
1326 else if (OpVal != N->getOperand(i))
1327 return 0;
1328 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001329
Gabor Greifba36cb52008-08-28 21:40:38 +00001330 if (OpVal.getNode() != 0) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001331 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001332 return CN;
1333 }
1334 }
1335
1336 return 0; // All UNDEF: use implicit def.; not Constant node
1337}
1338
1339/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1340/// and the value fits into an unsigned 18-bit constant, and if so, return the
1341/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001342SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001343 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001344 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001345 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001346 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001347 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001348 uint32_t upper = uint32_t(UValue >> 32);
1349 uint32_t lower = uint32_t(UValue);
1350 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001351 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001352 Value = Value >> 32;
1353 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001354 if (Value <= 0x3ffff)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001355 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001356 }
1357
Dan Gohman475871a2008-07-27 21:46:04 +00001358 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001359}
1360
1361/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1362/// and the value fits into a signed 16-bit constant, and if so, return the
1363/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001364SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001365 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001366 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001367 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001368 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001369 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001370 uint32_t upper = uint32_t(UValue >> 32);
1371 uint32_t lower = uint32_t(UValue);
1372 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001373 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001374 Value = Value >> 32;
1375 }
Scott Michelad2715e2008-03-05 23:02:02 +00001376 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001377 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001378 }
1379 }
1380
Dan Gohman475871a2008-07-27 21:46:04 +00001381 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001382}
1383
1384/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1385/// and the value fits into a signed 10-bit constant, and if so, return the
1386/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001387SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001388 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001389 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001390 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001391 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001392 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001393 uint32_t upper = uint32_t(UValue >> 32);
1394 uint32_t lower = uint32_t(UValue);
1395 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001396 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001397 Value = Value >> 32;
1398 }
Scott Michelad2715e2008-03-05 23:02:02 +00001399 if (isS10Constant(Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001400 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001401 }
1402
Dan Gohman475871a2008-07-27 21:46:04 +00001403 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001404}
1405
1406/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1407/// and the value fits into a signed 8-bit constant, and if so, return the
1408/// constant.
1409///
1410/// @note: The incoming vector is v16i8 because that's the only way we can load
1411/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1412/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001413SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001414 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001415 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001416 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001417 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001418 && Value <= 0xffff /* truncated from uint64_t */
1419 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001420 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001421 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001422 && (Value & 0xff) == Value)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001423 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001424 }
1425
Dan Gohman475871a2008-07-27 21:46:04 +00001426 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001427}
1428
1429/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1430/// and the value fits into a signed 16-bit constant, and if so, return the
1431/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001432SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001433 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001434 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001435 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001436 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001437 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1438 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001439 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001440 }
1441
Dan Gohman475871a2008-07-27 21:46:04 +00001442 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001443}
1444
1445/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001446SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001447 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001448 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001449 }
1450
Dan Gohman475871a2008-07-27 21:46:04 +00001451 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001452}
1453
1454/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001455SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001456 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001457 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001458 }
1459
Dan Gohman475871a2008-07-27 21:46:04 +00001460 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001461}
1462
1463// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001464// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001465// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1466// zero. Return true if this is not an array of constants, false if it is.
1467//
1468static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1469 uint64_t UndefBits[2]) {
1470 // Start with zero'd results.
1471 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001472
Duncan Sands83ec4b62008-06-06 12:08:01 +00001473 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001474 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001475 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001476
Scott Michel266bc8f2007-12-04 22:23:35 +00001477 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1478 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1479
1480 uint64_t EltBits = 0;
1481 if (OpVal.getOpcode() == ISD::UNDEF) {
1482 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1483 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1484 continue;
Scott Michel19fd42a2008-11-11 03:06:06 +00001485 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001486 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel19fd42a2008-11-11 03:06:06 +00001487 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001488 const APFloat &apf = CN->getValueAPF();
1489 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001490 ? FloatToBits(apf.convertToFloat())
1491 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001492 } else {
1493 // Nonconstant element.
1494 return true;
1495 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001496
Scott Michel266bc8f2007-12-04 22:23:35 +00001497 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1498 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001499
1500 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001501 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1502 return false;
1503}
1504
1505/// If this is a splat (repetition) of a value across the whole vector, return
1506/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001507/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001508/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001509static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001510 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001511 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001512 uint64_t &SplatBits, uint64_t &SplatUndef,
1513 int &SplatSize) {
1514 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1515 // the same as the lower 64-bits, ignoring undefs.
1516 uint64_t Bits64 = Bits128[0] | Bits128[1];
1517 uint64_t Undef64 = Undef128[0] & Undef128[1];
1518 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1519 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1520 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1521 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1522
1523 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1524 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001525
Scott Michel266bc8f2007-12-04 22:23:35 +00001526 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1527 // undefs.
1528 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001529 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001530
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001531 // If the top 16-bits are different than the lower 16-bits, ignoring
1532 // undefs, we have an i32 splat.
1533 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1534 if (MinSplatBits < 16) {
1535 // If the top 8-bits are different than the lower 8-bits, ignoring
1536 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001537 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1538 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001539 // Otherwise, we have an 8-bit splat.
1540 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1541 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1542 SplatSize = 1;
1543 return true;
1544 }
1545 } else {
1546 SplatBits = Bits16;
1547 SplatUndef = Undef16;
1548 SplatSize = 2;
1549 return true;
1550 }
1551 }
1552 } else {
1553 SplatBits = Bits32;
1554 SplatUndef = Undef32;
1555 SplatSize = 4;
1556 return true;
1557 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001558 }
1559 } else {
1560 SplatBits = Bits128[0];
1561 SplatUndef = Undef128[0];
1562 SplatSize = 8;
1563 return true;
1564 }
1565 }
1566
1567 return false; // Can't be a splat if two pieces don't match.
1568}
1569
1570// If this is a case we can't handle, return null and let the default
1571// expansion code take care of it. If we CAN select this case, and if it
1572// selects to a single instruction, return Op. Otherwise, if we can codegen
1573// this case more efficiently than a constant pool load, lower it to the
1574// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001575static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001576 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001577 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001578 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001579 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001580 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001581 uint64_t VectorBits[2];
1582 uint64_t UndefBits[2];
1583 uint64_t SplatBits, SplatUndef;
1584 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001585 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001586 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001587 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001588 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001589 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001590
Duncan Sands83ec4b62008-06-06 12:08:01 +00001591 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001592 default:
1593 case MVT::v4f32: {
1594 uint32_t Value32 = SplatBits;
1595 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001596 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001597 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001598 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001599 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001600 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001601 break;
1602 }
1603 case MVT::v2f64: {
1604 uint64_t f64val = SplatBits;
1605 assert(SplatSize == 8
Scott Michel104de432008-11-24 17:11:17 +00001606 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001607 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001608 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001609 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001610 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001611 break;
1612 }
1613 case MVT::v16i8: {
1614 // 8-bit constants have to be expanded to 16-bits
1615 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001616 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001617 for (int i = 0; i < 8; ++i)
1618 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1619 return DAG.getNode(ISD::BIT_CONVERT, VT,
1620 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1621 }
1622 case MVT::v8i16: {
1623 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001624 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001625 Value16 = (unsigned short) (SplatBits & 0xffff);
1626 else
1627 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001628 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1629 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001630 for (int i = 0; i < 8; ++i) Ops[i] = T;
1631 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1632 }
1633 case MVT::v4i32: {
1634 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001635 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001636 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1637 }
1638 case MVT::v2i64: {
1639 uint64_t val = SplatBits;
1640 uint32_t upper = uint32_t(val >> 32);
1641 uint32_t lower = uint32_t(val);
1642
Scott Michel4cb8bd82008-03-06 04:02:54 +00001643 if (upper == lower) {
1644 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001645 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001646 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001647 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001648 SDValue LO32;
1649 SDValue HI32;
1650 SmallVector<SDValue, 16> ShufBytes;
1651 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001652 bool upper_special, lower_special;
1653
1654 // NOTE: This code creates common-case shuffle masks that can be easily
1655 // detected as common expressions. It is not attempting to create highly
1656 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1657
1658 // Detect if the upper or lower half is a special shuffle mask pattern:
Scott Michel104de432008-11-24 17:11:17 +00001659 upper_special = (upper == 0||upper == 0xffffffff||upper == 0x80000000);
1660 lower_special = (lower == 0||lower == 0xffffffff||lower == 0x80000000);
Scott Michel266bc8f2007-12-04 22:23:35 +00001661
1662 // Create lower vector if not a special pattern
1663 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001664 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001665 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1666 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1667 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001668 }
1669
1670 // Create upper vector if not a special pattern
1671 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001672 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001673 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1674 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1675 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001676 }
1677
1678 // If either upper or lower are special, then the two input operands are
1679 // the same (basically, one of them is a "don't care")
1680 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001681 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001682 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001683 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001684 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001685 // Unhappy situation... both upper and lower are special, so punt with
1686 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001687 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001688 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001689 Zero, Zero);
1690 }
1691
1692 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001693 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001694 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001695 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001696 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001697 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001698 process_upper = (upper_special && (i & 1) == 0);
1699 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001700
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001701 if (process_upper || process_lower) {
1702 if ((process_upper && upper == 0)
1703 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001704 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001705 else if ((process_upper && upper == 0xffffffff)
1706 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001707 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001708 else if ((process_upper && upper == 0x80000000)
1709 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001710 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001711 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001712 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001713 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001714
1715 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001716 }
1717
1718 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001719 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001720 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001721 }
1722 }
1723 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001724
Dan Gohman475871a2008-07-27 21:46:04 +00001725 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001726}
1727
1728/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1729/// which the Cell can operate. The code inspects V3 to ascertain whether the
1730/// permutation vector, V3, is monotonically increasing with one "exception"
1731/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel7a1c9e92008-11-22 23:50:42 +00001732/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel266bc8f2007-12-04 22:23:35 +00001733/// In either case, the net result is going to eventually invoke SHUFB to
1734/// permute/shuffle the bytes from V1 and V2.
1735/// \note
Scott Michel7a1c9e92008-11-22 23:50:42 +00001736/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel266bc8f2007-12-04 22:23:35 +00001737/// control word for byte/halfword/word insertion. This takes care of a single
1738/// element move from V2 into V1.
1739/// \note
1740/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001741static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1742 SDValue V1 = Op.getOperand(0);
1743 SDValue V2 = Op.getOperand(1);
1744 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001745
Scott Michel266bc8f2007-12-04 22:23:35 +00001746 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001747
Scott Michel266bc8f2007-12-04 22:23:35 +00001748 // If we have a single element being moved from V1 to V2, this can be handled
1749 // using the C*[DX] compute mask instructions, but the vector elements have
1750 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001751 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001752 unsigned EltsFromV2 = 0;
1753 unsigned V2Elt = 0;
1754 unsigned V2EltIdx0 = 0;
1755 unsigned CurrElt = 0;
1756 bool monotonic = true;
1757 if (EltVT == MVT::i8)
1758 V2EltIdx0 = 16;
1759 else if (EltVT == MVT::i16)
1760 V2EltIdx0 = 8;
1761 else if (EltVT == MVT::i32)
1762 V2EltIdx0 = 4;
1763 else
1764 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1765
1766 for (unsigned i = 0, e = PermMask.getNumOperands();
1767 EltsFromV2 <= 1 && monotonic && i != e;
1768 ++i) {
1769 unsigned SrcElt;
1770 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1771 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001772 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001773 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001774
1775 if (SrcElt >= V2EltIdx0) {
1776 ++EltsFromV2;
1777 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1778 } else if (CurrElt != SrcElt) {
1779 monotonic = false;
1780 }
1781
1782 ++CurrElt;
1783 }
1784
1785 if (EltsFromV2 == 1 && monotonic) {
1786 // Compute mask and shuffle
1787 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001788 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1789 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001790 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001791 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001792 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001793 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel7a1c9e92008-11-22 23:50:42 +00001794 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001795 SDValue ShufMaskOp =
Scott Michel7a1c9e92008-11-22 23:50:42 +00001796 DAG.getNode(SPUISD::SHUFFLE_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001797 DAG.getTargetConstant(V2Elt, MVT::i32),
1798 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001799 // Use shuffle mask in SHUFB synthetic instruction:
1800 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1801 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001802 // Convert the SHUFFLE_VECTOR mask's input element units to the
1803 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001804 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001805
Dan Gohman475871a2008-07-27 21:46:04 +00001806 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001807 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1808 unsigned SrcElt;
1809 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001810 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001811 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001812 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001813
Scott Michela59d4692008-02-23 18:41:37 +00001814 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001815 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1816 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001817 }
1818 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001819
Dan Gohman475871a2008-07-27 21:46:04 +00001820 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001821 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001822 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1823 }
1824}
1825
Dan Gohman475871a2008-07-27 21:46:04 +00001826static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1827 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001828
Gabor Greifba36cb52008-08-28 21:40:38 +00001829 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001830 // For a constant, build the appropriate constant vector, which will
1831 // eventually simplify to a vector register load.
1832
Gabor Greifba36cb52008-08-28 21:40:38 +00001833 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001834 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001835 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001836 size_t n_copies;
1837
1838 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001839 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001840 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001841 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001842 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1843 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1844 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1845 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1846 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1847 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1848 }
1849
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001850 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001851 for (size_t j = 0; j < n_copies; ++j)
1852 ConstVecValues.push_back(CValue);
1853
1854 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001855 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001856 } else {
1857 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001858 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001859 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1860 case MVT::i8:
1861 case MVT::i16:
1862 case MVT::i32:
1863 case MVT::i64:
1864 case MVT::f32:
1865 case MVT::f64:
1866 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1867 }
1868 }
1869
Dan Gohman475871a2008-07-27 21:46:04 +00001870 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001871}
1872
Dan Gohman475871a2008-07-27 21:46:04 +00001873static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001874 switch (Op.getValueType().getSimpleVT()) {
1875 default:
1876 cerr << "CellSPU: Unknown vector multiplication, got "
1877 << Op.getValueType().getMVTString()
1878 << "\n";
1879 abort();
1880 /*NOTREACHED*/
1881
Scott Michel266bc8f2007-12-04 22:23:35 +00001882 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001883 SDValue rA = Op.getOperand(0);
1884 SDValue rB = Op.getOperand(1);
1885 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1886 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1887 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1888 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001889
1890 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1891 break;
1892 }
1893
1894 // Multiply two v8i16 vectors (pipeline friendly version):
1895 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1896 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1897 // c) Use SELB to select upper and lower halves from the intermediate results
1898 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001899 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001900 // dual-issue. This code does manage to do this, even if it's a little on
1901 // the wacky side
1902 case MVT::v8i16: {
1903 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001904 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001905 SDValue Chain = Op.getOperand(0);
1906 SDValue rA = Op.getOperand(0);
1907 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001908 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1909 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001910
Dan Gohman475871a2008-07-27 21:46:04 +00001911 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001912 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001913 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001914 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001915
Dan Gohman475871a2008-07-27 21:46:04 +00001916 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001917 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001918 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001919
Dan Gohman475871a2008-07-27 21:46:04 +00001920 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001921 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001922 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001923
1924 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001925 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1926 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1927 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1928 HHProd_v4i32,
1929 DAG.getConstant(16, MVT::i16))),
1930 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001931 }
1932
1933 // This M00sE is N@stI! (apologies to Monty Python)
1934 //
1935 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1936 // is to break it all apart, sign extend, and reassemble the various
1937 // intermediate products.
1938 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001939 SDValue rA = Op.getOperand(0);
1940 SDValue rB = Op.getOperand(1);
1941 SDValue c8 = DAG.getConstant(8, MVT::i32);
1942 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001943
Dan Gohman475871a2008-07-27 21:46:04 +00001944 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001945 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001946 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1947 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001948
Dan Gohman475871a2008-07-27 21:46:04 +00001949 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001950
Dan Gohman475871a2008-07-27 21:46:04 +00001951 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001952
Dan Gohman475871a2008-07-27 21:46:04 +00001953 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001954 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001955 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001956
Dan Gohman475871a2008-07-27 21:46:04 +00001957 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001958 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001959
Dan Gohman475871a2008-07-27 21:46:04 +00001960 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001961 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1962 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1963 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001964
Dan Gohman475871a2008-07-27 21:46:04 +00001965 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001966
Dan Gohman475871a2008-07-27 21:46:04 +00001967 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001968 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00001969 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001970 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1971 LoProdMask, LoProdMask,
1972 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00001973
Dan Gohman475871a2008-07-27 21:46:04 +00001974 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001975 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001976 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001977
Dan Gohman475871a2008-07-27 21:46:04 +00001978 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00001979 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001980 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00001981
Dan Gohman475871a2008-07-27 21:46:04 +00001982 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001983 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001984 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
1985 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00001986
Dan Gohman475871a2008-07-27 21:46:04 +00001987 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001988 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001989 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001990 DAG.getNode(SPUISD::VEC_SRA,
1991 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001992 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00001993 DAG.getNode(SPUISD::VEC_SRA,
1994 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001995
Dan Gohman475871a2008-07-27 21:46:04 +00001996 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00001997 DAG.getNode(SPUISD::SELB, MVT::v8i16,
1998 HLProd,
1999 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2000 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002001
Dan Gohman475871a2008-07-27 21:46:04 +00002002 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002003 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002004
2005 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002006 DAG.getNode(ISD::OR, MVT::v4i32,
2007 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002008 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002009 }
2010
Dan Gohman475871a2008-07-27 21:46:04 +00002011 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002012}
2013
Dan Gohman475871a2008-07-27 21:46:04 +00002014static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002015 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002016 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002017
Dan Gohman475871a2008-07-27 21:46:04 +00002018 SDValue A = Op.getOperand(0);
2019 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002020 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002021
2022 unsigned VRegBR, VRegC;
2023
2024 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002025 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2026 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002027 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002028 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2029 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002030 }
2031 // TODO: make sure we're feeding FPInterp the right arguments
2032 // Right now: fi B, frest(B)
2033
2034 // Computes BRcpl =
2035 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002036 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002037 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2038 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002039 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002040
Scott Michel266bc8f2007-12-04 22:23:35 +00002041 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002042 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002043 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002044 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002045 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002046 // What's the Chain variable do? It's magic!
2047 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002048
2049 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002050 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002051 DAG.getNode(ISD::FMUL, VT,
2052 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002053 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002054 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002055 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002056}
2057
Dan Gohman475871a2008-07-27 21:46:04 +00002058static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002059 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002060 SDValue N = Op.getOperand(0);
2061 SDValue Elt = Op.getOperand(1);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002062 SDValue retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00002063
Scott Michel7a1c9e92008-11-22 23:50:42 +00002064 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2065 // Constant argument:
2066 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002067
Scott Michel7a1c9e92008-11-22 23:50:42 +00002068 // sanity checks:
2069 if (VT == MVT::i8 && EltNo >= 16)
2070 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2071 else if (VT == MVT::i16 && EltNo >= 8)
2072 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2073 else if (VT == MVT::i32 && EltNo >= 4)
2074 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2075 else if (VT == MVT::i64 && EltNo >= 2)
2076 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel266bc8f2007-12-04 22:23:35 +00002077
Scott Michel7a1c9e92008-11-22 23:50:42 +00002078 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2079 // i32 and i64: Element 0 is the preferred slot
Scott Michel104de432008-11-24 17:11:17 +00002080 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002081 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002082
Scott Michel7a1c9e92008-11-22 23:50:42 +00002083 // Need to generate shuffle mask and extract:
2084 int prefslot_begin = -1, prefslot_end = -1;
2085 int elt_byte = EltNo * VT.getSizeInBits() / 8;
2086
2087 switch (VT.getSimpleVT()) {
2088 default:
2089 assert(false && "Invalid value type!");
2090 case MVT::i8: {
2091 prefslot_begin = prefslot_end = 3;
2092 break;
2093 }
2094 case MVT::i16: {
2095 prefslot_begin = 2; prefslot_end = 3;
2096 break;
2097 }
2098 case MVT::i32:
2099 case MVT::f32: {
2100 prefslot_begin = 0; prefslot_end = 3;
2101 break;
2102 }
2103 case MVT::i64:
2104 case MVT::f64: {
2105 prefslot_begin = 0; prefslot_end = 7;
2106 break;
2107 }
2108 }
2109
2110 assert(prefslot_begin != -1 && prefslot_end != -1 &&
2111 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2112
2113 unsigned int ShufBytes[16];
2114 for (int i = 0; i < 16; ++i) {
2115 // zero fill uppper part of preferred slot, don't care about the
2116 // other slots:
2117 unsigned int mask_val;
2118 if (i <= prefslot_end) {
2119 mask_val =
2120 ((i < prefslot_begin)
2121 ? 0x80
2122 : elt_byte + (i - prefslot_begin));
2123
2124 ShufBytes[i] = mask_val;
2125 } else
2126 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2127 }
2128
2129 SDValue ShufMask[4];
2130 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
2131 unsigned bidx = i / 4;
2132 unsigned int bits = ((ShufBytes[bidx] << 24) |
2133 (ShufBytes[bidx+1] << 16) |
2134 (ShufBytes[bidx+2] << 8) |
2135 ShufBytes[bidx+3]);
2136 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
2137 }
2138
2139 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2140 &ShufMask[0],
2141 sizeof(ShufMask) / sizeof(ShufMask[0]));
2142
Scott Michel104de432008-11-24 17:11:17 +00002143 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel7a1c9e92008-11-22 23:50:42 +00002144 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2145 N, N, ShufMaskVec));
2146 } else {
2147 // Variable index: Rotate the requested element into slot 0, then replicate
2148 // slot 0 across the vector
2149 MVT VecVT = N.getValueType();
2150 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2151 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2152 abort();
2153 }
2154
2155 // Make life easier by making sure the index is zero-extended to i32
2156 if (Elt.getValueType() != MVT::i32)
2157 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2158
2159 // Scale the index to a bit/byte shift quantity
2160 APInt scaleFactor =
Scott Michel104de432008-11-24 17:11:17 +00002161 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2162 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel7a1c9e92008-11-22 23:50:42 +00002163 SDValue vecShift;
Scott Michel7a1c9e92008-11-22 23:50:42 +00002164
Scott Michel104de432008-11-24 17:11:17 +00002165 if (scaleShift > 0) {
2166 // Scale the shift factor:
Scott Michel7a1c9e92008-11-22 23:50:42 +00002167 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel104de432008-11-24 17:11:17 +00002168 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel7a1c9e92008-11-22 23:50:42 +00002169 }
2170
Scott Michel104de432008-11-24 17:11:17 +00002171 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2172
2173 // Replicate the bytes starting at byte 0 across the entire vector (for
2174 // consistency with the notion of a unified register set)
Scott Michel7a1c9e92008-11-22 23:50:42 +00002175 SDValue replicate;
2176
2177 switch (VT.getSimpleVT()) {
2178 default:
2179 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2180 abort();
2181 /*NOTREACHED*/
2182 case MVT::i8: {
Scott Michel104de432008-11-24 17:11:17 +00002183 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002184 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2185 factor, factor);
2186 break;
2187 }
2188 case MVT::i16: {
Scott Michel104de432008-11-24 17:11:17 +00002189 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002190 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2191 factor, factor);
2192 break;
2193 }
2194 case MVT::i32:
2195 case MVT::f32: {
2196 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2197 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2198 factor, factor);
2199 break;
2200 }
2201 case MVT::i64:
2202 case MVT::f64: {
2203 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2204 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2205 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2206 loFactor, hiFactor);
2207 break;
2208 }
2209 }
2210
Scott Michel104de432008-11-24 17:11:17 +00002211 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel7a1c9e92008-11-22 23:50:42 +00002212 DAG.getNode(SPUISD::SHUFB, VecVT, vecShift, vecShift, replicate));
Scott Michel266bc8f2007-12-04 22:23:35 +00002213 }
2214
Scott Michel7a1c9e92008-11-22 23:50:42 +00002215 return retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00002216}
2217
Dan Gohman475871a2008-07-27 21:46:04 +00002218static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2219 SDValue VecOp = Op.getOperand(0);
2220 SDValue ValOp = Op.getOperand(1);
2221 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002222 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002223
2224 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2225 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2226
Duncan Sands83ec4b62008-06-06 12:08:01 +00002227 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002228 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002229 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002230
Dan Gohman475871a2008-07-27 21:46:04 +00002231 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002232 DAG.getNode(SPUISD::SHUFB, VT,
2233 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2234 VecOp,
Scott Michel7a1c9e92008-11-22 23:50:42 +00002235 DAG.getNode(SPUISD::SHUFFLE_MASK, VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002236 DAG.getNode(ISD::ADD, PtrVT,
2237 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002238 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002239 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002240
2241 return result;
2242}
2243
Dan Gohman475871a2008-07-27 21:46:04 +00002244static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002245{
Dan Gohman475871a2008-07-27 21:46:04 +00002246 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002247
2248 assert(Op.getValueType() == MVT::i8);
2249 switch (Opc) {
2250 default:
2251 assert(0 && "Unhandled i8 math operator");
2252 /*NOTREACHED*/
2253 break;
2254 case ISD::SUB: {
2255 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2256 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002257 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002258 N0 = (N0.getOpcode() != ISD::Constant
2259 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002260 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2261 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002262 N1 = (N1.getOpcode() != ISD::Constant
2263 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002264 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2265 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002266 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002267 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002268 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002269 case ISD::ROTR:
2270 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002271 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002272 unsigned N1Opc;
2273 N0 = (N0.getOpcode() != ISD::Constant
2274 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002275 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2276 MVT::i16));
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002277 N1Opc = N1.getValueType().bitsLT(MVT::i32)
Gabor Greif93c53e52008-08-31 15:37:04 +00002278 ? ISD::ZERO_EXTEND
2279 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002280 N1 = (N1.getOpcode() != ISD::Constant
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002281 ? DAG.getNode(N1Opc, MVT::i32, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002282 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002283 MVT::i32));
Dan Gohman475871a2008-07-27 21:46:04 +00002284 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002285 DAG.getNode(ISD::OR, MVT::i16, N0,
2286 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002287 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002288 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002289 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2290 }
2291 case ISD::SRL:
2292 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002293 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002294 unsigned N1Opc;
2295 N0 = (N0.getOpcode() != ISD::Constant
2296 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002297 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2298 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002299 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2300 ? ISD::ZERO_EXTEND
2301 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002302 N1 = (N1.getOpcode() != ISD::Constant
2303 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002304 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2305 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002306 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002307 DAG.getNode(Opc, MVT::i16, N0, N1));
2308 }
2309 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002310 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002311 unsigned N1Opc;
2312 N0 = (N0.getOpcode() != ISD::Constant
2313 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002314 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2315 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002316 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2317 ? ISD::SIGN_EXTEND
2318 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002319 N1 = (N1.getOpcode() != ISD::Constant
2320 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002321 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2322 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002323 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002324 DAG.getNode(Opc, MVT::i16, N0, N1));
2325 }
2326 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002327 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002328 unsigned N1Opc;
2329 N0 = (N0.getOpcode() != ISD::Constant
2330 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002331 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2332 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002333 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002334 N1 = (N1.getOpcode() != ISD::Constant
2335 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002336 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2337 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002338 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002339 DAG.getNode(Opc, MVT::i16, N0, N1));
2340 break;
2341 }
2342 }
2343
Dan Gohman475871a2008-07-27 21:46:04 +00002344 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002345}
2346
Dan Gohman475871a2008-07-27 21:46:04 +00002347static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002348{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002349 MVT VT = Op.getValueType();
2350 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002351
Dan Gohman475871a2008-07-27 21:46:04 +00002352 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002353
2354 switch (Opc) {
2355 case ISD::ZERO_EXTEND:
2356 case ISD::SIGN_EXTEND:
2357 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002358 MVT Op0VT = Op0.getValueType();
2359 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002360
2361 assert(Op0VT == MVT::i32
2362 && "CellSPU: Zero/sign extending something other than i32");
2363
Scott Michel104de432008-11-24 17:11:17 +00002364 DEBUG(cerr << "CellSPU.LowerI64Math: lowering zero/sign/any extend\n");
2365
Dan Gohman475871a2008-07-27 21:46:04 +00002366 SDValue PromoteScalar =
Scott Michel104de432008-11-24 17:11:17 +00002367 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
Scott Michela59d4692008-02-23 18:41:37 +00002368
Scott Michel104de432008-11-24 17:11:17 +00002369 if (Opc != ISD::SIGN_EXTEND) {
Scott Michel045a1452008-11-24 18:20:46 +00002370 // Use a shuffle to zero extend the i32 to i64 directly:
2371 SDValue shufMask =
2372 DAG.getNode(ISD::BUILD_VECTOR, Op0VecVT,
2373 DAG.getConstant(0x80808080, MVT::i32),
2374 DAG.getConstant(0x00010203, MVT::i32),
2375 DAG.getConstant(0x80808080, MVT::i32),
2376 DAG.getConstant(0x08090a0b, MVT::i32));
2377 SDValue zextShuffle =
2378 DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2379 PromoteScalar, PromoteScalar, shufMask);
2380
Scott Michel104de432008-11-24 17:11:17 +00002381 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel045a1452008-11-24 18:20:46 +00002382 DAG.getNode(ISD::BIT_CONVERT, VecVT, zextShuffle));
Scott Michel104de432008-11-24 17:11:17 +00002383 } else {
2384 // SPU has no "rotate quadword and replicate bit 0" (i.e. rotate/shift
2385 // right and propagate the sign bit) instruction.
Scott Michel045a1452008-11-24 18:20:46 +00002386 SDValue RotQuad =
2387 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, Op0VecVT,
2388 PromoteScalar, DAG.getConstant(4, MVT::i32));
Scott Michel104de432008-11-24 17:11:17 +00002389 SDValue SignQuad =
2390 DAG.getNode(SPUISD::VEC_SRA, Op0VecVT,
2391 PromoteScalar, DAG.getConstant(32, MVT::i32));
2392 SDValue SelMask =
2393 DAG.getNode(SPUISD::SELECT_MASK, Op0VecVT,
2394 DAG.getConstant(0xf0f0, MVT::i16));
2395 SDValue CombineQuad =
2396 DAG.getNode(SPUISD::SELB, Op0VecVT,
2397 SignQuad, RotQuad, SelMask);
2398
2399 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2400 DAG.getNode(ISD::BIT_CONVERT, VecVT, CombineQuad));
2401 }
Scott Michela59d4692008-02-23 18:41:37 +00002402 }
2403
Scott Michel8bf61e82008-06-02 22:18:03 +00002404 case ISD::ADD: {
2405 // Turn operands into vectors to satisfy type checking (shufb works on
2406 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002407 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002408 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002409 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002410 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002411 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002412
2413 // Create the shuffle mask for "rotating" the borrow up one register slot
2414 // once the borrow is generated.
2415 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2416 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2417 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2418 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2419
Dan Gohman475871a2008-07-27 21:46:04 +00002420 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002421 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002422 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002423 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2424 CarryGen, CarryGen,
2425 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2426 &ShufBytes[0], ShufBytes.size()));
2427
Scott Michel104de432008-11-24 17:11:17 +00002428 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel8bf61e82008-06-02 22:18:03 +00002429 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2430 Op0, Op1, ShiftedCarry));
2431 }
2432
2433 case ISD::SUB: {
2434 // Turn operands into vectors to satisfy type checking (shufb works on
2435 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002436 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002437 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002438 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002439 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002440 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002441
2442 // Create the shuffle mask for "rotating" the borrow up one register slot
2443 // once the borrow is generated.
2444 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2445 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2446 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2447 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2448
Dan Gohman475871a2008-07-27 21:46:04 +00002449 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002450 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002451 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002452 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2453 BorrowGen, BorrowGen,
2454 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2455 &ShufBytes[0], ShufBytes.size()));
2456
Scott Michel104de432008-11-24 17:11:17 +00002457 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel8bf61e82008-06-02 22:18:03 +00002458 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2459 Op0, Op1, ShiftedBorrow));
2460 }
2461
Scott Michela59d4692008-02-23 18:41:37 +00002462 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002463 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002464 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002465 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2466 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002467 DAG.getNode(SPUISD::SELB, VecVT,
2468 Op0Vec,
2469 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002470 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002471 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002472 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002473 DAG.getNode(ISD::SRL, ShiftAmtVT,
2474 ShiftAmt,
2475 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002476 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002477 DAG.getNode(ISD::AND, ShiftAmtVT,
2478 ShiftAmt,
2479 DAG.getConstant(7, ShiftAmtVT));
2480
Scott Michel104de432008-11-24 17:11:17 +00002481 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michela59d4692008-02-23 18:41:37 +00002482 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2483 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2484 MaskLower, ShiftAmtBytes),
2485 ShiftAmtBits));
2486 }
2487
2488 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002489 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002490 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002491 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002492 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002493 DAG.getNode(ISD::SRL, ShiftAmtVT,
2494 ShiftAmt,
2495 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002496 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002497 DAG.getNode(ISD::AND, ShiftAmtVT,
2498 ShiftAmt,
2499 DAG.getConstant(7, ShiftAmtVT));
2500
2501 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2502 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2503 Op0, ShiftAmtBytes),
2504 ShiftAmtBits);
2505 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002506
2507 case ISD::SRA: {
2508 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002509 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002510 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002511 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002512 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002513
2514 // Negate variable shift amounts
2515 if (!isa<ConstantSDNode>(ShiftAmt)) {
2516 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2517 DAG.getConstant(0, ShiftVT), ShiftAmt);
2518 }
2519
Dan Gohman475871a2008-07-27 21:46:04 +00002520 SDValue UpperHalfSign =
Scott Michel104de432008-11-24 17:11:17 +00002521 DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i32,
Scott Michel8bf61e82008-06-02 22:18:03 +00002522 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2523 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2524 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002525 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002526 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002527 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002528 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2529 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002530 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002531 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2532 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002533 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002534 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2535 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002536 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002537 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2538 RotateLeftBytes, ShiftAmt);
2539
Scott Michel104de432008-11-24 17:11:17 +00002540 return DAG.getNode(SPUISD::VEC2PREFSLOT, MVT::i64,
Scott Michel8bf61e82008-06-02 22:18:03 +00002541 RotateLeftBits);
2542 }
Scott Michela59d4692008-02-23 18:41:37 +00002543 }
2544
Dan Gohman475871a2008-07-27 21:46:04 +00002545 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002546}
2547
Scott Michel266bc8f2007-12-04 22:23:35 +00002548//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002549static SDValue
2550LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2551 SDValue ConstVec;
2552 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002553 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002554
2555 ConstVec = Op.getOperand(0);
2556 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002557 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2558 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002559 ConstVec = ConstVec.getOperand(0);
2560 } else {
2561 ConstVec = Op.getOperand(1);
2562 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002563 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002564 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002565 }
2566 }
2567 }
2568
Gabor Greifba36cb52008-08-28 21:40:38 +00002569 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002570 uint64_t VectorBits[2];
2571 uint64_t UndefBits[2];
2572 uint64_t SplatBits, SplatUndef;
2573 int SplatSize;
2574
Gabor Greifba36cb52008-08-28 21:40:38 +00002575 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002576 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002577 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002578 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002579 SDValue tcVec[16];
2580 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002581 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2582
2583 // Turn the BUILD_VECTOR into a set of target constants:
2584 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002585 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002586
Gabor Greifba36cb52008-08-28 21:40:38 +00002587 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002588 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002589 }
2590 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002591 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2592 // lowered. Return the operation, rather than a null SDValue.
2593 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002594}
2595
2596//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002597static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002598 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002599 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002600 default:
2601 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002602 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002603 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002604 abort();
2605 /*NOTREACHED*/
2606
2607 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002608 SDValue rA = Op.getOperand(0);
2609 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002610
2611 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002612 DAG.getNode(ISD::ADD, MVT::i32,
2613 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2614 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2615 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002616 }
2617 }
2618
Dan Gohman475871a2008-07-27 21:46:04 +00002619 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002620}
2621
2622//! Custom lowering for CTPOP (count population)
2623/*!
2624 Custom lowering code that counts the number ones in the input
2625 operand. SPU has such an instruction, but it counts the number of
2626 ones per byte, which then have to be accumulated.
2627*/
Dan Gohman475871a2008-07-27 21:46:04 +00002628static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002629 MVT VT = Op.getValueType();
2630 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002631
Duncan Sands83ec4b62008-06-06 12:08:01 +00002632 switch (VT.getSimpleVT()) {
2633 default:
2634 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002635 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002636 SDValue N = Op.getOperand(0);
2637 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002638
Dan Gohman475871a2008-07-27 21:46:04 +00002639 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2640 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002641
2642 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2643 }
2644
2645 case MVT::i16: {
2646 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002647 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002648
Chris Lattner84bc5422007-12-31 04:13:23 +00002649 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002650
Dan Gohman475871a2008-07-27 21:46:04 +00002651 SDValue N = Op.getOperand(0);
2652 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2653 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002654 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002655
Dan Gohman475871a2008-07-27 21:46:04 +00002656 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2657 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002658
2659 // CNTB_result becomes the chain to which all of the virtual registers
2660 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002661 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002662 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002663
Dan Gohman475871a2008-07-27 21:46:04 +00002664 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002665 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2666
Dan Gohman475871a2008-07-27 21:46:04 +00002667 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002668
2669 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002670 DAG.getNode(ISD::ADD, MVT::i16,
2671 DAG.getNode(ISD::SRL, MVT::i16,
2672 Tmp1, Shift1),
2673 Tmp1),
2674 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002675 }
2676
2677 case MVT::i32: {
2678 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002679 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002680
Chris Lattner84bc5422007-12-31 04:13:23 +00002681 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2682 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002683
Dan Gohman475871a2008-07-27 21:46:04 +00002684 SDValue N = Op.getOperand(0);
2685 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2686 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2687 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2688 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002689
Dan Gohman475871a2008-07-27 21:46:04 +00002690 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2691 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002692
2693 // CNTB_result becomes the chain to which all of the virtual registers
2694 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002695 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002696 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002697
Dan Gohman475871a2008-07-27 21:46:04 +00002698 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002699 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2700
Dan Gohman475871a2008-07-27 21:46:04 +00002701 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002702 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002703 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002704
Dan Gohman475871a2008-07-27 21:46:04 +00002705 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002706 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002707 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002708
Dan Gohman475871a2008-07-27 21:46:04 +00002709 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002710 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2711
Dan Gohman475871a2008-07-27 21:46:04 +00002712 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002713 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002714 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2715 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002716 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002717 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002718 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002719
2720 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2721 }
2722
2723 case MVT::i64:
2724 break;
2725 }
2726
Dan Gohman475871a2008-07-27 21:46:04 +00002727 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002728}
2729
Scott Michel7a1c9e92008-11-22 23:50:42 +00002730//! Lower ISD::SELECT_CC
2731/*!
2732 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2733 SELB instruction.
2734
2735 \note Need to revisit this in the future: if the code path through the true
2736 and false value computations is longer than the latency of a branch (6
2737 cycles), then it would be more advantageous to branch and insert a new basic
2738 block and branch on the condition. However, this code does not make that
2739 assumption, given the simplisitc uses so far.
2740 */
2741
2742static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
2743 MVT VT = Op.getValueType();
2744 SDValue lhs = Op.getOperand(0);
2745 SDValue rhs = Op.getOperand(1);
2746 SDValue trueval = Op.getOperand(2);
2747 SDValue falseval = Op.getOperand(3);
2748 SDValue condition = Op.getOperand(4);
2749
2750 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2751 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2752 // with another "cannot select select_cc" assert:
2753
2754 SDValue compare = DAG.getNode(ISD::SETCC, VT, lhs, rhs, condition);
2755 return DAG.getNode(SPUISD::SELB, VT, trueval, falseval, compare);
2756}
2757
2758//! Custom (target-specific) lowering entry point
2759/*!
2760 This is where LLVM's DAG selection process calls to do target-specific
2761 lowering of nodes.
2762 */
Dan Gohman475871a2008-07-27 21:46:04 +00002763SDValue
2764SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002765{
Scott Michela59d4692008-02-23 18:41:37 +00002766 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002767 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002768
2769 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002770 default: {
2771 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002772 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002773 cerr << "*Op.getNode():\n";
2774 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002775 abort();
2776 }
2777 case ISD::LOAD:
2778 case ISD::SEXTLOAD:
2779 case ISD::ZEXTLOAD:
2780 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2781 case ISD::STORE:
2782 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2783 case ISD::ConstantPool:
2784 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2785 case ISD::GlobalAddress:
2786 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2787 case ISD::JumpTable:
2788 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2789 case ISD::Constant:
2790 return LowerConstant(Op, DAG);
2791 case ISD::ConstantFP:
2792 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002793 case ISD::BRCOND:
2794 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002795 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002796 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002797 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002798 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002799 case ISD::RET:
2800 return LowerRET(Op, DAG, getTargetMachine());
2801
Scott Michela59d4692008-02-23 18:41:37 +00002802
2803 // i8, i64 math ops:
2804 case ISD::ZERO_EXTEND:
2805 case ISD::SIGN_EXTEND:
2806 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002807 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002808 case ISD::SUB:
2809 case ISD::ROTR:
2810 case ISD::ROTL:
2811 case ISD::SRL:
2812 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002813 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002814 if (VT == MVT::i8)
2815 return LowerI8Math(Op, DAG, Opc);
2816 else if (VT == MVT::i64)
2817 return LowerI64Math(Op, DAG, Opc);
2818 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002819 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002820
2821 // Vector-related lowering.
2822 case ISD::BUILD_VECTOR:
2823 return LowerBUILD_VECTOR(Op, DAG);
2824 case ISD::SCALAR_TO_VECTOR:
2825 return LowerSCALAR_TO_VECTOR(Op, DAG);
2826 case ISD::VECTOR_SHUFFLE:
2827 return LowerVECTOR_SHUFFLE(Op, DAG);
2828 case ISD::EXTRACT_VECTOR_ELT:
2829 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2830 case ISD::INSERT_VECTOR_ELT:
2831 return LowerINSERT_VECTOR_ELT(Op, DAG);
2832
2833 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2834 case ISD::AND:
2835 case ISD::OR:
2836 case ISD::XOR:
2837 return LowerByteImmed(Op, DAG);
2838
2839 // Vector and i8 multiply:
2840 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002841 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002842 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002843 else if (VT == MVT::i8)
2844 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002845 else
Scott Michela59d4692008-02-23 18:41:37 +00002846 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002847
2848 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002849 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002850 return LowerFDIVf32(Op, DAG);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002851#if 0
2852 // This is probably a libcall
2853 else if (Op.getValueType() == MVT::f64)
2854 return LowerFDIVf64(Op, DAG);
2855#endif
Scott Michel266bc8f2007-12-04 22:23:35 +00002856 else
2857 assert(0 && "Calling FDIV on unsupported MVT");
2858
2859 case ISD::CTPOP:
2860 return LowerCTPOP(Op, DAG);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002861
2862 case ISD::SELECT_CC:
2863 return LowerSELECT_CC(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002864 }
2865
Dan Gohman475871a2008-07-27 21:46:04 +00002866 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002867}
2868
Duncan Sands1607f052008-12-01 11:39:25 +00002869void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
2870 SmallVectorImpl<SDValue>&Results,
2871 SelectionDAG &DAG)
Scott Michel73ce1c52008-11-10 23:43:06 +00002872{
2873#if 0
2874 unsigned Opc = (unsigned) N->getOpcode();
2875 MVT OpVT = N->getValueType(0);
2876
2877 switch (Opc) {
2878 default: {
2879 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2880 cerr << "Op.getOpcode() = " << Opc << "\n";
2881 cerr << "*Op.getNode():\n";
2882 N->dump();
2883 abort();
2884 /*NOTREACHED*/
2885 }
2886 }
2887#endif
2888
2889 /* Otherwise, return unchanged */
Scott Michel73ce1c52008-11-10 23:43:06 +00002890}
2891
Scott Michel266bc8f2007-12-04 22:23:35 +00002892//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002893// Target Optimization Hooks
2894//===----------------------------------------------------------------------===//
2895
Dan Gohman475871a2008-07-27 21:46:04 +00002896SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002897SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2898{
2899#if 0
2900 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002901#endif
2902 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002903 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002904 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2905 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002906
2907 switch (N->getOpcode()) {
2908 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002909 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002910 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002911
Scott Michel8bf61e82008-06-02 22:18:03 +00002912 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002913 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002914 if (Op01.getOpcode() == ISD::Constant
2915 || Op01.getOpcode() == ISD::TargetConstant) {
2916 // (add <const>, (SPUindirect <arg>, <const>)) ->
2917 // (SPUindirect <arg>, <const + const>)
2918 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2919 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002920 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002921 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002922 Op0.getValueType());
2923
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002924 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2925 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002926 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002927 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002928 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2929 Op0.getOperand(0), combinedConst);
2930 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002931 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002932 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002933 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002934 if (Op11.getOpcode() == ISD::Constant
2935 || Op11.getOpcode() == ISD::TargetConstant) {
2936 // (add (SPUindirect <arg>, <const>), <const>) ->
2937 // (SPUindirect <arg>, <const + const>)
2938 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2939 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002940 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002941 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002942 Op0.getValueType());
2943
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002944 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2945 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002946 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002947 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002948
2949 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2950 Op1.getOperand(0), combinedConst);
2951 }
2952 }
Scott Michela59d4692008-02-23 18:41:37 +00002953 break;
2954 }
2955 case ISD::SIGN_EXTEND:
2956 case ISD::ZERO_EXTEND:
2957 case ISD::ANY_EXTEND: {
Scott Michel104de432008-11-24 17:11:17 +00002958 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT &&
Scott Michela59d4692008-02-23 18:41:37 +00002959 N->getValueType(0) == Op0.getValueType()) {
2960 // (any_extend (SPUextract_elt0 <arg>)) ->
2961 // (SPUextract_elt0 <arg>)
2962 // Types must match, however...
2963 DEBUG(cerr << "Replace: ");
2964 DEBUG(N->dump(&DAG));
2965 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002966 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002967 DEBUG(cerr << "\n");
2968
2969 return Op0;
2970 }
2971 break;
2972 }
2973 case SPUISD::IndirectAddr: {
2974 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2975 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002976 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002977 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2978 // (SPUaform <addr>, 0)
2979
2980 DEBUG(cerr << "Replace: ");
2981 DEBUG(N->dump(&DAG));
2982 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002983 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002984 DEBUG(cerr << "\n");
2985
2986 return Op0;
2987 }
2988 }
2989 break;
2990 }
2991 case SPUISD::SHLQUAD_L_BITS:
2992 case SPUISD::SHLQUAD_L_BYTES:
2993 case SPUISD::VEC_SHL:
2994 case SPUISD::VEC_SRL:
2995 case SPUISD::VEC_SRA:
2996 case SPUISD::ROTQUAD_RZ_BYTES:
2997 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002998 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002999
3000 if (isa<ConstantSDNode>(Op1)) {
3001 // Kill degenerate vector shifts:
3002 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
3003
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00003004 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00003005 Result = Op0;
3006 }
3007 }
3008 break;
3009 }
3010 case SPUISD::PROMOTE_SCALAR: {
3011 switch (Op0.getOpcode()) {
3012 default:
3013 break;
3014 case ISD::ANY_EXTEND:
3015 case ISD::ZERO_EXTEND:
3016 case ISD::SIGN_EXTEND: {
3017 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
3018 // <arg>
3019 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00003020 SDValue Op00 = Op0.getOperand(0);
Scott Michel104de432008-11-24 17:11:17 +00003021 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman475871a2008-07-27 21:46:04 +00003022 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00003023 if (Op000.getValueType() == N->getValueType(0)) {
3024 Result = Op000;
3025 }
3026 }
3027 break;
3028 }
Scott Michel104de432008-11-24 17:11:17 +00003029 case SPUISD::VEC2PREFSLOT: {
Scott Michela59d4692008-02-23 18:41:37 +00003030 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
3031 // <arg>
3032 Result = Op0.getOperand(0);
3033 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003034 }
Scott Michela59d4692008-02-23 18:41:37 +00003035 }
3036 break;
Scott Michel053c1da2008-01-29 02:16:57 +00003037 }
3038 }
Scott Michel58c58182008-01-17 20:38:41 +00003039 // Otherwise, return unchanged.
Scott Michel9c0c6b22008-11-21 02:56:16 +00003040#ifdef NDEBUG
Gabor Greifba36cb52008-08-28 21:40:38 +00003041 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00003042 DEBUG(cerr << "\nReplace.SPU: ");
3043 DEBUG(N->dump(&DAG));
3044 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00003045 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00003046 DEBUG(cerr << "\n");
3047 }
3048#endif
3049
3050 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00003051}
3052
3053//===----------------------------------------------------------------------===//
3054// Inline Assembly Support
3055//===----------------------------------------------------------------------===//
3056
3057/// getConstraintType - Given a constraint letter, return the type of
3058/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00003059SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00003060SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3061 if (ConstraintLetter.size() == 1) {
3062 switch (ConstraintLetter[0]) {
3063 default: break;
3064 case 'b':
3065 case 'r':
3066 case 'f':
3067 case 'v':
3068 case 'y':
3069 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003070 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003071 }
3072 return TargetLowering::getConstraintType(ConstraintLetter);
3073}
3074
Scott Michel5af8f0e2008-07-16 17:17:29 +00003075std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00003076SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00003077 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00003078{
3079 if (Constraint.size() == 1) {
3080 // GCC RS6000 Constraint Letters
3081 switch (Constraint[0]) {
3082 case 'b': // R1-R31
3083 case 'r': // R0-R31
3084 if (VT == MVT::i64)
3085 return std::make_pair(0U, SPU::R64CRegisterClass);
3086 return std::make_pair(0U, SPU::R32CRegisterClass);
3087 case 'f':
3088 if (VT == MVT::f32)
3089 return std::make_pair(0U, SPU::R32FPRegisterClass);
3090 else if (VT == MVT::f64)
3091 return std::make_pair(0U, SPU::R64FPRegisterClass);
3092 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003093 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00003094 return std::make_pair(0U, SPU::GPRCRegisterClass);
3095 }
3096 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003097
Scott Michel266bc8f2007-12-04 22:23:35 +00003098 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3099}
3100
Scott Michela59d4692008-02-23 18:41:37 +00003101//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00003102void
Dan Gohman475871a2008-07-27 21:46:04 +00003103SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00003104 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00003105 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00003106 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00003107 const SelectionDAG &DAG,
3108 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00003109#if 0
Scott Michela59d4692008-02-23 18:41:37 +00003110 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00003111#endif
Scott Michela59d4692008-02-23 18:41:37 +00003112
3113 switch (Op.getOpcode()) {
3114 default:
3115 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3116 break;
3117
3118#if 0
3119 case CALL:
3120 case SHUFB:
Scott Michel7a1c9e92008-11-22 23:50:42 +00003121 case SHUFFLE_MASK:
Scott Michela59d4692008-02-23 18:41:37 +00003122 case CNTB:
3123#endif
3124
3125 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00003126 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00003127 MVT Op0VT = Op0.getValueType();
3128 unsigned Op0VTBits = Op0VT.getSizeInBits();
3129 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003130 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3131 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003132 break;
3133 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003134
Scott Michela59d4692008-02-23 18:41:37 +00003135 case SPUISD::LDRESULT:
Scott Michel104de432008-11-24 17:11:17 +00003136 case SPUISD::VEC2PREFSLOT:
3137 case SPUISD::VEC2PREFSLOT_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00003138 MVT OpVT = Op.getValueType();
3139 unsigned OpVTBits = OpVT.getSizeInBits();
3140 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003141 KnownZero |= APInt(OpVTBits, ~InMask, false);
3142 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003143 break;
3144 }
3145
3146#if 0
3147 case EXTRACT_I1_ZEXT:
3148 case EXTRACT_I1_SEXT:
3149 case EXTRACT_I8_ZEXT:
3150 case EXTRACT_I8_SEXT:
3151 case MPY:
3152 case MPYU:
3153 case MPYH:
3154 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003155 case SPUISD::SHLQUAD_L_BITS:
3156 case SPUISD::SHLQUAD_L_BYTES:
3157 case SPUISD::VEC_SHL:
3158 case SPUISD::VEC_SRL:
3159 case SPUISD::VEC_SRA:
3160 case SPUISD::VEC_ROTL:
3161 case SPUISD::VEC_ROTR:
3162 case SPUISD::ROTQUAD_RZ_BYTES:
3163 case SPUISD::ROTQUAD_RZ_BITS:
Scott Michel203b2d62008-04-30 00:30:08 +00003164 case SPUISD::ROTBYTES_LEFT:
3165 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003166 case SPUISD::SELECT_MASK:
3167 case SPUISD::SELB:
3168 case SPUISD::FPInterp:
3169 case SPUISD::FPRecipEst:
3170 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003171#endif
3172 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003173}
3174
Scott Michel203b2d62008-04-30 00:30:08 +00003175// LowerAsmOperandForConstraint
3176void
Dan Gohman475871a2008-07-27 21:46:04 +00003177SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003178 char ConstraintLetter,
Evan Chengda43bcf2008-09-24 00:05:32 +00003179 bool hasMemory,
Dan Gohman475871a2008-07-27 21:46:04 +00003180 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003181 SelectionDAG &DAG) const {
3182 // Default, for the time being, to the base class handler
Evan Chengda43bcf2008-09-24 00:05:32 +00003183 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3184 Ops, DAG);
Scott Michel203b2d62008-04-30 00:30:08 +00003185}
3186
Scott Michel266bc8f2007-12-04 22:23:35 +00003187/// isLegalAddressImmediate - Return true if the integer value can be used
3188/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003189bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3190 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003191 // SPU's addresses are 256K:
3192 return (V > -(1 << 18) && V < (1 << 18) - 1);
3193}
3194
3195bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003196 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003197}
Dan Gohman6520e202008-10-18 02:06:02 +00003198
3199bool
3200SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3201 // The SPU target isn't yet aware of offsets.
3202 return false;
3203}