blob: eec428bbabfc0eb60626d09546f36ee4d84b6fd1 [file] [log] [blame]
Scott Michel266bc8f2007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel266bc8f2007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SPUTargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPURegisterNames.h"
15#include "SPUISelLowering.h"
16#include "SPUTargetMachine.h"
Scott Michel203b2d62008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000018#include "llvm/ADT/VectorExtras.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000019#include "llvm/CodeGen/CallingConvLower.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner84bc5422007-12-31 04:13:23 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000025#include "llvm/Constants.h"
26#include "llvm/Function.h"
27#include "llvm/Intrinsics.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/MathExtras.h"
30#include "llvm/Target/TargetOptions.h"
31
32#include <map>
33
34using namespace llvm;
35
36// Used in getTargetNodeName() below
37namespace {
38 std::map<unsigned, const char *> node_names;
39
Duncan Sands83ec4b62008-06-06 12:08:01 +000040 //! MVT mapping to useful data for Cell SPU
Scott Michel266bc8f2007-12-04 22:23:35 +000041 struct valtype_map_s {
Duncan Sands83ec4b62008-06-06 12:08:01 +000042 const MVT valtype;
Scott Michel7f9ba9b2008-01-30 02:55:46 +000043 const int prefslot_byte;
Scott Michel266bc8f2007-12-04 22:23:35 +000044 };
Scott Michel5af8f0e2008-07-16 17:17:29 +000045
Scott Michel266bc8f2007-12-04 22:23:35 +000046 const valtype_map_s valtype_map[] = {
47 { MVT::i1, 3 },
48 { MVT::i8, 3 },
49 { MVT::i16, 2 },
50 { MVT::i32, 0 },
51 { MVT::f32, 0 },
52 { MVT::i64, 0 },
53 { MVT::f64, 0 },
54 { MVT::i128, 0 }
55 };
56
57 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
58
Duncan Sands83ec4b62008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel266bc8f2007-12-04 22:23:35 +000060 const valtype_map_s *retval = 0;
61
62 for (size_t i = 0; i < n_valtype_map; ++i) {
63 if (valtype_map[i].valtype == VT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel266bc8f2007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands83ec4b62008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +000074 abort();
75 }
76#endif
77
78 return retval;
79 }
80
81 //! Predicate that returns true if operand is a memory target
82 /*!
83 \arg Op Operand to test
84 \return true if the operand is a memory target (i.e., global
Scott Michel9de5d0d2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel266bc8f2007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman475871a2008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel266bc8f2007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
95 || Opc == ISD::ExternalSymbol
96 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
100 || Opc == ISD::TargetExternalSymbol
Scott Michel9de5d0d2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000102 }
Scott Michel58c58182008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman475871a2008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel58c58182008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel58c58182008-01-17 20:38:41 +0000110 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000111}
112
113SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
114 : TargetLowering(TM),
115 SPUTM(TM)
116{
117 // Fold away setcc operations if possible.
118 setPow2DivIsCheap();
119
120 // Use _setjmp/_longjmp instead of setjmp/longjmp.
121 setUseUnderscoreSetJmp(true);
122 setUseUnderscoreLongJmp(true);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000123
Scott Michel266bc8f2007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel504c3692007-12-17 22:32:34 +0000125 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
126 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
127 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
128 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
129 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
130 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel266bc8f2007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000132
Scott Michel266bc8f2007-12-04 22:23:35 +0000133 // SPU has no sign or zero extended loads for i1, i8, i16:
Scott Michel58c58182008-01-17 20:38:41 +0000134 setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +0000135 setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote);
136 setLoadXAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Chris Lattnerddf89562008-01-17 19:59:44 +0000137 setTruncStoreAction(MVT::i8, MVT::i1, Custom);
138 setTruncStoreAction(MVT::i16, MVT::i1, Custom);
139 setTruncStoreAction(MVT::i32, MVT::i1, Custom);
140 setTruncStoreAction(MVT::i64, MVT::i1, Custom);
141 setTruncStoreAction(MVT::i128, MVT::i1, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000142
143 setLoadXAction(ISD::EXTLOAD, MVT::i8, Custom);
144 setLoadXAction(ISD::SEXTLOAD, MVT::i8, Custom);
145 setLoadXAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Chris Lattnerddf89562008-01-17 19:59:44 +0000146 setTruncStoreAction(MVT::i8 , MVT::i8, Custom);
147 setTruncStoreAction(MVT::i16 , MVT::i8, Custom);
148 setTruncStoreAction(MVT::i32 , MVT::i8, Custom);
149 setTruncStoreAction(MVT::i64 , MVT::i8, Custom);
150 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000151
Scott Michel266bc8f2007-12-04 22:23:35 +0000152 setLoadXAction(ISD::EXTLOAD, MVT::i16, Custom);
153 setLoadXAction(ISD::SEXTLOAD, MVT::i16, Custom);
154 setLoadXAction(ISD::ZEXTLOAD, MVT::i16, Custom);
155
156 // SPU constant load actions are custom lowered:
157 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begemanccef5802008-02-14 18:43:04 +0000158 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000159 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
160
161 // SPU's loads and stores have to be custom lowered:
162 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
163 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000164 MVT VT = (MVT::SimpleValueType)sctype;
165
166 setOperationAction(ISD::LOAD, VT, Custom);
167 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000168 }
169
Scott Michel58c58182008-01-17 20:38:41 +0000170 // Custom lower BRCOND for i1, i8 to "promote" the result to
171 // i32 and i16, respectively.
172 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000173
174 // Expand the jumptable branches
175 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
176 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000177 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000178
179 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000180 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
181
Scott Michel266bc8f2007-12-04 22:23:35 +0000182 // PowerPC has no SREM/UREM instructions
183 setOperationAction(ISD::SREM, MVT::i32, Expand);
184 setOperationAction(ISD::UREM, MVT::i32, Expand);
185 setOperationAction(ISD::SREM, MVT::i64, Expand);
186 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000187
Scott Michel266bc8f2007-12-04 22:23:35 +0000188 // We don't support sin/cos/sqrt/fmod
189 setOperationAction(ISD::FSIN , MVT::f64, Expand);
190 setOperationAction(ISD::FCOS , MVT::f64, Expand);
191 setOperationAction(ISD::FREM , MVT::f64, Expand);
Dale Johannesen7794f2a2008-09-04 00:47:13 +0000192 setOperationAction(ISD::FLOG , MVT::f64, Expand);
193 setOperationAction(ISD::FLOG2, MVT::f64, Expand);
194 setOperationAction(ISD::FLOG10,MVT::f64, Expand);
195 setOperationAction(ISD::FEXP , MVT::f64, Expand);
196 setOperationAction(ISD::FEXP2, MVT::f64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000197 setOperationAction(ISD::FSIN , MVT::f32, Expand);
198 setOperationAction(ISD::FCOS , MVT::f32, Expand);
199 setOperationAction(ISD::FREM , MVT::f32, Expand);
Dale Johannesen7794f2a2008-09-04 00:47:13 +0000200 setOperationAction(ISD::FLOG , MVT::f32, Expand);
201 setOperationAction(ISD::FLOG2, MVT::f32, Expand);
202 setOperationAction(ISD::FLOG10,MVT::f32, Expand);
203 setOperationAction(ISD::FEXP , MVT::f32, Expand);
204 setOperationAction(ISD::FEXP2, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000205
Scott Michel266bc8f2007-12-04 22:23:35 +0000206 // If we're enabling GP optimizations, use hardware square root
207 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
208 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000209
Scott Michel266bc8f2007-12-04 22:23:35 +0000210 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
211 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
212
213 // SPU can do rotate right and left, so legalize it... but customize for i8
214 // because instructions don't exist.
Bill Wendling9440e352008-08-31 02:59:23 +0000215
216 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
217 // .td files.
218 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
219 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
220 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
221
Scott Michel266bc8f2007-12-04 22:23:35 +0000222 setOperationAction(ISD::ROTL, MVT::i32, Legal);
223 setOperationAction(ISD::ROTL, MVT::i16, Legal);
224 setOperationAction(ISD::ROTL, MVT::i8, Custom);
225 // SPU has no native version of shift left/right for i8
226 setOperationAction(ISD::SHL, MVT::i8, Custom);
227 setOperationAction(ISD::SRL, MVT::i8, Custom);
228 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michela59d4692008-02-23 18:41:37 +0000229 // And SPU needs custom lowering for shift left/right for i64
230 setOperationAction(ISD::SHL, MVT::i64, Custom);
231 setOperationAction(ISD::SRL, MVT::i64, Custom);
232 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000233
Scott Michel5af8f0e2008-07-16 17:17:29 +0000234 // Custom lower i8, i32 and i64 multiplications
235 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000236 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000237 setOperationAction(ISD::MUL, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000238
Scott Michel8bf61e82008-06-02 22:18:03 +0000239 // Need to custom handle (some) common i8, i64 math ops
240 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000241 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel8bf61e82008-06-02 22:18:03 +0000242 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000243
Scott Michel266bc8f2007-12-04 22:23:35 +0000244 // SPU does not have BSWAP. It does have i32 support CTLZ.
245 // CTPOP has to be custom lowered.
246 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
247 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
248
249 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
250 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
251 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
252 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
253
254 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
255 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
256
257 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000258
Scott Michel8bf61e82008-06-02 22:18:03 +0000259 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000260 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000261 setOperationAction(ISD::SELECT, MVT::i1, Promote);
262 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000263 setOperationAction(ISD::SELECT, MVT::i16, Legal);
264 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000265 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000266
Scott Michel78c47fa2008-03-10 16:58:52 +0000267 setOperationAction(ISD::SETCC, MVT::i1, Promote);
268 setOperationAction(ISD::SETCC, MVT::i8, Legal);
269 setOperationAction(ISD::SETCC, MVT::i16, Legal);
270 setOperationAction(ISD::SETCC, MVT::i32, Legal);
271 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michelad2715e2008-03-05 23:02:02 +0000272
Scott Michela59d4692008-02-23 18:41:37 +0000273 // Zero extension and sign extension for i64 have to be
274 // custom legalized
275 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
276 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
277 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000278
Scott Michel266bc8f2007-12-04 22:23:35 +0000279 // SPU has a legal FP -> signed INT instruction
280 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
281 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
282 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
283 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
284
285 // FDIV on SPU requires custom lowering
286 setOperationAction(ISD::FDIV, MVT::f32, Custom);
287 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
288
289 // SPU has [U|S]INT_TO_FP
290 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
291 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
292 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
293 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
294 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
295 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
296 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
297 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
298
Scott Michel86c041f2007-12-20 00:44:13 +0000299 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
300 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
301 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
302 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000303
304 // We cannot sextinreg(i1). Expand to shifts.
305 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000306
Scott Michel266bc8f2007-12-04 22:23:35 +0000307 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000308 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000309 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000310
311 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000312 // appropriate instructions to materialize the address.
Scott Michel053c1da2008-01-29 02:16:57 +0000313 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
314 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000315 MVT VT = (MVT::SimpleValueType)sctype;
316
317 setOperationAction(ISD::GlobalAddress, VT, Custom);
318 setOperationAction(ISD::ConstantPool, VT, Custom);
319 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000320 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000321
322 // RET must be custom lowered, to meet ABI requirements
323 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000324
Scott Michel266bc8f2007-12-04 22:23:35 +0000325 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
326 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000327
Scott Michel266bc8f2007-12-04 22:23:35 +0000328 // Use the default implementation.
329 setOperationAction(ISD::VAARG , MVT::Other, Expand);
330 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
331 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000332 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000333 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
334 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
335 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
336
337 // Cell SPU has instructions for converting between i64 and fp.
338 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
339 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000340
Scott Michel266bc8f2007-12-04 22:23:35 +0000341 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
342 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
343
344 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
345 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
346
347 // First set operation action for all vector types to expand. Then we
348 // will selectively turn on ones that can be effectively codegen'd.
349 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
350 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
351 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
352 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
353 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
354 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
355
Duncan Sands83ec4b62008-06-06 12:08:01 +0000356 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
357 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
358 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000359
Duncan Sands83ec4b62008-06-06 12:08:01 +0000360 // add/sub are legal for all supported vector VT's.
361 setOperationAction(ISD::ADD , VT, Legal);
362 setOperationAction(ISD::SUB , VT, Legal);
363 // mul has to be custom lowered.
364 setOperationAction(ISD::MUL , VT, Custom);
365
366 setOperationAction(ISD::AND , VT, Legal);
367 setOperationAction(ISD::OR , VT, Legal);
368 setOperationAction(ISD::XOR , VT, Legal);
369 setOperationAction(ISD::LOAD , VT, Legal);
370 setOperationAction(ISD::SELECT, VT, Legal);
371 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000372
Scott Michel266bc8f2007-12-04 22:23:35 +0000373 // These operations need to be expanded:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000374 setOperationAction(ISD::SDIV, VT, Expand);
375 setOperationAction(ISD::SREM, VT, Expand);
376 setOperationAction(ISD::UDIV, VT, Expand);
377 setOperationAction(ISD::UREM, VT, Expand);
378 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000379
380 // Custom lower build_vector, constant pool spills, insert and
381 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000382 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
383 setOperationAction(ISD::ConstantPool, VT, Custom);
384 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
385 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
386 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
387 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000388 }
389
390 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
391 setOperationAction(ISD::AND, MVT::v16i8, Custom);
392 setOperationAction(ISD::OR, MVT::v16i8, Custom);
393 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
394 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000395
Scott Michel266bc8f2007-12-04 22:23:35 +0000396 setShiftAmountType(MVT::i32);
397 setSetCCResultContents(ZeroOrOneSetCCResult);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000398
Scott Michel266bc8f2007-12-04 22:23:35 +0000399 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000400
Scott Michel266bc8f2007-12-04 22:23:35 +0000401 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000402 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000403 setTargetDAGCombine(ISD::ZERO_EXTEND);
404 setTargetDAGCombine(ISD::SIGN_EXTEND);
405 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000406
Scott Michel266bc8f2007-12-04 22:23:35 +0000407 computeRegisterProperties();
408}
409
410const char *
411SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
412{
413 if (node_names.empty()) {
414 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
415 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
416 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
417 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000418 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000419 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000420 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
421 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
422 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
423 node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
424 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
425 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
426 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
Gabor Greif93c53e52008-08-31 15:37:04 +0000427 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED]
428 = "SPUISD::EXTRACT_ELT0_CHAINED";
Scott Michel266bc8f2007-12-04 22:23:35 +0000429 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
430 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
431 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
432 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
433 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
434 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
435 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
436 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michela59d4692008-02-23 18:41:37 +0000437 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
438 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000439 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
440 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
441 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
442 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
443 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michela59d4692008-02-23 18:41:37 +0000444 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
445 "SPUISD::ROTQUAD_RZ_BYTES";
446 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
447 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel266bc8f2007-12-04 22:23:35 +0000448 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
449 "SPUISD::ROTBYTES_RIGHT_S";
450 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
451 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
452 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel8bf61e82008-06-02 22:18:03 +0000453 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
454 "SPUISD::ROTBYTES_LEFT_BITS";
455 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000456 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000457 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
458 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
459 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
460 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000461 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
462 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
463 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
464 }
465
466 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
467
468 return ((i != node_names.end()) ? i->second : 0);
469}
470
Dan Gohman475871a2008-07-27 21:46:04 +0000471MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000472 MVT VT = Op.getValueType();
473 if (VT.isInteger())
Scott Michel405fba12008-03-10 23:49:09 +0000474 return VT;
475 else
476 return MVT::i32;
Scott Michel78c47fa2008-03-10 16:58:52 +0000477}
478
Scott Michel266bc8f2007-12-04 22:23:35 +0000479//===----------------------------------------------------------------------===//
480// Calling convention code:
481//===----------------------------------------------------------------------===//
482
483#include "SPUGenCallingConv.inc"
484
485//===----------------------------------------------------------------------===//
486// LowerOperation implementation
487//===----------------------------------------------------------------------===//
488
Scott Michel9de5d0d2008-01-11 02:53:15 +0000489/// Aligned load common code for CellSPU
490/*!
491 \param[in] Op The SelectionDAG load or store operand
492 \param[in] DAG The selection DAG
493 \param[in] ST CellSPU subtarget information structure
494 \param[in,out] alignment Caller initializes this to the load or store node's
495 value from getAlignment(), may be updated while generating the aligned load
496 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
497 offset (divisible by 16, modulo 16 == 0)
498 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
499 offset of the preferred slot (modulo 16 != 0)
500 \param[in,out] VT Caller initializes this value type to the the load or store
501 node's loaded or stored value type; may be updated if an i1-extended load or
502 store.
503 \param[out] was16aligned true if the base pointer had 16-byte alignment,
504 otherwise false. Can help to determine if the chunk needs to be rotated.
505
506 Both load and store lowering load a block of data aligned on a 16-byte
507 boundary. This is the common aligned load code shared between both.
508 */
Dan Gohman475871a2008-07-27 21:46:04 +0000509static SDValue
510AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Michel9de5d0d2008-01-11 02:53:15 +0000511 LSBaseSDNode *LSN,
512 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000513 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000514{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000515 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000516 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman475871a2008-07-27 21:46:04 +0000517 SDValue basePtr = LSN->getBasePtr();
518 SDValue chain = LSN->getChain();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000519
520 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000521 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000522
Gabor Greif93c53e52008-08-31 15:37:04 +0000523 if (Op1.getOpcode() == ISD::Constant
524 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000525 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000526
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000527 alignOffs = (int) CN->getZExtValue();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000528 prefSlotOffs = (int) (alignOffs & 0xf);
529
530 // Adjust the rotation amount to ensure that the final result ends up in
531 // the preferred slot:
532 prefSlotOffs -= vtm->prefslot_byte;
533 basePtr = basePtr.getOperand(0);
534
Scott Michel58c58182008-01-17 20:38:41 +0000535 // Loading from memory, can we adjust alignment?
536 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +0000537 SDValue APtr = basePtr.getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000538 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
539 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
540 alignment = GSDN->getGlobal()->getAlignment();
541 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000542 }
543 } else {
544 alignOffs = 0;
545 prefSlotOffs = -vtm->prefslot_byte;
546 }
Scott Michel203b2d62008-04-30 00:30:08 +0000547 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
548 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
549 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
550 prefSlotOffs = (int) (alignOffs & 0xf);
551 prefSlotOffs -= vtm->prefslot_byte;
552 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000553 } else {
554 alignOffs = 0;
555 prefSlotOffs = -vtm->prefslot_byte;
556 }
557
558 if (alignment == 16) {
559 // Realign the base pointer as a D-Form address:
560 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000561 basePtr = DAG.getNode(ISD::ADD, PtrVT,
562 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000563 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000564 }
565
566 // Emit the vector load:
567 was16aligned = true;
568 return DAG.getLoad(MVT::v16i8, chain, basePtr,
569 LSN->getSrcValue(), LSN->getSrcValueOffset(),
570 LSN->isVolatile(), 16);
571 }
572
573 // Unaligned load or we're using the "large memory" model, which means that
574 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000575 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greif93c53e52008-08-31 15:37:04 +0000576 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
577 DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000578 }
579
580 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000581 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000582 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000583 was16aligned = false;
584 return DAG.getLoad(MVT::v16i8, chain, basePtr,
585 LSN->getSrcValue(), LSN->getSrcValueOffset(),
586 LSN->isVolatile(), 16);
587}
588
Scott Michel266bc8f2007-12-04 22:23:35 +0000589/// Custom lower loads for CellSPU
590/*!
591 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
592 within a 16-byte block, we have to rotate to extract the requested element.
593 */
Dan Gohman475871a2008-07-27 21:46:04 +0000594static SDValue
595LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000596 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000597 SDValue the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000598 MVT VT = LN->getMemoryVT();
Gabor Greifba36cb52008-08-28 21:40:38 +0000599 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000600 ISD::LoadExtType ExtType = LN->getExtensionType();
601 unsigned alignment = LN->getAlignment();
Dan Gohman475871a2008-07-27 21:46:04 +0000602 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000603
Scott Michel266bc8f2007-12-04 22:23:35 +0000604 switch (LN->getAddressingMode()) {
605 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000606 int offset, rotamt;
607 bool was16aligned;
Dan Gohman475871a2008-07-27 21:46:04 +0000608 SDValue result =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000609 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000610
Gabor Greifba36cb52008-08-28 21:40:38 +0000611 if (result.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000612 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000613
614 the_chain = result.getValue(1);
615 // Rotate the chunk if necessary
616 if (rotamt < 0)
617 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000618 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000619 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
620
Scott Michel58c58182008-01-17 20:38:41 +0000621 Ops[0] = the_chain;
622 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000623 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000624 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
625 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000626 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000627 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000628 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000629 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000630 }
631
632 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
633 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000634 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000635
636 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
637 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000638 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000639
Scott Michel9de5d0d2008-01-11 02:53:15 +0000640 // Convert the loaded v16i8 vector to the appropriate vector type
641 // specified by the operand:
642 if (OpVT == VT) {
643 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000644 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000645 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000646 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000647
648 Ops[0] = the_chain;
649 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
650 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
651 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
652 the_chain = result.getValue(1);
653 } else {
654 // Handle the sign and zero-extending loads for i1 and i8:
655 unsigned NewOpC;
656
657 if (ExtType == ISD::SEXTLOAD) {
658 NewOpC = (OpVT == MVT::i1
659 ? SPUISD::EXTRACT_I1_SEXT
660 : SPUISD::EXTRACT_I8_SEXT);
661 } else {
662 assert(ExtType == ISD::ZEXTLOAD);
663 NewOpC = (OpVT == MVT::i1
664 ? SPUISD::EXTRACT_I1_ZEXT
665 : SPUISD::EXTRACT_I8_ZEXT);
666 }
667
668 result = DAG.getNode(NewOpC, OpVT, result);
669 }
670
671 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000672 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000673 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000674 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000675 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000676
Scott Michel58c58182008-01-17 20:38:41 +0000677 result = DAG.getNode(SPUISD::LDRESULT, retvts,
678 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000679 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000680 }
681 case ISD::PRE_INC:
682 case ISD::PRE_DEC:
683 case ISD::POST_INC:
684 case ISD::POST_DEC:
685 case ISD::LAST_INDEXED_MODE:
686 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
687 "UNINDEXED\n";
688 cerr << (unsigned) LN->getAddressingMode() << "\n";
689 abort();
690 /*NOTREACHED*/
691 }
692
Dan Gohman475871a2008-07-27 21:46:04 +0000693 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000694}
695
696/// Custom lower stores for CellSPU
697/*!
698 All CellSPU stores are aligned to 16-byte boundaries, so for elements
699 within a 16-byte block, we have to generate a shuffle to insert the
700 requested element into its place, then store the resulting block.
701 */
Dan Gohman475871a2008-07-27 21:46:04 +0000702static SDValue
703LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000704 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000705 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000706 MVT VT = Value.getValueType();
707 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
708 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000709 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000710
711 switch (SN->getAddressingMode()) {
712 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000713 int chunk_offset, slot_offset;
714 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000715
716 // The vector type we really want to load from the 16-byte chunk, except
717 // in the case of MVT::i1, which has to be v16i8.
Duncan Sands83ec4b62008-06-06 12:08:01 +0000718 MVT vecVT, stVecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000719
Scott Michel266bc8f2007-12-04 22:23:35 +0000720 if (StVT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000721 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
722 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000723
Dan Gohman475871a2008-07-27 21:46:04 +0000724 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000725 AlignedLoad(Op, DAG, ST, SN, alignment,
726 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000727
Gabor Greifba36cb52008-08-28 21:40:38 +0000728 if (alignLoadVec.getNode() == 0)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000729 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000730
Scott Michel9de5d0d2008-01-11 02:53:15 +0000731 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000732 SDValue basePtr = LN->getBasePtr();
733 SDValue the_chain = alignLoadVec.getValue(1);
734 SDValue theValue = SN->getValue();
735 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000736
737 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000738 && (theValue.getOpcode() == ISD::AssertZext
739 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000740 // Drill down and get the value for zero- and sign-extended
741 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000742 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000743 }
744
Scott Michel9de5d0d2008-01-11 02:53:15 +0000745 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000746
Dan Gohman475871a2008-07-27 21:46:04 +0000747 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
748 SDValue insertEltPtr;
749 SDValue insertEltOp;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000750
751 // If the base pointer is already a D-form address, then just create
752 // a new D-form address with a slot offset and the orignal base pointer.
753 // Otherwise generate a D-form address with the slot offset relative
754 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000755 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greifba36cb52008-08-28 21:40:38 +0000756 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michel497e8882008-01-11 21:01:19 +0000757 DEBUG(cerr << "\n");
758
Scott Michel053c1da2008-01-29 02:16:57 +0000759 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
760 (basePtr.getOpcode() == ISD::ADD
761 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000762 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000763 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000764 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000765 }
766
767 insertEltOp = DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000768 result = DAG.getNode(SPUISD::SHUFB, vecVT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000769 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue),
770 alignLoadVec,
771 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000772
Scott Michel9de5d0d2008-01-11 02:53:15 +0000773 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000774 LN->getSrcValue(), LN->getSrcValueOffset(),
775 LN->isVolatile(), LN->getAlignment());
776
777 return result;
778 /*UNREACHED*/
779 }
780 case ISD::PRE_INC:
781 case ISD::PRE_DEC:
782 case ISD::POST_INC:
783 case ISD::POST_DEC:
784 case ISD::LAST_INDEXED_MODE:
785 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
786 "UNINDEXED\n";
787 cerr << (unsigned) SN->getAddressingMode() << "\n";
788 abort();
789 /*NOTREACHED*/
790 }
791
Dan Gohman475871a2008-07-27 21:46:04 +0000792 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000793}
794
795/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000796static SDValue
797LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000798 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000799 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
800 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000801 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
802 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000803 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000804
805 if (TM.getRelocationModel() == Reloc::Static) {
806 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000807 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000808 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000809 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000810 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
811 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000812 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000813 }
814 }
815
816 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000817 "LowerConstantPool: Relocation model other than static"
818 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000819 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000820}
821
Dan Gohman475871a2008-07-27 21:46:04 +0000822static SDValue
823LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000824 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000825 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000826 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
827 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000828 const TargetMachine &TM = DAG.getTarget();
829
830 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000831 if (!ST->usingLargeMem()) {
832 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
833 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000834 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
835 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000836 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
837 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000838 }
839
840 assert(0 &&
841 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000842 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000843}
844
Dan Gohman475871a2008-07-27 21:46:04 +0000845static SDValue
846LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000847 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000848 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
849 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000850 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000851 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000852 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000853
Scott Michel266bc8f2007-12-04 22:23:35 +0000854 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000855 if (!ST->usingLargeMem()) {
856 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
857 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000858 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
859 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000860 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
861 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000862 } else {
863 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000864 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000865 abort();
866 /*NOTREACHED*/
867 }
868
Dan Gohman475871a2008-07-27 21:46:04 +0000869 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000870}
871
872//! Custom lower i64 integer constants
873/*!
874 This code inserts all of the necessary juggling that needs to occur to load
875 a 64-bit constant into a register.
876 */
Dan Gohman475871a2008-07-27 21:46:04 +0000877static SDValue
878LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000879 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000880 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000881
882 if (VT == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000883 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +0000884 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000885 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000886 } else {
887 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000888 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000889 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000890 abort();
891 /*NOTREACHED*/
892 }
893
Dan Gohman475871a2008-07-27 21:46:04 +0000894 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000895}
896
Nate Begemanccef5802008-02-14 18:43:04 +0000897//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000898static SDValue
899LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000900 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000901 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000902
903 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000904 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000905
Nate Begemanccef5802008-02-14 18:43:04 +0000906 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000907 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000908 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000909 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000910 }
911
Dan Gohman475871a2008-07-27 21:46:04 +0000912 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000913}
914
Scott Michel58c58182008-01-17 20:38:41 +0000915//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000916static SDValue
917LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000918{
Dan Gohman475871a2008-07-27 21:46:04 +0000919 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000920 MVT CondVT = Cond.getValueType();
921 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000922
923 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
924 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
925 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
926 Op.getOperand(0),
927 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
928 Op.getOperand(2));
929 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000930 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000931}
932
Dan Gohman475871a2008-07-27 21:46:04 +0000933static SDValue
934LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000935{
936 MachineFunction &MF = DAG.getMachineFunction();
937 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000938 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +0000939 SmallVector<SDValue, 8> ArgValues;
940 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000941 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000942
943 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
944 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000945
Scott Michel266bc8f2007-12-04 22:23:35 +0000946 unsigned ArgOffset = SPUFrameInfo::minStackSize();
947 unsigned ArgRegIdx = 0;
948 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000949
Duncan Sands83ec4b62008-06-06 12:08:01 +0000950 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000951
Scott Michel266bc8f2007-12-04 22:23:35 +0000952 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000953 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
954 ArgNo != e; ++ArgNo) {
Dan Gohman475871a2008-07-27 21:46:04 +0000955 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000956 bool needsLoad = false;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000957 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
958 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michel266bc8f2007-12-04 22:23:35 +0000959
Duncan Sands83ec4b62008-06-06 12:08:01 +0000960 switch (ObjectVT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000961 default: {
962 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000963 << ObjectVT.getMVTString()
Scott Michel266bc8f2007-12-04 22:23:35 +0000964 << "\n";
965 abort();
966 }
967 case MVT::i8:
968 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000969 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R8CRegClass);
970 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000971 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i8);
972 ++ArgRegIdx;
973 } else {
974 needsLoad = true;
975 }
976 break;
977 case MVT::i16:
978 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000979 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
980 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000981 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i16);
982 ++ArgRegIdx;
983 } else {
984 needsLoad = true;
985 }
986 break;
987 case MVT::i32:
988 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000989 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
990 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000991 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
992 ++ArgRegIdx;
993 } else {
994 needsLoad = true;
995 }
996 break;
997 case MVT::i64:
998 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000999 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64CRegClass);
1000 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001001 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64);
1002 ++ArgRegIdx;
1003 } else {
1004 needsLoad = true;
1005 }
1006 break;
1007 case MVT::f32:
1008 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001009 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
1010 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001011 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f32);
1012 ++ArgRegIdx;
1013 } else {
1014 needsLoad = true;
1015 }
1016 break;
1017 case MVT::f64:
1018 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001019 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64FPRegClass);
1020 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001021 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f64);
1022 ++ArgRegIdx;
1023 } else {
1024 needsLoad = true;
1025 }
1026 break;
1027 case MVT::v2f64:
1028 case MVT::v4f32:
Scott Michelad2715e2008-03-05 23:02:02 +00001029 case MVT::v2i64:
Scott Michel266bc8f2007-12-04 22:23:35 +00001030 case MVT::v4i32:
1031 case MVT::v8i16:
1032 case MVT::v16i8:
1033 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001034 unsigned VReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1035 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001036 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1037 ++ArgRegIdx;
1038 } else {
1039 needsLoad = true;
1040 }
1041 break;
1042 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001043
Scott Michel266bc8f2007-12-04 22:23:35 +00001044 // We need to load the argument to a virtual register if we determined above
1045 // that we ran out of physical registers of the appropriate type
1046 if (needsLoad) {
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001047 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001048 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001049 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001050 ArgOffset += StackSlotSize;
1051 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001052
Scott Michel266bc8f2007-12-04 22:23:35 +00001053 ArgValues.push_back(ArgVal);
1054 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001055
Scott Michel266bc8f2007-12-04 22:23:35 +00001056 // If the function takes variable number of arguments, make a frame index for
1057 // the start of the first vararg value... for expansion of llvm.va_start.
1058 if (isVarArg) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001059 VarArgsFrameIndex = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8,
Scott Michel266bc8f2007-12-04 22:23:35 +00001060 ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001061 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001062 // If this function is vararg, store any remaining integer argument regs to
1063 // their spots on the stack so that they may be loaded by deferencing the
1064 // result of va_next.
Dan Gohman475871a2008-07-27 21:46:04 +00001065 SmallVector<SDValue, 8> MemOps;
Scott Michel266bc8f2007-12-04 22:23:35 +00001066 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001067 unsigned VReg = RegInfo.createVirtualRegister(&SPU::GPRCRegClass);
1068 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Dan Gohman475871a2008-07-27 21:46:04 +00001069 SDValue Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
1070 SDValue Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001071 MemOps.push_back(Store);
1072 // Increment the address by four for the next argument to store
Dan Gohman475871a2008-07-27 21:46:04 +00001073 SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001074 FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
1075 }
1076 if (!MemOps.empty())
1077 Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
1078 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001079
Scott Michel266bc8f2007-12-04 22:23:35 +00001080 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001081
Scott Michel266bc8f2007-12-04 22:23:35 +00001082 // Return the new list of results.
Gabor Greifba36cb52008-08-28 21:40:38 +00001083 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf9516202008-06-30 10:19:09 +00001084 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001085}
1086
1087/// isLSAAddress - Return the immediate to use if the specified
1088/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001089static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001090 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
1091 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001092
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001093 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001094 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1095 (Addr << 14 >> 14) != Addr)
1096 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001097
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001098 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001099}
1100
1101static
Dan Gohman475871a2008-07-27 21:46:04 +00001102SDValue
1103LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
1104 SDValue Chain = Op.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001105#if 0
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001106 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
1107 bool isTailCall = cast<ConstantSDNode>(Op.getOperand(3))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +00001108#endif
Dan Gohman475871a2008-07-27 21:46:04 +00001109 SDValue Callee = Op.getOperand(4);
Scott Michel266bc8f2007-12-04 22:23:35 +00001110 unsigned NumOps = (Op.getNumOperands() - 5) / 2;
1111 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1112 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1113 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1114
1115 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001116 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001117
Scott Michel266bc8f2007-12-04 22:23:35 +00001118 // Accumulate how many bytes are to be pushed on the stack, including the
1119 // linkage area, and parameter passing area. According to the SPU ABI,
1120 // we minimally need space for [LR] and [SP]
1121 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001122
Scott Michel266bc8f2007-12-04 22:23:35 +00001123 // Set up a copy of the stack pointer for use loading and storing any
1124 // arguments that may not fit in the registers available for argument
1125 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001126 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001127
Scott Michel266bc8f2007-12-04 22:23:35 +00001128 // Figure out which arguments are going to go in registers, and which in
1129 // memory.
1130 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1131 unsigned ArgRegIdx = 0;
1132
1133 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001134 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001135 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001136 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001137
1138 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001139 SDValue Arg = Op.getOperand(5+2*i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001140
Scott Michel266bc8f2007-12-04 22:23:35 +00001141 // PtrOff will be used to store the current argument to the stack if a
1142 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001143 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001144 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1145
Duncan Sands83ec4b62008-06-06 12:08:01 +00001146 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001147 default: assert(0 && "Unexpected ValueType for argument!");
1148 case MVT::i32:
1149 case MVT::i64:
1150 case MVT::i128:
1151 if (ArgRegIdx != NumArgRegs) {
1152 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1153 } else {
1154 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001155 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001156 }
1157 break;
1158 case MVT::f32:
1159 case MVT::f64:
1160 if (ArgRegIdx != NumArgRegs) {
1161 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1162 } else {
1163 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001164 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001165 }
1166 break;
1167 case MVT::v4f32:
1168 case MVT::v4i32:
1169 case MVT::v8i16:
1170 case MVT::v16i8:
1171 if (ArgRegIdx != NumArgRegs) {
1172 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1173 } else {
1174 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001175 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001176 }
1177 break;
1178 }
1179 }
1180
1181 // Update number of stack bytes actually used, insert a call sequence start
1182 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
1183 Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumStackBytes, PtrVT));
1184
1185 if (!MemOpChains.empty()) {
1186 // Adjust the stack pointer for the stack arguments.
1187 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1188 &MemOpChains[0], MemOpChains.size());
1189 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001190
Scott Michel266bc8f2007-12-04 22:23:35 +00001191 // Build a sequence of copy-to-reg nodes chained together with token chain
1192 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001193 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001194 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1195 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1196 InFlag);
1197 InFlag = Chain.getValue(1);
1198 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001199
Dan Gohman475871a2008-07-27 21:46:04 +00001200 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001201 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001202
Scott Michel266bc8f2007-12-04 22:23:35 +00001203 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1204 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1205 // node so that legalize doesn't hack it.
1206 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1207 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001208 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001209 SDValue Zero = DAG.getConstant(0, PtrVT);
1210 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001211
Scott Michel9de5d0d2008-01-11 02:53:15 +00001212 if (!ST->usingLargeMem()) {
1213 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1214 // style calls, otherwise, external symbols are BRASL calls. This assumes
1215 // that declared/defined symbols are in the same compilation unit and can
1216 // be reached through PC-relative jumps.
1217 //
1218 // NOTE:
1219 // This may be an unsafe assumption for JIT and really large compilation
1220 // units.
1221 if (GV->isDeclaration()) {
1222 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1223 } else {
1224 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1225 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001226 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001227 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1228 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001229 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001230 }
1231 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
1232 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001233 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001234 // If this is an absolute destination address that appears to be a legal
1235 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001236 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001237 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001238
1239 Ops.push_back(Chain);
1240 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001241
Scott Michel266bc8f2007-12-04 22:23:35 +00001242 // Add argument registers to the end of the list so that they are known live
1243 // into the call.
1244 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001245 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001246 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001247
Gabor Greifba36cb52008-08-28 21:40:38 +00001248 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001249 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001250 // Returns a chain and a flag for retval copy to use.
1251 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1252 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001253 InFlag = Chain.getValue(1);
1254
Evan Chengebaaa912008-02-05 22:44:06 +00001255 Chain = DAG.getCALLSEQ_END(Chain,
1256 DAG.getConstant(NumStackBytes, PtrVT),
1257 DAG.getConstant(0, PtrVT),
1258 InFlag);
Gabor Greifba36cb52008-08-28 21:40:38 +00001259 if (Op.getNode()->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001260 InFlag = Chain.getValue(1);
1261
Dan Gohman475871a2008-07-27 21:46:04 +00001262 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001263 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001264
Scott Michel266bc8f2007-12-04 22:23:35 +00001265 // If the call has results, copy the values out of the ret val registers.
Gabor Greifba36cb52008-08-28 21:40:38 +00001266 switch (Op.getNode()->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001267 default: assert(0 && "Unexpected ret value!");
1268 case MVT::Other: break;
1269 case MVT::i32:
Gabor Greifba36cb52008-08-28 21:40:38 +00001270 if (Op.getNode()->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001271 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1272 ResultVals[0] = Chain.getValue(0);
1273 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1274 Chain.getValue(2)).getValue(1);
1275 ResultVals[1] = Chain.getValue(0);
1276 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001277 } else {
1278 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1279 ResultVals[0] = Chain.getValue(0);
1280 NumResults = 1;
1281 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001282 break;
1283 case MVT::i64:
1284 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1285 ResultVals[0] = Chain.getValue(0);
1286 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001287 break;
1288 case MVT::f32:
1289 case MVT::f64:
Gabor Greifba36cb52008-08-28 21:40:38 +00001290 Chain = DAG.getCopyFromReg(Chain, SPU::R3, Op.getNode()->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001291 InFlag).getValue(1);
1292 ResultVals[0] = Chain.getValue(0);
1293 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001294 break;
1295 case MVT::v2f64:
1296 case MVT::v4f32:
1297 case MVT::v4i32:
1298 case MVT::v8i16:
1299 case MVT::v16i8:
Gabor Greifba36cb52008-08-28 21:40:38 +00001300 Chain = DAG.getCopyFromReg(Chain, SPU::R3, Op.getNode()->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001301 InFlag).getValue(1);
1302 ResultVals[0] = Chain.getValue(0);
1303 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001304 break;
1305 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001306
Scott Michel266bc8f2007-12-04 22:23:35 +00001307 // If the function returns void, just return the chain.
1308 if (NumResults == 0)
1309 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001310
Scott Michel266bc8f2007-12-04 22:23:35 +00001311 // Otherwise, merge everything together with a MERGE_VALUES node.
1312 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001313 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001314 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001315}
1316
Dan Gohman475871a2008-07-27 21:46:04 +00001317static SDValue
1318LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001319 SmallVector<CCValAssign, 16> RVLocs;
1320 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1321 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1322 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001323 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001324
Scott Michel266bc8f2007-12-04 22:23:35 +00001325 // If this is the first return lowered for this function, add the regs to the
1326 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001327 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001328 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001329 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001330 }
1331
Dan Gohman475871a2008-07-27 21:46:04 +00001332 SDValue Chain = Op.getOperand(0);
1333 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001334
Scott Michel266bc8f2007-12-04 22:23:35 +00001335 // Copy the result values into the output registers.
1336 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1337 CCValAssign &VA = RVLocs[i];
1338 assert(VA.isRegLoc() && "Can only return in registers!");
1339 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1340 Flag = Chain.getValue(1);
1341 }
1342
Gabor Greifba36cb52008-08-28 21:40:38 +00001343 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001344 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1345 else
1346 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1347}
1348
1349
1350//===----------------------------------------------------------------------===//
1351// Vector related lowering:
1352//===----------------------------------------------------------------------===//
1353
1354static ConstantSDNode *
1355getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001356 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001357
Scott Michel266bc8f2007-12-04 22:23:35 +00001358 // Check to see if this buildvec has a single non-undef value in its elements.
1359 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1360 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001361 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001362 OpVal = N->getOperand(i);
1363 else if (OpVal != N->getOperand(i))
1364 return 0;
1365 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001366
Gabor Greifba36cb52008-08-28 21:40:38 +00001367 if (OpVal.getNode() != 0) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001368 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1369 return CN;
1370 }
1371 }
1372
1373 return 0; // All UNDEF: use implicit def.; not Constant node
1374}
1375
1376/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1377/// and the value fits into an unsigned 18-bit constant, and if so, return the
1378/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001379SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001380 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001381 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001382 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001383 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001384 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001385 uint32_t upper = uint32_t(UValue >> 32);
1386 uint32_t lower = uint32_t(UValue);
1387 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001388 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001389 Value = Value >> 32;
1390 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001391 if (Value <= 0x3ffff)
1392 return DAG.getConstant(Value, ValueType);
1393 }
1394
Dan Gohman475871a2008-07-27 21:46:04 +00001395 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001396}
1397
1398/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1399/// and the value fits into a signed 16-bit constant, and if so, return the
1400/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001401SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001402 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001403 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001404 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001405 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001406 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001407 uint32_t upper = uint32_t(UValue >> 32);
1408 uint32_t lower = uint32_t(UValue);
1409 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001410 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001411 Value = Value >> 32;
1412 }
Scott Michelad2715e2008-03-05 23:02:02 +00001413 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
1414 return DAG.getConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001415 }
1416 }
1417
Dan Gohman475871a2008-07-27 21:46:04 +00001418 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001419}
1420
1421/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1422/// and the value fits into a signed 10-bit constant, and if so, return the
1423/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001424SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001425 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001426 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001427 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001428 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001429 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001430 uint32_t upper = uint32_t(UValue >> 32);
1431 uint32_t lower = uint32_t(UValue);
1432 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001433 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001434 Value = Value >> 32;
1435 }
Scott Michelad2715e2008-03-05 23:02:02 +00001436 if (isS10Constant(Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001437 return DAG.getConstant(Value, ValueType);
1438 }
1439
Dan Gohman475871a2008-07-27 21:46:04 +00001440 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001441}
1442
1443/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1444/// and the value fits into a signed 8-bit constant, and if so, return the
1445/// constant.
1446///
1447/// @note: The incoming vector is v16i8 because that's the only way we can load
1448/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1449/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001450SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001451 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001452 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001453 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001454 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001455 && Value <= 0xffff /* truncated from uint64_t */
1456 && ((short) Value >> 8) == ((short) Value & 0xff))
Scott Michel266bc8f2007-12-04 22:23:35 +00001457 return DAG.getConstant(Value & 0xff, ValueType);
1458 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001459 && (Value & 0xff) == Value)
Scott Michel266bc8f2007-12-04 22:23:35 +00001460 return DAG.getConstant(Value, ValueType);
1461 }
1462
Dan Gohman475871a2008-07-27 21:46:04 +00001463 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001464}
1465
1466/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1467/// and the value fits into a signed 16-bit constant, and if so, return the
1468/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001469SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001470 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001471 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001472 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001473 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001474 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1475 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001476 return DAG.getConstant(Value >> 16, ValueType);
1477 }
1478
Dan Gohman475871a2008-07-27 21:46:04 +00001479 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001480}
1481
1482/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001483SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001484 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001485 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001486 }
1487
Dan Gohman475871a2008-07-27 21:46:04 +00001488 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001489}
1490
1491/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001492SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001493 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001494 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001495 }
1496
Dan Gohman475871a2008-07-27 21:46:04 +00001497 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001498}
1499
1500// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001501// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001502// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1503// zero. Return true if this is not an array of constants, false if it is.
1504//
1505static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1506 uint64_t UndefBits[2]) {
1507 // Start with zero'd results.
1508 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001509
Duncan Sands83ec4b62008-06-06 12:08:01 +00001510 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001511 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001512 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001513
Scott Michel266bc8f2007-12-04 22:23:35 +00001514 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1515 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1516
1517 uint64_t EltBits = 0;
1518 if (OpVal.getOpcode() == ISD::UNDEF) {
1519 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1520 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1521 continue;
1522 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001523 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00001524 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
1525 const APFloat &apf = CN->getValueAPF();
1526 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001527 ? FloatToBits(apf.convertToFloat())
1528 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001529 } else {
1530 // Nonconstant element.
1531 return true;
1532 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001533
Scott Michel266bc8f2007-12-04 22:23:35 +00001534 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1535 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001536
1537 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001538 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1539 return false;
1540}
1541
1542/// If this is a splat (repetition) of a value across the whole vector, return
1543/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001544/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001545/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001546static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001547 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001548 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001549 uint64_t &SplatBits, uint64_t &SplatUndef,
1550 int &SplatSize) {
1551 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1552 // the same as the lower 64-bits, ignoring undefs.
1553 uint64_t Bits64 = Bits128[0] | Bits128[1];
1554 uint64_t Undef64 = Undef128[0] & Undef128[1];
1555 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1556 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1557 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1558 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1559
1560 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1561 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001562
Scott Michel266bc8f2007-12-04 22:23:35 +00001563 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1564 // undefs.
1565 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001566 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001567
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001568 // If the top 16-bits are different than the lower 16-bits, ignoring
1569 // undefs, we have an i32 splat.
1570 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1571 if (MinSplatBits < 16) {
1572 // If the top 8-bits are different than the lower 8-bits, ignoring
1573 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001574 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1575 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001576 // Otherwise, we have an 8-bit splat.
1577 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1578 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1579 SplatSize = 1;
1580 return true;
1581 }
1582 } else {
1583 SplatBits = Bits16;
1584 SplatUndef = Undef16;
1585 SplatSize = 2;
1586 return true;
1587 }
1588 }
1589 } else {
1590 SplatBits = Bits32;
1591 SplatUndef = Undef32;
1592 SplatSize = 4;
1593 return true;
1594 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001595 }
1596 } else {
1597 SplatBits = Bits128[0];
1598 SplatUndef = Undef128[0];
1599 SplatSize = 8;
1600 return true;
1601 }
1602 }
1603
1604 return false; // Can't be a splat if two pieces don't match.
1605}
1606
1607// If this is a case we can't handle, return null and let the default
1608// expansion code take care of it. If we CAN select this case, and if it
1609// selects to a single instruction, return Op. Otherwise, if we can codegen
1610// this case more efficiently than a constant pool load, lower it to the
1611// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001612static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001613 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001614 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001615 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001616 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001617 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001618 uint64_t VectorBits[2];
1619 uint64_t UndefBits[2];
1620 uint64_t SplatBits, SplatUndef;
1621 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001622 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001623 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001624 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001625 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001626 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001627
Duncan Sands83ec4b62008-06-06 12:08:01 +00001628 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001629 default:
1630 case MVT::v4f32: {
1631 uint32_t Value32 = SplatBits;
1632 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001633 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001634 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001635 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001636 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001637 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001638 break;
1639 }
1640 case MVT::v2f64: {
1641 uint64_t f64val = SplatBits;
1642 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001643 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001644 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001645 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001646 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001647 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001648 break;
1649 }
1650 case MVT::v16i8: {
1651 // 8-bit constants have to be expanded to 16-bits
1652 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001653 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001654 for (int i = 0; i < 8; ++i)
1655 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1656 return DAG.getNode(ISD::BIT_CONVERT, VT,
1657 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1658 }
1659 case MVT::v8i16: {
1660 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001661 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001662 Value16 = (unsigned short) (SplatBits & 0xffff);
1663 else
1664 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001665 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1666 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001667 for (int i = 0; i < 8; ++i) Ops[i] = T;
1668 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1669 }
1670 case MVT::v4i32: {
1671 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001672 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001673 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1674 }
1675 case MVT::v2i64: {
1676 uint64_t val = SplatBits;
1677 uint32_t upper = uint32_t(val >> 32);
1678 uint32_t lower = uint32_t(val);
1679
Scott Michel4cb8bd82008-03-06 04:02:54 +00001680 if (upper == lower) {
1681 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001682 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001683 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001684 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001685 SDValue LO32;
1686 SDValue HI32;
1687 SmallVector<SDValue, 16> ShufBytes;
1688 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001689 bool upper_special, lower_special;
1690
1691 // NOTE: This code creates common-case shuffle masks that can be easily
1692 // detected as common expressions. It is not attempting to create highly
1693 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1694
1695 // Detect if the upper or lower half is a special shuffle mask pattern:
1696 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1697 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1698
1699 // Create lower vector if not a special pattern
1700 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001701 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001702 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1703 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1704 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001705 }
1706
1707 // Create upper vector if not a special pattern
1708 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001709 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001710 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1711 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1712 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001713 }
1714
1715 // If either upper or lower are special, then the two input operands are
1716 // the same (basically, one of them is a "don't care")
1717 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001718 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001719 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001720 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001721 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001722 // Unhappy situation... both upper and lower are special, so punt with
1723 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001724 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001725 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001726 Zero, Zero);
1727 }
1728
1729 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001730 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001731 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001732 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001733 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001734 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001735 process_upper = (upper_special && (i & 1) == 0);
1736 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001737
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001738 if (process_upper || process_lower) {
1739 if ((process_upper && upper == 0)
1740 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001741 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001742 else if ((process_upper && upper == 0xffffffff)
1743 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001744 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001745 else if ((process_upper && upper == 0x80000000)
1746 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001747 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001748 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001749 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001750 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001751
1752 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001753 }
1754
1755 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001756 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001757 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001758 }
1759 }
1760 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001761
Dan Gohman475871a2008-07-27 21:46:04 +00001762 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001763}
1764
1765/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1766/// which the Cell can operate. The code inspects V3 to ascertain whether the
1767/// permutation vector, V3, is monotonically increasing with one "exception"
1768/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1769/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1770/// In either case, the net result is going to eventually invoke SHUFB to
1771/// permute/shuffle the bytes from V1 and V2.
1772/// \note
1773/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1774/// control word for byte/halfword/word insertion. This takes care of a single
1775/// element move from V2 into V1.
1776/// \note
1777/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001778static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1779 SDValue V1 = Op.getOperand(0);
1780 SDValue V2 = Op.getOperand(1);
1781 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001782
Scott Michel266bc8f2007-12-04 22:23:35 +00001783 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001784
Scott Michel266bc8f2007-12-04 22:23:35 +00001785 // If we have a single element being moved from V1 to V2, this can be handled
1786 // using the C*[DX] compute mask instructions, but the vector elements have
1787 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001788 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001789 unsigned EltsFromV2 = 0;
1790 unsigned V2Elt = 0;
1791 unsigned V2EltIdx0 = 0;
1792 unsigned CurrElt = 0;
1793 bool monotonic = true;
1794 if (EltVT == MVT::i8)
1795 V2EltIdx0 = 16;
1796 else if (EltVT == MVT::i16)
1797 V2EltIdx0 = 8;
1798 else if (EltVT == MVT::i32)
1799 V2EltIdx0 = 4;
1800 else
1801 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1802
1803 for (unsigned i = 0, e = PermMask.getNumOperands();
1804 EltsFromV2 <= 1 && monotonic && i != e;
1805 ++i) {
1806 unsigned SrcElt;
1807 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1808 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001809 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001810 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001811
1812 if (SrcElt >= V2EltIdx0) {
1813 ++EltsFromV2;
1814 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1815 } else if (CurrElt != SrcElt) {
1816 monotonic = false;
1817 }
1818
1819 ++CurrElt;
1820 }
1821
1822 if (EltsFromV2 == 1 && monotonic) {
1823 // Compute mask and shuffle
1824 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001825 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1826 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001827 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001828 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001829 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001830 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1831 // Copy register's contents as index in INSERT_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001832 SDValue ShufMaskOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001833 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001834 DAG.getTargetConstant(V2Elt, MVT::i32),
1835 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001836 // Use shuffle mask in SHUFB synthetic instruction:
1837 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1838 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001839 // Convert the SHUFFLE_VECTOR mask's input element units to the
1840 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001841 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001842
Dan Gohman475871a2008-07-27 21:46:04 +00001843 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001844 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1845 unsigned SrcElt;
1846 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001847 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001848 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001849 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001850
Scott Michela59d4692008-02-23 18:41:37 +00001851 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001852 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1853 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001854 }
1855 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001856
Dan Gohman475871a2008-07-27 21:46:04 +00001857 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001858 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001859 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1860 }
1861}
1862
Dan Gohman475871a2008-07-27 21:46:04 +00001863static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1864 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001865
Gabor Greifba36cb52008-08-28 21:40:38 +00001866 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001867 // For a constant, build the appropriate constant vector, which will
1868 // eventually simplify to a vector register load.
1869
Gabor Greifba36cb52008-08-28 21:40:38 +00001870 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001871 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001872 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001873 size_t n_copies;
1874
1875 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001876 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001877 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001878 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001879 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1880 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1881 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1882 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1883 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1884 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1885 }
1886
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001887 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001888 for (size_t j = 0; j < n_copies; ++j)
1889 ConstVecValues.push_back(CValue);
1890
1891 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001892 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001893 } else {
1894 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001895 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001896 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1897 case MVT::i8:
1898 case MVT::i16:
1899 case MVT::i32:
1900 case MVT::i64:
1901 case MVT::f32:
1902 case MVT::f64:
1903 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1904 }
1905 }
1906
Dan Gohman475871a2008-07-27 21:46:04 +00001907 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001908}
1909
Dan Gohman475871a2008-07-27 21:46:04 +00001910static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001911 switch (Op.getValueType().getSimpleVT()) {
1912 default:
1913 cerr << "CellSPU: Unknown vector multiplication, got "
1914 << Op.getValueType().getMVTString()
1915 << "\n";
1916 abort();
1917 /*NOTREACHED*/
1918
Scott Michel266bc8f2007-12-04 22:23:35 +00001919 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001920 SDValue rA = Op.getOperand(0);
1921 SDValue rB = Op.getOperand(1);
1922 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1923 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1924 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1925 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001926
1927 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1928 break;
1929 }
1930
1931 // Multiply two v8i16 vectors (pipeline friendly version):
1932 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1933 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1934 // c) Use SELB to select upper and lower halves from the intermediate results
1935 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001936 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001937 // dual-issue. This code does manage to do this, even if it's a little on
1938 // the wacky side
1939 case MVT::v8i16: {
1940 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001941 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001942 SDValue Chain = Op.getOperand(0);
1943 SDValue rA = Op.getOperand(0);
1944 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001945 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1946 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001947
Dan Gohman475871a2008-07-27 21:46:04 +00001948 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001949 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001950 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001951 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001952
Dan Gohman475871a2008-07-27 21:46:04 +00001953 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001954 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001955 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001956
Dan Gohman475871a2008-07-27 21:46:04 +00001957 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001958 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001959 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001960
1961 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001962 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1963 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1964 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1965 HHProd_v4i32,
1966 DAG.getConstant(16, MVT::i16))),
1967 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001968 }
1969
1970 // This M00sE is N@stI! (apologies to Monty Python)
1971 //
1972 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1973 // is to break it all apart, sign extend, and reassemble the various
1974 // intermediate products.
1975 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001976 SDValue rA = Op.getOperand(0);
1977 SDValue rB = Op.getOperand(1);
1978 SDValue c8 = DAG.getConstant(8, MVT::i32);
1979 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001980
Dan Gohman475871a2008-07-27 21:46:04 +00001981 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001982 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001983 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1984 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001985
Dan Gohman475871a2008-07-27 21:46:04 +00001986 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001987
Dan Gohman475871a2008-07-27 21:46:04 +00001988 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001989
Dan Gohman475871a2008-07-27 21:46:04 +00001990 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001991 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001992 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001993
Dan Gohman475871a2008-07-27 21:46:04 +00001994 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001995 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001996
Dan Gohman475871a2008-07-27 21:46:04 +00001997 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001998 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1999 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2000 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002001
Dan Gohman475871a2008-07-27 21:46:04 +00002002 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002003
Dan Gohman475871a2008-07-27 21:46:04 +00002004 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002005 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00002006 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002007 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2008 LoProdMask, LoProdMask,
2009 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002010
Dan Gohman475871a2008-07-27 21:46:04 +00002011 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002012 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002013 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002014
Dan Gohman475871a2008-07-27 21:46:04 +00002015 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002016 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002017 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002018
Dan Gohman475871a2008-07-27 21:46:04 +00002019 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002020 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002021 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2022 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00002023
Dan Gohman475871a2008-07-27 21:46:04 +00002024 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002025 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002026 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002027 DAG.getNode(SPUISD::VEC_SRA,
2028 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002029 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002030 DAG.getNode(SPUISD::VEC_SRA,
2031 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002032
Dan Gohman475871a2008-07-27 21:46:04 +00002033 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00002034 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2035 HLProd,
2036 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2037 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002038
Dan Gohman475871a2008-07-27 21:46:04 +00002039 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002040 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002041
2042 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002043 DAG.getNode(ISD::OR, MVT::v4i32,
2044 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002045 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002046 }
2047
Dan Gohman475871a2008-07-27 21:46:04 +00002048 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002049}
2050
Dan Gohman475871a2008-07-27 21:46:04 +00002051static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002052 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002053 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002054
Dan Gohman475871a2008-07-27 21:46:04 +00002055 SDValue A = Op.getOperand(0);
2056 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002057 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002058
2059 unsigned VRegBR, VRegC;
2060
2061 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002062 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2063 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002064 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002065 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2066 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002067 }
2068 // TODO: make sure we're feeding FPInterp the right arguments
2069 // Right now: fi B, frest(B)
2070
2071 // Computes BRcpl =
2072 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002073 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002074 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2075 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002076 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002077
Scott Michel266bc8f2007-12-04 22:23:35 +00002078 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002079 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002080 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002081 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002082 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002083 // What's the Chain variable do? It's magic!
2084 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002085
2086 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002087 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002088 DAG.getNode(ISD::FMUL, VT,
2089 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002090 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002091 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002092 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002093}
2094
Dan Gohman475871a2008-07-27 21:46:04 +00002095static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002096 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002097 SDValue N = Op.getOperand(0);
2098 SDValue Elt = Op.getOperand(1);
2099 SDValue ShufMask[16];
Scott Michel266bc8f2007-12-04 22:23:35 +00002100 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
2101
2102 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2103
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002104 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002105
2106 // sanity checks:
2107 if (VT == MVT::i8 && EltNo >= 16)
2108 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2109 else if (VT == MVT::i16 && EltNo >= 8)
2110 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2111 else if (VT == MVT::i32 && EltNo >= 4)
2112 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2113 else if (VT == MVT::i64 && EltNo >= 2)
2114 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2115
2116 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2117 // i32 and i64: Element 0 is the preferred slot
2118 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2119 }
2120
2121 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002122 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002123 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002124
Duncan Sands83ec4b62008-06-06 12:08:01 +00002125 switch (VT.getSimpleVT()) {
2126 default:
2127 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002128 case MVT::i8: {
2129 prefslot_begin = prefslot_end = 3;
2130 break;
2131 }
2132 case MVT::i16: {
2133 prefslot_begin = 2; prefslot_end = 3;
2134 break;
2135 }
2136 case MVT::i32: {
2137 prefslot_begin = 0; prefslot_end = 3;
2138 break;
2139 }
2140 case MVT::i64: {
2141 prefslot_begin = 0; prefslot_end = 7;
2142 break;
2143 }
2144 }
2145
Scott Michel0e5665b2007-12-19 21:17:42 +00002146 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002147 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002148
Scott Michel266bc8f2007-12-04 22:23:35 +00002149 for (int i = 0; i < 16; ++i) {
2150 // zero fill uppper part of preferred slot, don't care about the
2151 // other slots:
2152 unsigned int mask_val;
2153
2154 if (i <= prefslot_end) {
2155 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002156 ((i < prefslot_begin)
2157 ? 0x80
2158 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002159
Scott Michel0e5665b2007-12-19 21:17:42 +00002160 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002161 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002162 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2163 }
2164
Dan Gohman475871a2008-07-27 21:46:04 +00002165 SDValue ShufMaskVec =
Scott Michel266bc8f2007-12-04 22:23:35 +00002166 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002167 &ShufMask[0],
2168 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002169
2170 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002171 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2172 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002173
Scott Michel266bc8f2007-12-04 22:23:35 +00002174}
2175
Dan Gohman475871a2008-07-27 21:46:04 +00002176static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2177 SDValue VecOp = Op.getOperand(0);
2178 SDValue ValOp = Op.getOperand(1);
2179 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002180 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002181
2182 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2183 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2184
Duncan Sands83ec4b62008-06-06 12:08:01 +00002185 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002186 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002187 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002188
Dan Gohman475871a2008-07-27 21:46:04 +00002189 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002190 DAG.getNode(SPUISD::SHUFB, VT,
2191 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2192 VecOp,
2193 DAG.getNode(SPUISD::INSERT_MASK, VT,
2194 DAG.getNode(ISD::ADD, PtrVT,
2195 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002196 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002197 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002198
2199 return result;
2200}
2201
Dan Gohman475871a2008-07-27 21:46:04 +00002202static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002203{
Dan Gohman475871a2008-07-27 21:46:04 +00002204 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002205
2206 assert(Op.getValueType() == MVT::i8);
2207 switch (Opc) {
2208 default:
2209 assert(0 && "Unhandled i8 math operator");
2210 /*NOTREACHED*/
2211 break;
2212 case ISD::SUB: {
2213 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2214 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002215 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002216 N0 = (N0.getOpcode() != ISD::Constant
2217 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002218 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2219 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002220 N1 = (N1.getOpcode() != ISD::Constant
2221 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002222 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2223 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002224 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002225 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002226 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002227 case ISD::ROTR:
2228 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002229 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002230 unsigned N1Opc;
2231 N0 = (N0.getOpcode() != ISD::Constant
2232 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002233 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2234 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002235 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2236 ? ISD::ZERO_EXTEND
2237 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002238 N1 = (N1.getOpcode() != ISD::Constant
2239 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002240 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2241 MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002242 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002243 DAG.getNode(ISD::OR, MVT::i16, N0,
2244 DAG.getNode(ISD::SHL, MVT::i16,
2245 N0, DAG.getConstant(8, MVT::i16)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002246 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002247 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2248 }
2249 case ISD::SRL:
2250 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002251 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002252 unsigned N1Opc;
2253 N0 = (N0.getOpcode() != ISD::Constant
2254 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002255 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2256 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002257 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2258 ? ISD::ZERO_EXTEND
2259 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002260 N1 = (N1.getOpcode() != ISD::Constant
2261 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002262 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2263 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002264 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002265 DAG.getNode(Opc, MVT::i16, N0, N1));
2266 }
2267 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002268 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002269 unsigned N1Opc;
2270 N0 = (N0.getOpcode() != ISD::Constant
2271 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002272 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2273 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002274 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2275 ? ISD::SIGN_EXTEND
2276 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002277 N1 = (N1.getOpcode() != ISD::Constant
2278 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002279 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2280 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002281 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002282 DAG.getNode(Opc, MVT::i16, N0, N1));
2283 }
2284 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002285 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002286 unsigned N1Opc;
2287 N0 = (N0.getOpcode() != ISD::Constant
2288 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002289 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2290 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002291 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002292 N1 = (N1.getOpcode() != ISD::Constant
2293 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002294 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2295 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002296 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002297 DAG.getNode(Opc, MVT::i16, N0, N1));
2298 break;
2299 }
2300 }
2301
Dan Gohman475871a2008-07-27 21:46:04 +00002302 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002303}
2304
Dan Gohman475871a2008-07-27 21:46:04 +00002305static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002306{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002307 MVT VT = Op.getValueType();
2308 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002309
Dan Gohman475871a2008-07-27 21:46:04 +00002310 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002311
2312 switch (Opc) {
2313 case ISD::ZERO_EXTEND:
2314 case ISD::SIGN_EXTEND:
2315 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002316 MVT Op0VT = Op0.getValueType();
2317 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002318
2319 assert(Op0VT == MVT::i32
2320 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002321 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002322
2323 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2324 ? SPUISD::ROTBYTES_RIGHT_S
2325 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002326 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002327 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2328
2329 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2330 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2331 DAG.getNode(NewOpc, Op0VecVT,
2332 PromoteScalar,
2333 DAG.getConstant(4, MVT::i32))));
2334 }
2335
Scott Michel8bf61e82008-06-02 22:18:03 +00002336 case ISD::ADD: {
2337 // Turn operands into vectors to satisfy type checking (shufb works on
2338 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002339 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002340 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002341 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002342 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002343 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002344
2345 // Create the shuffle mask for "rotating" the borrow up one register slot
2346 // once the borrow is generated.
2347 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2348 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2349 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2350 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2351
Dan Gohman475871a2008-07-27 21:46:04 +00002352 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002353 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002354 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002355 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2356 CarryGen, CarryGen,
2357 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2358 &ShufBytes[0], ShufBytes.size()));
2359
2360 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2361 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2362 Op0, Op1, ShiftedCarry));
2363 }
2364
2365 case ISD::SUB: {
2366 // Turn operands into vectors to satisfy type checking (shufb works on
2367 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002368 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002369 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002370 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002371 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002372 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002373
2374 // Create the shuffle mask for "rotating" the borrow up one register slot
2375 // once the borrow is generated.
2376 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2377 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2378 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2379 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2380
Dan Gohman475871a2008-07-27 21:46:04 +00002381 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002382 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002383 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002384 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2385 BorrowGen, BorrowGen,
2386 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2387 &ShufBytes[0], ShufBytes.size()));
2388
2389 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2390 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2391 Op0, Op1, ShiftedBorrow));
2392 }
2393
Scott Michela59d4692008-02-23 18:41:37 +00002394 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002395 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002396 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002397 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2398 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002399 DAG.getNode(SPUISD::SELB, VecVT,
2400 Op0Vec,
2401 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002402 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002403 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002404 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002405 DAG.getNode(ISD::SRL, ShiftAmtVT,
2406 ShiftAmt,
2407 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002408 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002409 DAG.getNode(ISD::AND, ShiftAmtVT,
2410 ShiftAmt,
2411 DAG.getConstant(7, ShiftAmtVT));
2412
2413 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2414 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2415 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2416 MaskLower, ShiftAmtBytes),
2417 ShiftAmtBits));
2418 }
2419
2420 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002421 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002422 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002423 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002424 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002425 DAG.getNode(ISD::SRL, ShiftAmtVT,
2426 ShiftAmt,
2427 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002428 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002429 DAG.getNode(ISD::AND, ShiftAmtVT,
2430 ShiftAmt,
2431 DAG.getConstant(7, ShiftAmtVT));
2432
2433 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2434 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2435 Op0, ShiftAmtBytes),
2436 ShiftAmtBits);
2437 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002438
2439 case ISD::SRA: {
2440 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002441 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002442 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002443 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002444 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002445
2446 // Negate variable shift amounts
2447 if (!isa<ConstantSDNode>(ShiftAmt)) {
2448 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2449 DAG.getConstant(0, ShiftVT), ShiftAmt);
2450 }
2451
Dan Gohman475871a2008-07-27 21:46:04 +00002452 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002453 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2454 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2455 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2456 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002457 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002458 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002459 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002460 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2461 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002462 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002463 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2464 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002465 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002466 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2467 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002468 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002469 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2470 RotateLeftBytes, ShiftAmt);
2471
2472 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2473 RotateLeftBits);
2474 }
Scott Michela59d4692008-02-23 18:41:37 +00002475 }
2476
Dan Gohman475871a2008-07-27 21:46:04 +00002477 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002478}
2479
Scott Michel266bc8f2007-12-04 22:23:35 +00002480//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002481static SDValue
2482LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2483 SDValue ConstVec;
2484 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002485 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002486
2487 ConstVec = Op.getOperand(0);
2488 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002489 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2490 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002491 ConstVec = ConstVec.getOperand(0);
2492 } else {
2493 ConstVec = Op.getOperand(1);
2494 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002495 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002496 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002497 }
2498 }
2499 }
2500
Gabor Greifba36cb52008-08-28 21:40:38 +00002501 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002502 uint64_t VectorBits[2];
2503 uint64_t UndefBits[2];
2504 uint64_t SplatBits, SplatUndef;
2505 int SplatSize;
2506
Gabor Greifba36cb52008-08-28 21:40:38 +00002507 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002508 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002509 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002510 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002511 SDValue tcVec[16];
2512 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002513 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2514
2515 // Turn the BUILD_VECTOR into a set of target constants:
2516 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002517 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002518
Gabor Greifba36cb52008-08-28 21:40:38 +00002519 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002520 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002521 }
2522 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002523 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2524 // lowered. Return the operation, rather than a null SDValue.
2525 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002526}
2527
2528//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002529static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002530 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002531 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002532 default:
2533 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002534 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002535 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002536 abort();
2537 /*NOTREACHED*/
2538
2539 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002540 SDValue rA = Op.getOperand(0);
2541 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002542
2543 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002544 DAG.getNode(ISD::ADD, MVT::i32,
2545 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2546 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2547 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002548 }
2549 }
2550
Dan Gohman475871a2008-07-27 21:46:04 +00002551 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002552}
2553
2554//! Custom lowering for CTPOP (count population)
2555/*!
2556 Custom lowering code that counts the number ones in the input
2557 operand. SPU has such an instruction, but it counts the number of
2558 ones per byte, which then have to be accumulated.
2559*/
Dan Gohman475871a2008-07-27 21:46:04 +00002560static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002561 MVT VT = Op.getValueType();
2562 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002563
Duncan Sands83ec4b62008-06-06 12:08:01 +00002564 switch (VT.getSimpleVT()) {
2565 default:
2566 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002567 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002568 SDValue N = Op.getOperand(0);
2569 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002570
Dan Gohman475871a2008-07-27 21:46:04 +00002571 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2572 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002573
2574 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2575 }
2576
2577 case MVT::i16: {
2578 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002579 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002580
Chris Lattner84bc5422007-12-31 04:13:23 +00002581 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002582
Dan Gohman475871a2008-07-27 21:46:04 +00002583 SDValue N = Op.getOperand(0);
2584 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2585 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
2586 SDValue Shift1 = DAG.getConstant(8, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002587
Dan Gohman475871a2008-07-27 21:46:04 +00002588 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2589 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002590
2591 // CNTB_result becomes the chain to which all of the virtual registers
2592 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002593 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002594 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002595
Dan Gohman475871a2008-07-27 21:46:04 +00002596 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002597 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2598
Dan Gohman475871a2008-07-27 21:46:04 +00002599 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002600
2601 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002602 DAG.getNode(ISD::ADD, MVT::i16,
2603 DAG.getNode(ISD::SRL, MVT::i16,
2604 Tmp1, Shift1),
2605 Tmp1),
2606 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002607 }
2608
2609 case MVT::i32: {
2610 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002611 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002612
Chris Lattner84bc5422007-12-31 04:13:23 +00002613 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2614 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002615
Dan Gohman475871a2008-07-27 21:46:04 +00002616 SDValue N = Op.getOperand(0);
2617 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2618 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2619 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2620 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002621
Dan Gohman475871a2008-07-27 21:46:04 +00002622 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2623 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002624
2625 // CNTB_result becomes the chain to which all of the virtual registers
2626 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002627 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002628 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002629
Dan Gohman475871a2008-07-27 21:46:04 +00002630 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002631 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2632
Dan Gohman475871a2008-07-27 21:46:04 +00002633 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002634 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002635 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002636
Dan Gohman475871a2008-07-27 21:46:04 +00002637 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002638 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002639 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002640
Dan Gohman475871a2008-07-27 21:46:04 +00002641 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002642 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2643
Dan Gohman475871a2008-07-27 21:46:04 +00002644 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002645 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002646 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2647 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002648 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002649 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002650 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002651
2652 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2653 }
2654
2655 case MVT::i64:
2656 break;
2657 }
2658
Dan Gohman475871a2008-07-27 21:46:04 +00002659 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002660}
2661
2662/// LowerOperation - Provide custom lowering hooks for some operations.
2663///
Dan Gohman475871a2008-07-27 21:46:04 +00002664SDValue
2665SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002666{
Scott Michela59d4692008-02-23 18:41:37 +00002667 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002668 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002669
2670 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002671 default: {
2672 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002673 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002674 cerr << "*Op.getNode():\n";
2675 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002676 abort();
2677 }
2678 case ISD::LOAD:
2679 case ISD::SEXTLOAD:
2680 case ISD::ZEXTLOAD:
2681 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2682 case ISD::STORE:
2683 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2684 case ISD::ConstantPool:
2685 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2686 case ISD::GlobalAddress:
2687 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2688 case ISD::JumpTable:
2689 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2690 case ISD::Constant:
2691 return LowerConstant(Op, DAG);
2692 case ISD::ConstantFP:
2693 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002694 case ISD::BRCOND:
2695 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002696 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002697 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002698 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002699 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002700 case ISD::RET:
2701 return LowerRET(Op, DAG, getTargetMachine());
2702
Scott Michela59d4692008-02-23 18:41:37 +00002703
2704 // i8, i64 math ops:
2705 case ISD::ZERO_EXTEND:
2706 case ISD::SIGN_EXTEND:
2707 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002708 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002709 case ISD::SUB:
2710 case ISD::ROTR:
2711 case ISD::ROTL:
2712 case ISD::SRL:
2713 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002714 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002715 if (VT == MVT::i8)
2716 return LowerI8Math(Op, DAG, Opc);
2717 else if (VT == MVT::i64)
2718 return LowerI64Math(Op, DAG, Opc);
2719 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002720 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002721
2722 // Vector-related lowering.
2723 case ISD::BUILD_VECTOR:
2724 return LowerBUILD_VECTOR(Op, DAG);
2725 case ISD::SCALAR_TO_VECTOR:
2726 return LowerSCALAR_TO_VECTOR(Op, DAG);
2727 case ISD::VECTOR_SHUFFLE:
2728 return LowerVECTOR_SHUFFLE(Op, DAG);
2729 case ISD::EXTRACT_VECTOR_ELT:
2730 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2731 case ISD::INSERT_VECTOR_ELT:
2732 return LowerINSERT_VECTOR_ELT(Op, DAG);
2733
2734 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2735 case ISD::AND:
2736 case ISD::OR:
2737 case ISD::XOR:
2738 return LowerByteImmed(Op, DAG);
2739
2740 // Vector and i8 multiply:
2741 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002742 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002743 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002744 else if (VT == MVT::i8)
2745 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002746 else
Scott Michela59d4692008-02-23 18:41:37 +00002747 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002748
2749 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002750 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002751 return LowerFDIVf32(Op, DAG);
2752// else if (Op.getValueType() == MVT::f64)
2753// return LowerFDIVf64(Op, DAG);
2754 else
2755 assert(0 && "Calling FDIV on unsupported MVT");
2756
2757 case ISD::CTPOP:
2758 return LowerCTPOP(Op, DAG);
2759 }
2760
Dan Gohman475871a2008-07-27 21:46:04 +00002761 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002762}
2763
2764//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002765// Target Optimization Hooks
2766//===----------------------------------------------------------------------===//
2767
Dan Gohman475871a2008-07-27 21:46:04 +00002768SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002769SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2770{
2771#if 0
2772 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002773#endif
2774 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002775 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002776 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2777 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002778
2779 switch (N->getOpcode()) {
2780 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002781 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002782 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002783
Scott Michel8bf61e82008-06-02 22:18:03 +00002784 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002785 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002786 if (Op01.getOpcode() == ISD::Constant
2787 || Op01.getOpcode() == ISD::TargetConstant) {
2788 // (add <const>, (SPUindirect <arg>, <const>)) ->
2789 // (SPUindirect <arg>, <const + const>)
2790 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2791 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002792 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002793 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002794 Op0.getValueType());
2795
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002796 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2797 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002798 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002799 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002800 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2801 Op0.getOperand(0), combinedConst);
2802 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002803 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002804 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002805 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002806 if (Op11.getOpcode() == ISD::Constant
2807 || Op11.getOpcode() == ISD::TargetConstant) {
2808 // (add (SPUindirect <arg>, <const>), <const>) ->
2809 // (SPUindirect <arg>, <const + const>)
2810 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2811 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002812 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002813 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002814 Op0.getValueType());
2815
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002816 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2817 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002818 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002819 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002820
2821 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2822 Op1.getOperand(0), combinedConst);
2823 }
2824 }
Scott Michela59d4692008-02-23 18:41:37 +00002825 break;
2826 }
2827 case ISD::SIGN_EXTEND:
2828 case ISD::ZERO_EXTEND:
2829 case ISD::ANY_EXTEND: {
2830 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2831 N->getValueType(0) == Op0.getValueType()) {
2832 // (any_extend (SPUextract_elt0 <arg>)) ->
2833 // (SPUextract_elt0 <arg>)
2834 // Types must match, however...
2835 DEBUG(cerr << "Replace: ");
2836 DEBUG(N->dump(&DAG));
2837 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002838 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002839 DEBUG(cerr << "\n");
2840
2841 return Op0;
2842 }
2843 break;
2844 }
2845 case SPUISD::IndirectAddr: {
2846 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2847 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002848 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002849 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2850 // (SPUaform <addr>, 0)
2851
2852 DEBUG(cerr << "Replace: ");
2853 DEBUG(N->dump(&DAG));
2854 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002855 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002856 DEBUG(cerr << "\n");
2857
2858 return Op0;
2859 }
2860 }
2861 break;
2862 }
2863 case SPUISD::SHLQUAD_L_BITS:
2864 case SPUISD::SHLQUAD_L_BYTES:
2865 case SPUISD::VEC_SHL:
2866 case SPUISD::VEC_SRL:
2867 case SPUISD::VEC_SRA:
2868 case SPUISD::ROTQUAD_RZ_BYTES:
2869 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002870 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002871
2872 if (isa<ConstantSDNode>(Op1)) {
2873 // Kill degenerate vector shifts:
2874 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2875
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002876 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002877 Result = Op0;
2878 }
2879 }
2880 break;
2881 }
2882 case SPUISD::PROMOTE_SCALAR: {
2883 switch (Op0.getOpcode()) {
2884 default:
2885 break;
2886 case ISD::ANY_EXTEND:
2887 case ISD::ZERO_EXTEND:
2888 case ISD::SIGN_EXTEND: {
2889 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2890 // <arg>
2891 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002892 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002893 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00002894 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002895 if (Op000.getValueType() == N->getValueType(0)) {
2896 Result = Op000;
2897 }
2898 }
2899 break;
2900 }
2901 case SPUISD::EXTRACT_ELT0: {
2902 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2903 // <arg>
2904 Result = Op0.getOperand(0);
2905 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002906 }
Scott Michela59d4692008-02-23 18:41:37 +00002907 }
2908 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002909 }
2910 }
Scott Michel58c58182008-01-17 20:38:41 +00002911 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002912#if 1
Gabor Greifba36cb52008-08-28 21:40:38 +00002913 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00002914 DEBUG(cerr << "\nReplace.SPU: ");
2915 DEBUG(N->dump(&DAG));
2916 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002917 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002918 DEBUG(cerr << "\n");
2919 }
2920#endif
2921
2922 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002923}
2924
2925//===----------------------------------------------------------------------===//
2926// Inline Assembly Support
2927//===----------------------------------------------------------------------===//
2928
2929/// getConstraintType - Given a constraint letter, return the type of
2930/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002931SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002932SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2933 if (ConstraintLetter.size() == 1) {
2934 switch (ConstraintLetter[0]) {
2935 default: break;
2936 case 'b':
2937 case 'r':
2938 case 'f':
2939 case 'v':
2940 case 'y':
2941 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002942 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002943 }
2944 return TargetLowering::getConstraintType(ConstraintLetter);
2945}
2946
Scott Michel5af8f0e2008-07-16 17:17:29 +00002947std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002948SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002949 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002950{
2951 if (Constraint.size() == 1) {
2952 // GCC RS6000 Constraint Letters
2953 switch (Constraint[0]) {
2954 case 'b': // R1-R31
2955 case 'r': // R0-R31
2956 if (VT == MVT::i64)
2957 return std::make_pair(0U, SPU::R64CRegisterClass);
2958 return std::make_pair(0U, SPU::R32CRegisterClass);
2959 case 'f':
2960 if (VT == MVT::f32)
2961 return std::make_pair(0U, SPU::R32FPRegisterClass);
2962 else if (VT == MVT::f64)
2963 return std::make_pair(0U, SPU::R64FPRegisterClass);
2964 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002965 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002966 return std::make_pair(0U, SPU::GPRCRegisterClass);
2967 }
2968 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002969
Scott Michel266bc8f2007-12-04 22:23:35 +00002970 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2971}
2972
Scott Michela59d4692008-02-23 18:41:37 +00002973//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002974void
Dan Gohman475871a2008-07-27 21:46:04 +00002975SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002976 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002977 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002978 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002979 const SelectionDAG &DAG,
2980 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002981#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002982 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002983#endif
Scott Michela59d4692008-02-23 18:41:37 +00002984
2985 switch (Op.getOpcode()) {
2986 default:
2987 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2988 break;
2989
2990#if 0
2991 case CALL:
2992 case SHUFB:
2993 case INSERT_MASK:
2994 case CNTB:
2995#endif
2996
2997 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00002998 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002999 MVT Op0VT = Op0.getValueType();
3000 unsigned Op0VTBits = Op0VT.getSizeInBits();
3001 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003002 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3003 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003004 break;
3005 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003006
Scott Michela59d4692008-02-23 18:41:37 +00003007 case SPUISD::LDRESULT:
3008 case SPUISD::EXTRACT_ELT0:
3009 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00003010 MVT OpVT = Op.getValueType();
3011 unsigned OpVTBits = OpVT.getSizeInBits();
3012 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003013 KnownZero |= APInt(OpVTBits, ~InMask, false);
3014 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003015 break;
3016 }
3017
3018#if 0
3019 case EXTRACT_I1_ZEXT:
3020 case EXTRACT_I1_SEXT:
3021 case EXTRACT_I8_ZEXT:
3022 case EXTRACT_I8_SEXT:
3023 case MPY:
3024 case MPYU:
3025 case MPYH:
3026 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003027 case SPUISD::SHLQUAD_L_BITS:
3028 case SPUISD::SHLQUAD_L_BYTES:
3029 case SPUISD::VEC_SHL:
3030 case SPUISD::VEC_SRL:
3031 case SPUISD::VEC_SRA:
3032 case SPUISD::VEC_ROTL:
3033 case SPUISD::VEC_ROTR:
3034 case SPUISD::ROTQUAD_RZ_BYTES:
3035 case SPUISD::ROTQUAD_RZ_BITS:
3036 case SPUISD::ROTBYTES_RIGHT_S:
3037 case SPUISD::ROTBYTES_LEFT:
3038 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003039 case SPUISD::SELECT_MASK:
3040 case SPUISD::SELB:
3041 case SPUISD::FPInterp:
3042 case SPUISD::FPRecipEst:
3043 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003044#endif
3045 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003046}
3047
Scott Michel203b2d62008-04-30 00:30:08 +00003048// LowerAsmOperandForConstraint
3049void
Dan Gohman475871a2008-07-27 21:46:04 +00003050SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003051 char ConstraintLetter,
Dan Gohman475871a2008-07-27 21:46:04 +00003052 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003053 SelectionDAG &DAG) const {
3054 // Default, for the time being, to the base class handler
3055 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, Ops, DAG);
3056}
3057
Scott Michel266bc8f2007-12-04 22:23:35 +00003058/// isLegalAddressImmediate - Return true if the integer value can be used
3059/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003060bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3061 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003062 // SPU's addresses are 256K:
3063 return (V > -(1 << 18) && V < (1 << 18) - 1);
3064}
3065
3066bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003067 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003068}