blob: b97f4c4c2b9a5aa78e2f86a46470ab797051b3a9 [file] [log] [blame]
Scott Michel266bc8f2007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel266bc8f2007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SPUTargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPURegisterNames.h"
15#include "SPUISelLowering.h"
16#include "SPUTargetMachine.h"
Scott Michel203b2d62008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000018#include "llvm/ADT/VectorExtras.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000019#include "llvm/CodeGen/CallingConvLower.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner84bc5422007-12-31 04:13:23 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000025#include "llvm/Constants.h"
26#include "llvm/Function.h"
27#include "llvm/Intrinsics.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/MathExtras.h"
30#include "llvm/Target/TargetOptions.h"
31
32#include <map>
33
34using namespace llvm;
35
36// Used in getTargetNodeName() below
37namespace {
38 std::map<unsigned, const char *> node_names;
39
Duncan Sands83ec4b62008-06-06 12:08:01 +000040 //! MVT mapping to useful data for Cell SPU
Scott Michel266bc8f2007-12-04 22:23:35 +000041 struct valtype_map_s {
Duncan Sands83ec4b62008-06-06 12:08:01 +000042 const MVT valtype;
Scott Michel7f9ba9b2008-01-30 02:55:46 +000043 const int prefslot_byte;
Scott Michel266bc8f2007-12-04 22:23:35 +000044 };
Scott Michel5af8f0e2008-07-16 17:17:29 +000045
Scott Michel266bc8f2007-12-04 22:23:35 +000046 const valtype_map_s valtype_map[] = {
47 { MVT::i1, 3 },
48 { MVT::i8, 3 },
49 { MVT::i16, 2 },
50 { MVT::i32, 0 },
51 { MVT::f32, 0 },
52 { MVT::i64, 0 },
53 { MVT::f64, 0 },
54 { MVT::i128, 0 }
55 };
56
57 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
58
Duncan Sands83ec4b62008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel266bc8f2007-12-04 22:23:35 +000060 const valtype_map_s *retval = 0;
61
62 for (size_t i = 0; i < n_valtype_map; ++i) {
63 if (valtype_map[i].valtype == VT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel266bc8f2007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands83ec4b62008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +000074 abort();
75 }
76#endif
77
78 return retval;
79 }
80
81 //! Predicate that returns true if operand is a memory target
82 /*!
83 \arg Op Operand to test
84 \return true if the operand is a memory target (i.e., global
Scott Michel9de5d0d2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel266bc8f2007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman475871a2008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel266bc8f2007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
Bill Wendling9468a9b2008-09-16 21:12:30 +000095 || Opc == ISD::Symbol
Scott Michel266bc8f2007-12-04 22:23:35 +000096 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
Bill Wendling9468a9b2008-09-16 21:12:30 +0000100 || Opc == ISD::TargetSymbol
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) {
Dan Gohman095cc292008-09-13 01:54:27 +00001104 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1105 SDValue Chain = TheCall->getChain();
Scott Michel266bc8f2007-12-04 22:23:35 +00001106#if 0
Dan Gohman095cc292008-09-13 01:54:27 +00001107 bool isVarArg = TheCall->isVarArg();
1108 bool isTailCall = TheCall->isTailCall();
Scott Michel266bc8f2007-12-04 22:23:35 +00001109#endif
Dan Gohman095cc292008-09-13 01:54:27 +00001110 SDValue Callee = TheCall->getCallee();
1111 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001112 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1113 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1114 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1115
1116 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001117 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001118
Scott Michel266bc8f2007-12-04 22:23:35 +00001119 // Accumulate how many bytes are to be pushed on the stack, including the
1120 // linkage area, and parameter passing area. According to the SPU ABI,
1121 // we minimally need space for [LR] and [SP]
1122 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001123
Scott Michel266bc8f2007-12-04 22:23:35 +00001124 // Set up a copy of the stack pointer for use loading and storing any
1125 // arguments that may not fit in the registers available for argument
1126 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001127 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001128
Scott Michel266bc8f2007-12-04 22:23:35 +00001129 // Figure out which arguments are going to go in registers, and which in
1130 // memory.
1131 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1132 unsigned ArgRegIdx = 0;
1133
1134 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001135 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001136 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001137 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001138
1139 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001140 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001141
Scott Michel266bc8f2007-12-04 22:23:35 +00001142 // PtrOff will be used to store the current argument to the stack if a
1143 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001144 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001145 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1146
Duncan Sands83ec4b62008-06-06 12:08:01 +00001147 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001148 default: assert(0 && "Unexpected ValueType for argument!");
1149 case MVT::i32:
1150 case MVT::i64:
1151 case MVT::i128:
1152 if (ArgRegIdx != NumArgRegs) {
1153 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1154 } else {
1155 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001156 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001157 }
1158 break;
1159 case MVT::f32:
1160 case MVT::f64:
1161 if (ArgRegIdx != NumArgRegs) {
1162 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1163 } else {
1164 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001165 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001166 }
1167 break;
1168 case MVT::v4f32:
1169 case MVT::v4i32:
1170 case MVT::v8i16:
1171 case MVT::v16i8:
1172 if (ArgRegIdx != NumArgRegs) {
1173 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1174 } else {
1175 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001176 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001177 }
1178 break;
1179 }
1180 }
1181
1182 // Update number of stack bytes actually used, insert a call sequence start
1183 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
1184 Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumStackBytes, PtrVT));
1185
1186 if (!MemOpChains.empty()) {
1187 // Adjust the stack pointer for the stack arguments.
1188 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1189 &MemOpChains[0], MemOpChains.size());
1190 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001191
Scott Michel266bc8f2007-12-04 22:23:35 +00001192 // Build a sequence of copy-to-reg nodes chained together with token chain
1193 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001194 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001195 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1196 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1197 InFlag);
1198 InFlag = Chain.getValue(1);
1199 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001200
Dan Gohman475871a2008-07-27 21:46:04 +00001201 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001202 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001203
Bill Wendling9468a9b2008-09-16 21:12:30 +00001204 // If the callee is a GlobalAddress/Symbol node (quite common, every direct
1205 // call is) turn it into a TargetGlobalAddress/TargetSymbol node so that
1206 // legalize doesn't hack it.
Scott Michel266bc8f2007-12-04 22:23:35 +00001207 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1208 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001209 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001210 SDValue Zero = DAG.getConstant(0, PtrVT);
1211 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001212
Scott Michel9de5d0d2008-01-11 02:53:15 +00001213 if (!ST->usingLargeMem()) {
1214 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1215 // style calls, otherwise, external symbols are BRASL calls. This assumes
1216 // that declared/defined symbols are in the same compilation unit and can
1217 // be reached through PC-relative jumps.
1218 //
1219 // NOTE:
1220 // This may be an unsafe assumption for JIT and really large compilation
1221 // units.
1222 if (GV->isDeclaration()) {
1223 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1224 } else {
1225 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1226 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001227 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001228 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1229 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001230 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001231 }
Bill Wendling9468a9b2008-09-16 21:12:30 +00001232 } else if (SymbolSDNode *S = dyn_cast<SymbolSDNode>(Callee))
1233 Callee = DAG.getSymbol(S->getSymbol(), Callee.getValueType(),
1234 S->getLinkage());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001235 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001236 // If this is an absolute destination address that appears to be a legal
1237 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001238 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001239 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001240
1241 Ops.push_back(Chain);
1242 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001243
Scott Michel266bc8f2007-12-04 22:23:35 +00001244 // Add argument registers to the end of the list so that they are known live
1245 // into the call.
1246 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001247 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001248 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001249
Gabor Greifba36cb52008-08-28 21:40:38 +00001250 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001251 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001252 // Returns a chain and a flag for retval copy to use.
1253 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1254 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001255 InFlag = Chain.getValue(1);
1256
Evan Chengebaaa912008-02-05 22:44:06 +00001257 Chain = DAG.getCALLSEQ_END(Chain,
1258 DAG.getConstant(NumStackBytes, PtrVT),
1259 DAG.getConstant(0, PtrVT),
1260 InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001261 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001262 InFlag = Chain.getValue(1);
1263
Dan Gohman475871a2008-07-27 21:46:04 +00001264 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001265 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001266
Scott Michel266bc8f2007-12-04 22:23:35 +00001267 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001268 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001269 default: assert(0 && "Unexpected ret value!");
1270 case MVT::Other: break;
1271 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001272 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001273 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1274 ResultVals[0] = Chain.getValue(0);
1275 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1276 Chain.getValue(2)).getValue(1);
1277 ResultVals[1] = Chain.getValue(0);
1278 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001279 } else {
1280 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1281 ResultVals[0] = Chain.getValue(0);
1282 NumResults = 1;
1283 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001284 break;
1285 case MVT::i64:
1286 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1287 ResultVals[0] = Chain.getValue(0);
1288 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001289 break;
1290 case MVT::f32:
1291 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001292 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001293 InFlag).getValue(1);
1294 ResultVals[0] = Chain.getValue(0);
1295 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001296 break;
1297 case MVT::v2f64:
1298 case MVT::v4f32:
1299 case MVT::v4i32:
1300 case MVT::v8i16:
1301 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001302 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001303 InFlag).getValue(1);
1304 ResultVals[0] = Chain.getValue(0);
1305 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001306 break;
1307 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001308
Scott Michel266bc8f2007-12-04 22:23:35 +00001309 // If the function returns void, just return the chain.
1310 if (NumResults == 0)
1311 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001312
Scott Michel266bc8f2007-12-04 22:23:35 +00001313 // Otherwise, merge everything together with a MERGE_VALUES node.
1314 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001315 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001316 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001317}
1318
Dan Gohman475871a2008-07-27 21:46:04 +00001319static SDValue
1320LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001321 SmallVector<CCValAssign, 16> RVLocs;
1322 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1323 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1324 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001325 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001326
Scott Michel266bc8f2007-12-04 22:23:35 +00001327 // If this is the first return lowered for this function, add the regs to the
1328 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001329 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001330 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001331 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001332 }
1333
Dan Gohman475871a2008-07-27 21:46:04 +00001334 SDValue Chain = Op.getOperand(0);
1335 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001336
Scott Michel266bc8f2007-12-04 22:23:35 +00001337 // Copy the result values into the output registers.
1338 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1339 CCValAssign &VA = RVLocs[i];
1340 assert(VA.isRegLoc() && "Can only return in registers!");
1341 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1342 Flag = Chain.getValue(1);
1343 }
1344
Gabor Greifba36cb52008-08-28 21:40:38 +00001345 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001346 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1347 else
1348 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1349}
1350
1351
1352//===----------------------------------------------------------------------===//
1353// Vector related lowering:
1354//===----------------------------------------------------------------------===//
1355
1356static ConstantSDNode *
1357getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001358 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001359
Scott Michel266bc8f2007-12-04 22:23:35 +00001360 // Check to see if this buildvec has a single non-undef value in its elements.
1361 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1362 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001363 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001364 OpVal = N->getOperand(i);
1365 else if (OpVal != N->getOperand(i))
1366 return 0;
1367 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001368
Gabor Greifba36cb52008-08-28 21:40:38 +00001369 if (OpVal.getNode() != 0) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001370 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1371 return CN;
1372 }
1373 }
1374
1375 return 0; // All UNDEF: use implicit def.; not Constant node
1376}
1377
1378/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1379/// and the value fits into an unsigned 18-bit constant, and if so, return the
1380/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001381SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001382 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001383 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001384 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001385 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001386 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001387 uint32_t upper = uint32_t(UValue >> 32);
1388 uint32_t lower = uint32_t(UValue);
1389 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001390 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001391 Value = Value >> 32;
1392 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001393 if (Value <= 0x3ffff)
1394 return DAG.getConstant(Value, ValueType);
1395 }
1396
Dan Gohman475871a2008-07-27 21:46:04 +00001397 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001398}
1399
1400/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1401/// and the value fits into a signed 16-bit constant, and if so, return the
1402/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001403SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001404 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001405 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001406 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001407 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001408 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001409 uint32_t upper = uint32_t(UValue >> 32);
1410 uint32_t lower = uint32_t(UValue);
1411 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001412 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001413 Value = Value >> 32;
1414 }
Scott Michelad2715e2008-03-05 23:02:02 +00001415 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
1416 return DAG.getConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001417 }
1418 }
1419
Dan Gohman475871a2008-07-27 21:46:04 +00001420 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001421}
1422
1423/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1424/// and the value fits into a signed 10-bit constant, and if so, return the
1425/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001426SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001427 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001428 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001429 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001430 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001431 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001432 uint32_t upper = uint32_t(UValue >> 32);
1433 uint32_t lower = uint32_t(UValue);
1434 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001435 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001436 Value = Value >> 32;
1437 }
Scott Michelad2715e2008-03-05 23:02:02 +00001438 if (isS10Constant(Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001439 return DAG.getConstant(Value, ValueType);
1440 }
1441
Dan Gohman475871a2008-07-27 21:46:04 +00001442 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001443}
1444
1445/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1446/// and the value fits into a signed 8-bit constant, and if so, return the
1447/// constant.
1448///
1449/// @note: The incoming vector is v16i8 because that's the only way we can load
1450/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1451/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001452SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001453 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001454 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001455 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001456 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001457 && Value <= 0xffff /* truncated from uint64_t */
1458 && ((short) Value >> 8) == ((short) Value & 0xff))
Scott Michel266bc8f2007-12-04 22:23:35 +00001459 return DAG.getConstant(Value & 0xff, ValueType);
1460 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001461 && (Value & 0xff) == Value)
Scott Michel266bc8f2007-12-04 22:23:35 +00001462 return DAG.getConstant(Value, ValueType);
1463 }
1464
Dan Gohman475871a2008-07-27 21:46:04 +00001465 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001466}
1467
1468/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1469/// and the value fits into a signed 16-bit constant, and if so, return the
1470/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001471SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001472 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001473 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001474 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001475 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001476 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1477 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001478 return DAG.getConstant(Value >> 16, ValueType);
1479 }
1480
Dan Gohman475871a2008-07-27 21:46:04 +00001481 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001482}
1483
1484/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001485SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001486 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001487 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001488 }
1489
Dan Gohman475871a2008-07-27 21:46:04 +00001490 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001491}
1492
1493/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001494SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001495 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001496 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001497 }
1498
Dan Gohman475871a2008-07-27 21:46:04 +00001499 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001500}
1501
1502// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001503// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001504// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1505// zero. Return true if this is not an array of constants, false if it is.
1506//
1507static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1508 uint64_t UndefBits[2]) {
1509 // Start with zero'd results.
1510 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001511
Duncan Sands83ec4b62008-06-06 12:08:01 +00001512 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001513 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001514 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001515
Scott Michel266bc8f2007-12-04 22:23:35 +00001516 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1517 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1518
1519 uint64_t EltBits = 0;
1520 if (OpVal.getOpcode() == ISD::UNDEF) {
1521 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1522 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1523 continue;
1524 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001525 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00001526 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
1527 const APFloat &apf = CN->getValueAPF();
1528 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001529 ? FloatToBits(apf.convertToFloat())
1530 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001531 } else {
1532 // Nonconstant element.
1533 return true;
1534 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001535
Scott Michel266bc8f2007-12-04 22:23:35 +00001536 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1537 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001538
1539 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001540 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1541 return false;
1542}
1543
1544/// If this is a splat (repetition) of a value across the whole vector, return
1545/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001546/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001547/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001548static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001549 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001550 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001551 uint64_t &SplatBits, uint64_t &SplatUndef,
1552 int &SplatSize) {
1553 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1554 // the same as the lower 64-bits, ignoring undefs.
1555 uint64_t Bits64 = Bits128[0] | Bits128[1];
1556 uint64_t Undef64 = Undef128[0] & Undef128[1];
1557 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1558 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1559 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1560 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1561
1562 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1563 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001564
Scott Michel266bc8f2007-12-04 22:23:35 +00001565 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1566 // undefs.
1567 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001568 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001569
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001570 // If the top 16-bits are different than the lower 16-bits, ignoring
1571 // undefs, we have an i32 splat.
1572 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1573 if (MinSplatBits < 16) {
1574 // If the top 8-bits are different than the lower 8-bits, ignoring
1575 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001576 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1577 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001578 // Otherwise, we have an 8-bit splat.
1579 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1580 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1581 SplatSize = 1;
1582 return true;
1583 }
1584 } else {
1585 SplatBits = Bits16;
1586 SplatUndef = Undef16;
1587 SplatSize = 2;
1588 return true;
1589 }
1590 }
1591 } else {
1592 SplatBits = Bits32;
1593 SplatUndef = Undef32;
1594 SplatSize = 4;
1595 return true;
1596 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001597 }
1598 } else {
1599 SplatBits = Bits128[0];
1600 SplatUndef = Undef128[0];
1601 SplatSize = 8;
1602 return true;
1603 }
1604 }
1605
1606 return false; // Can't be a splat if two pieces don't match.
1607}
1608
1609// If this is a case we can't handle, return null and let the default
1610// expansion code take care of it. If we CAN select this case, and if it
1611// selects to a single instruction, return Op. Otherwise, if we can codegen
1612// this case more efficiently than a constant pool load, lower it to the
1613// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001614static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001615 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001616 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001617 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001618 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001619 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001620 uint64_t VectorBits[2];
1621 uint64_t UndefBits[2];
1622 uint64_t SplatBits, SplatUndef;
1623 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001624 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001625 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001626 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001627 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001628 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001629
Duncan Sands83ec4b62008-06-06 12:08:01 +00001630 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001631 default:
1632 case MVT::v4f32: {
1633 uint32_t Value32 = SplatBits;
1634 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001635 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001636 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001637 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001638 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001639 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001640 break;
1641 }
1642 case MVT::v2f64: {
1643 uint64_t f64val = SplatBits;
1644 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001645 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001646 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001647 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001648 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001649 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001650 break;
1651 }
1652 case MVT::v16i8: {
1653 // 8-bit constants have to be expanded to 16-bits
1654 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001655 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001656 for (int i = 0; i < 8; ++i)
1657 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1658 return DAG.getNode(ISD::BIT_CONVERT, VT,
1659 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1660 }
1661 case MVT::v8i16: {
1662 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001663 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001664 Value16 = (unsigned short) (SplatBits & 0xffff);
1665 else
1666 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001667 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1668 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001669 for (int i = 0; i < 8; ++i) Ops[i] = T;
1670 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1671 }
1672 case MVT::v4i32: {
1673 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001674 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001675 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1676 }
1677 case MVT::v2i64: {
1678 uint64_t val = SplatBits;
1679 uint32_t upper = uint32_t(val >> 32);
1680 uint32_t lower = uint32_t(val);
1681
Scott Michel4cb8bd82008-03-06 04:02:54 +00001682 if (upper == lower) {
1683 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001684 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001685 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001686 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001687 SDValue LO32;
1688 SDValue HI32;
1689 SmallVector<SDValue, 16> ShufBytes;
1690 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001691 bool upper_special, lower_special;
1692
1693 // NOTE: This code creates common-case shuffle masks that can be easily
1694 // detected as common expressions. It is not attempting to create highly
1695 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1696
1697 // Detect if the upper or lower half is a special shuffle mask pattern:
1698 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1699 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1700
1701 // Create lower vector if not a special pattern
1702 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001703 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001704 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1705 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1706 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001707 }
1708
1709 // Create upper vector if not a special pattern
1710 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001711 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001712 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1713 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1714 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001715 }
1716
1717 // If either upper or lower are special, then the two input operands are
1718 // the same (basically, one of them is a "don't care")
1719 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001720 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001721 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001722 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001723 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001724 // Unhappy situation... both upper and lower are special, so punt with
1725 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001726 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001727 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001728 Zero, Zero);
1729 }
1730
1731 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001732 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001733 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001734 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001735 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001736 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001737 process_upper = (upper_special && (i & 1) == 0);
1738 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001739
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001740 if (process_upper || process_lower) {
1741 if ((process_upper && upper == 0)
1742 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001743 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001744 else if ((process_upper && upper == 0xffffffff)
1745 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001746 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001747 else if ((process_upper && upper == 0x80000000)
1748 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001749 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001750 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001751 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001752 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001753
1754 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001755 }
1756
1757 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001758 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001759 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001760 }
1761 }
1762 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001763
Dan Gohman475871a2008-07-27 21:46:04 +00001764 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001765}
1766
1767/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1768/// which the Cell can operate. The code inspects V3 to ascertain whether the
1769/// permutation vector, V3, is monotonically increasing with one "exception"
1770/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1771/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1772/// In either case, the net result is going to eventually invoke SHUFB to
1773/// permute/shuffle the bytes from V1 and V2.
1774/// \note
1775/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1776/// control word for byte/halfword/word insertion. This takes care of a single
1777/// element move from V2 into V1.
1778/// \note
1779/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001780static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1781 SDValue V1 = Op.getOperand(0);
1782 SDValue V2 = Op.getOperand(1);
1783 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001784
Scott Michel266bc8f2007-12-04 22:23:35 +00001785 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001786
Scott Michel266bc8f2007-12-04 22:23:35 +00001787 // If we have a single element being moved from V1 to V2, this can be handled
1788 // using the C*[DX] compute mask instructions, but the vector elements have
1789 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001790 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001791 unsigned EltsFromV2 = 0;
1792 unsigned V2Elt = 0;
1793 unsigned V2EltIdx0 = 0;
1794 unsigned CurrElt = 0;
1795 bool monotonic = true;
1796 if (EltVT == MVT::i8)
1797 V2EltIdx0 = 16;
1798 else if (EltVT == MVT::i16)
1799 V2EltIdx0 = 8;
1800 else if (EltVT == MVT::i32)
1801 V2EltIdx0 = 4;
1802 else
1803 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1804
1805 for (unsigned i = 0, e = PermMask.getNumOperands();
1806 EltsFromV2 <= 1 && monotonic && i != e;
1807 ++i) {
1808 unsigned SrcElt;
1809 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1810 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001811 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001812 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001813
1814 if (SrcElt >= V2EltIdx0) {
1815 ++EltsFromV2;
1816 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1817 } else if (CurrElt != SrcElt) {
1818 monotonic = false;
1819 }
1820
1821 ++CurrElt;
1822 }
1823
1824 if (EltsFromV2 == 1 && monotonic) {
1825 // Compute mask and shuffle
1826 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001827 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1828 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001829 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001830 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001831 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001832 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1833 // Copy register's contents as index in INSERT_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001834 SDValue ShufMaskOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001835 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001836 DAG.getTargetConstant(V2Elt, MVT::i32),
1837 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001838 // Use shuffle mask in SHUFB synthetic instruction:
1839 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1840 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001841 // Convert the SHUFFLE_VECTOR mask's input element units to the
1842 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001843 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001844
Dan Gohman475871a2008-07-27 21:46:04 +00001845 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001846 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1847 unsigned SrcElt;
1848 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001849 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001850 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001851 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001852
Scott Michela59d4692008-02-23 18:41:37 +00001853 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001854 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1855 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001856 }
1857 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001858
Dan Gohman475871a2008-07-27 21:46:04 +00001859 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001860 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001861 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1862 }
1863}
1864
Dan Gohman475871a2008-07-27 21:46:04 +00001865static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1866 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001867
Gabor Greifba36cb52008-08-28 21:40:38 +00001868 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001869 // For a constant, build the appropriate constant vector, which will
1870 // eventually simplify to a vector register load.
1871
Gabor Greifba36cb52008-08-28 21:40:38 +00001872 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001873 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001874 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001875 size_t n_copies;
1876
1877 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001878 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001879 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001880 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001881 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1882 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1883 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1884 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1885 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1886 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1887 }
1888
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001889 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001890 for (size_t j = 0; j < n_copies; ++j)
1891 ConstVecValues.push_back(CValue);
1892
1893 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001894 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001895 } else {
1896 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001897 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001898 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1899 case MVT::i8:
1900 case MVT::i16:
1901 case MVT::i32:
1902 case MVT::i64:
1903 case MVT::f32:
1904 case MVT::f64:
1905 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1906 }
1907 }
1908
Dan Gohman475871a2008-07-27 21:46:04 +00001909 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001910}
1911
Dan Gohman475871a2008-07-27 21:46:04 +00001912static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001913 switch (Op.getValueType().getSimpleVT()) {
1914 default:
1915 cerr << "CellSPU: Unknown vector multiplication, got "
1916 << Op.getValueType().getMVTString()
1917 << "\n";
1918 abort();
1919 /*NOTREACHED*/
1920
Scott Michel266bc8f2007-12-04 22:23:35 +00001921 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001922 SDValue rA = Op.getOperand(0);
1923 SDValue rB = Op.getOperand(1);
1924 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1925 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1926 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1927 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001928
1929 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1930 break;
1931 }
1932
1933 // Multiply two v8i16 vectors (pipeline friendly version):
1934 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1935 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1936 // c) Use SELB to select upper and lower halves from the intermediate results
1937 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001938 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001939 // dual-issue. This code does manage to do this, even if it's a little on
1940 // the wacky side
1941 case MVT::v8i16: {
1942 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001943 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001944 SDValue Chain = Op.getOperand(0);
1945 SDValue rA = Op.getOperand(0);
1946 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001947 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1948 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001949
Dan Gohman475871a2008-07-27 21:46:04 +00001950 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001951 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001952 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001953 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001954
Dan Gohman475871a2008-07-27 21:46:04 +00001955 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001956 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001957 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001958
Dan Gohman475871a2008-07-27 21:46:04 +00001959 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001960 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001961 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001962
1963 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001964 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1965 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1966 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1967 HHProd_v4i32,
1968 DAG.getConstant(16, MVT::i16))),
1969 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001970 }
1971
1972 // This M00sE is N@stI! (apologies to Monty Python)
1973 //
1974 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1975 // is to break it all apart, sign extend, and reassemble the various
1976 // intermediate products.
1977 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001978 SDValue rA = Op.getOperand(0);
1979 SDValue rB = Op.getOperand(1);
1980 SDValue c8 = DAG.getConstant(8, MVT::i32);
1981 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001982
Dan Gohman475871a2008-07-27 21:46:04 +00001983 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001984 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001985 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1986 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001987
Dan Gohman475871a2008-07-27 21:46:04 +00001988 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001989
Dan Gohman475871a2008-07-27 21:46:04 +00001990 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001991
Dan Gohman475871a2008-07-27 21:46:04 +00001992 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001993 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001994 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001995
Dan Gohman475871a2008-07-27 21:46:04 +00001996 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001997 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001998
Dan Gohman475871a2008-07-27 21:46:04 +00001999 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00002000 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2001 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2002 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002003
Dan Gohman475871a2008-07-27 21:46:04 +00002004 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002005
Dan Gohman475871a2008-07-27 21:46:04 +00002006 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002007 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00002008 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002009 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2010 LoProdMask, LoProdMask,
2011 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002012
Dan Gohman475871a2008-07-27 21:46:04 +00002013 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002014 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002015 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002016
Dan Gohman475871a2008-07-27 21:46:04 +00002017 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002018 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002019 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002020
Dan Gohman475871a2008-07-27 21:46:04 +00002021 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002022 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002023 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2024 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00002025
Dan Gohman475871a2008-07-27 21:46:04 +00002026 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002027 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002028 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002029 DAG.getNode(SPUISD::VEC_SRA,
2030 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002031 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002032 DAG.getNode(SPUISD::VEC_SRA,
2033 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002034
Dan Gohman475871a2008-07-27 21:46:04 +00002035 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00002036 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2037 HLProd,
2038 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2039 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002040
Dan Gohman475871a2008-07-27 21:46:04 +00002041 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002042 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002043
2044 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002045 DAG.getNode(ISD::OR, MVT::v4i32,
2046 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002047 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002048 }
2049
Dan Gohman475871a2008-07-27 21:46:04 +00002050 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002051}
2052
Dan Gohman475871a2008-07-27 21:46:04 +00002053static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002054 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002055 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002056
Dan Gohman475871a2008-07-27 21:46:04 +00002057 SDValue A = Op.getOperand(0);
2058 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002059 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002060
2061 unsigned VRegBR, VRegC;
2062
2063 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002064 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2065 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002066 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002067 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2068 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002069 }
2070 // TODO: make sure we're feeding FPInterp the right arguments
2071 // Right now: fi B, frest(B)
2072
2073 // Computes BRcpl =
2074 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002075 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002076 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2077 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002078 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002079
Scott Michel266bc8f2007-12-04 22:23:35 +00002080 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002081 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002082 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002083 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002084 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002085 // What's the Chain variable do? It's magic!
2086 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002087
2088 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002089 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002090 DAG.getNode(ISD::FMUL, VT,
2091 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002092 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002093 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002094 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002095}
2096
Dan Gohman475871a2008-07-27 21:46:04 +00002097static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002098 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002099 SDValue N = Op.getOperand(0);
2100 SDValue Elt = Op.getOperand(1);
2101 SDValue ShufMask[16];
Scott Michel266bc8f2007-12-04 22:23:35 +00002102 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
2103
2104 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2105
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002106 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002107
2108 // sanity checks:
2109 if (VT == MVT::i8 && EltNo >= 16)
2110 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2111 else if (VT == MVT::i16 && EltNo >= 8)
2112 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2113 else if (VT == MVT::i32 && EltNo >= 4)
2114 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2115 else if (VT == MVT::i64 && EltNo >= 2)
2116 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2117
2118 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2119 // i32 and i64: Element 0 is the preferred slot
2120 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2121 }
2122
2123 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002124 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002125 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002126
Duncan Sands83ec4b62008-06-06 12:08:01 +00002127 switch (VT.getSimpleVT()) {
2128 default:
2129 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002130 case MVT::i8: {
2131 prefslot_begin = prefslot_end = 3;
2132 break;
2133 }
2134 case MVT::i16: {
2135 prefslot_begin = 2; prefslot_end = 3;
2136 break;
2137 }
2138 case MVT::i32: {
2139 prefslot_begin = 0; prefslot_end = 3;
2140 break;
2141 }
2142 case MVT::i64: {
2143 prefslot_begin = 0; prefslot_end = 7;
2144 break;
2145 }
2146 }
2147
Scott Michel0e5665b2007-12-19 21:17:42 +00002148 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002149 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002150
Scott Michel266bc8f2007-12-04 22:23:35 +00002151 for (int i = 0; i < 16; ++i) {
2152 // zero fill uppper part of preferred slot, don't care about the
2153 // other slots:
2154 unsigned int mask_val;
2155
2156 if (i <= prefslot_end) {
2157 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002158 ((i < prefslot_begin)
2159 ? 0x80
2160 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002161
Scott Michel0e5665b2007-12-19 21:17:42 +00002162 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002163 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002164 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2165 }
2166
Dan Gohman475871a2008-07-27 21:46:04 +00002167 SDValue ShufMaskVec =
Scott Michel266bc8f2007-12-04 22:23:35 +00002168 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002169 &ShufMask[0],
2170 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002171
2172 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002173 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2174 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002175
Scott Michel266bc8f2007-12-04 22:23:35 +00002176}
2177
Dan Gohman475871a2008-07-27 21:46:04 +00002178static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2179 SDValue VecOp = Op.getOperand(0);
2180 SDValue ValOp = Op.getOperand(1);
2181 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002182 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002183
2184 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2185 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2186
Duncan Sands83ec4b62008-06-06 12:08:01 +00002187 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002188 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002189 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002190
Dan Gohman475871a2008-07-27 21:46:04 +00002191 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002192 DAG.getNode(SPUISD::SHUFB, VT,
2193 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2194 VecOp,
2195 DAG.getNode(SPUISD::INSERT_MASK, VT,
2196 DAG.getNode(ISD::ADD, PtrVT,
2197 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002198 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002199 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002200
2201 return result;
2202}
2203
Dan Gohman475871a2008-07-27 21:46:04 +00002204static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002205{
Dan Gohman475871a2008-07-27 21:46:04 +00002206 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002207
2208 assert(Op.getValueType() == MVT::i8);
2209 switch (Opc) {
2210 default:
2211 assert(0 && "Unhandled i8 math operator");
2212 /*NOTREACHED*/
2213 break;
2214 case ISD::SUB: {
2215 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2216 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002217 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002218 N0 = (N0.getOpcode() != ISD::Constant
2219 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002220 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2221 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002222 N1 = (N1.getOpcode() != ISD::Constant
2223 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002224 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2225 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002226 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002227 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002228 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002229 case ISD::ROTR:
2230 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002231 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002232 unsigned N1Opc;
2233 N0 = (N0.getOpcode() != ISD::Constant
2234 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002235 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2236 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002237 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2238 ? ISD::ZERO_EXTEND
2239 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002240 N1 = (N1.getOpcode() != ISD::Constant
2241 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002242 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2243 MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002244 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002245 DAG.getNode(ISD::OR, MVT::i16, N0,
2246 DAG.getNode(ISD::SHL, MVT::i16,
2247 N0, DAG.getConstant(8, MVT::i16)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002248 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002249 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2250 }
2251 case ISD::SRL:
2252 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002253 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002254 unsigned N1Opc;
2255 N0 = (N0.getOpcode() != ISD::Constant
2256 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002257 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2258 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002259 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2260 ? ISD::ZERO_EXTEND
2261 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002262 N1 = (N1.getOpcode() != ISD::Constant
2263 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002264 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2265 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002266 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002267 DAG.getNode(Opc, MVT::i16, N0, N1));
2268 }
2269 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002270 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002271 unsigned N1Opc;
2272 N0 = (N0.getOpcode() != ISD::Constant
2273 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002274 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2275 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002276 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2277 ? ISD::SIGN_EXTEND
2278 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002279 N1 = (N1.getOpcode() != ISD::Constant
2280 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002281 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2282 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002283 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002284 DAG.getNode(Opc, MVT::i16, N0, N1));
2285 }
2286 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002287 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002288 unsigned N1Opc;
2289 N0 = (N0.getOpcode() != ISD::Constant
2290 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002291 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2292 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002293 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002294 N1 = (N1.getOpcode() != ISD::Constant
2295 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002296 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2297 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002298 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002299 DAG.getNode(Opc, MVT::i16, N0, N1));
2300 break;
2301 }
2302 }
2303
Dan Gohman475871a2008-07-27 21:46:04 +00002304 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002305}
2306
Dan Gohman475871a2008-07-27 21:46:04 +00002307static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002308{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002309 MVT VT = Op.getValueType();
2310 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002311
Dan Gohman475871a2008-07-27 21:46:04 +00002312 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002313
2314 switch (Opc) {
2315 case ISD::ZERO_EXTEND:
2316 case ISD::SIGN_EXTEND:
2317 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002318 MVT Op0VT = Op0.getValueType();
2319 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002320
2321 assert(Op0VT == MVT::i32
2322 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002323 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002324
2325 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2326 ? SPUISD::ROTBYTES_RIGHT_S
2327 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002328 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002329 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2330
2331 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2332 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2333 DAG.getNode(NewOpc, Op0VecVT,
2334 PromoteScalar,
2335 DAG.getConstant(4, MVT::i32))));
2336 }
2337
Scott Michel8bf61e82008-06-02 22:18:03 +00002338 case ISD::ADD: {
2339 // Turn operands into vectors to satisfy type checking (shufb works on
2340 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002341 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002342 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002343 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002344 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002345 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002346
2347 // Create the shuffle mask for "rotating" the borrow up one register slot
2348 // once the borrow is generated.
2349 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2350 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2351 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2352 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2353
Dan Gohman475871a2008-07-27 21:46:04 +00002354 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002355 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002356 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002357 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2358 CarryGen, CarryGen,
2359 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2360 &ShufBytes[0], ShufBytes.size()));
2361
2362 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2363 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2364 Op0, Op1, ShiftedCarry));
2365 }
2366
2367 case ISD::SUB: {
2368 // Turn operands into vectors to satisfy type checking (shufb works on
2369 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002370 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002371 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002372 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002373 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002374 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002375
2376 // Create the shuffle mask for "rotating" the borrow up one register slot
2377 // once the borrow is generated.
2378 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2379 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2380 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2381 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2382
Dan Gohman475871a2008-07-27 21:46:04 +00002383 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002384 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002385 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002386 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2387 BorrowGen, BorrowGen,
2388 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2389 &ShufBytes[0], ShufBytes.size()));
2390
2391 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2392 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2393 Op0, Op1, ShiftedBorrow));
2394 }
2395
Scott Michela59d4692008-02-23 18:41:37 +00002396 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002397 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002398 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002399 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2400 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002401 DAG.getNode(SPUISD::SELB, VecVT,
2402 Op0Vec,
2403 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002404 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002405 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002406 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002407 DAG.getNode(ISD::SRL, ShiftAmtVT,
2408 ShiftAmt,
2409 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002410 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002411 DAG.getNode(ISD::AND, ShiftAmtVT,
2412 ShiftAmt,
2413 DAG.getConstant(7, ShiftAmtVT));
2414
2415 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2416 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2417 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2418 MaskLower, ShiftAmtBytes),
2419 ShiftAmtBits));
2420 }
2421
2422 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002423 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002424 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002425 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002426 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002427 DAG.getNode(ISD::SRL, ShiftAmtVT,
2428 ShiftAmt,
2429 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002430 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002431 DAG.getNode(ISD::AND, ShiftAmtVT,
2432 ShiftAmt,
2433 DAG.getConstant(7, ShiftAmtVT));
2434
2435 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2436 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2437 Op0, ShiftAmtBytes),
2438 ShiftAmtBits);
2439 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002440
2441 case ISD::SRA: {
2442 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002443 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002444 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002445 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002446 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002447
2448 // Negate variable shift amounts
2449 if (!isa<ConstantSDNode>(ShiftAmt)) {
2450 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2451 DAG.getConstant(0, ShiftVT), ShiftAmt);
2452 }
2453
Dan Gohman475871a2008-07-27 21:46:04 +00002454 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002455 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2456 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2457 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2458 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002459 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002460 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002461 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002462 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2463 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002464 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002465 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2466 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002467 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002468 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2469 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002470 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002471 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2472 RotateLeftBytes, ShiftAmt);
2473
2474 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2475 RotateLeftBits);
2476 }
Scott Michela59d4692008-02-23 18:41:37 +00002477 }
2478
Dan Gohman475871a2008-07-27 21:46:04 +00002479 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002480}
2481
Scott Michel266bc8f2007-12-04 22:23:35 +00002482//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002483static SDValue
2484LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2485 SDValue ConstVec;
2486 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002487 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002488
2489 ConstVec = Op.getOperand(0);
2490 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002491 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2492 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002493 ConstVec = ConstVec.getOperand(0);
2494 } else {
2495 ConstVec = Op.getOperand(1);
2496 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002497 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002498 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002499 }
2500 }
2501 }
2502
Gabor Greifba36cb52008-08-28 21:40:38 +00002503 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002504 uint64_t VectorBits[2];
2505 uint64_t UndefBits[2];
2506 uint64_t SplatBits, SplatUndef;
2507 int SplatSize;
2508
Gabor Greifba36cb52008-08-28 21:40:38 +00002509 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002510 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002511 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002512 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002513 SDValue tcVec[16];
2514 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002515 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2516
2517 // Turn the BUILD_VECTOR into a set of target constants:
2518 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002519 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002520
Gabor Greifba36cb52008-08-28 21:40:38 +00002521 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002522 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002523 }
2524 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002525 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2526 // lowered. Return the operation, rather than a null SDValue.
2527 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002528}
2529
2530//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002531static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002532 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002533 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002534 default:
2535 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002536 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002537 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002538 abort();
2539 /*NOTREACHED*/
2540
2541 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002542 SDValue rA = Op.getOperand(0);
2543 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002544
2545 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002546 DAG.getNode(ISD::ADD, MVT::i32,
2547 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2548 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2549 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002550 }
2551 }
2552
Dan Gohman475871a2008-07-27 21:46:04 +00002553 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002554}
2555
2556//! Custom lowering for CTPOP (count population)
2557/*!
2558 Custom lowering code that counts the number ones in the input
2559 operand. SPU has such an instruction, but it counts the number of
2560 ones per byte, which then have to be accumulated.
2561*/
Dan Gohman475871a2008-07-27 21:46:04 +00002562static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002563 MVT VT = Op.getValueType();
2564 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002565
Duncan Sands83ec4b62008-06-06 12:08:01 +00002566 switch (VT.getSimpleVT()) {
2567 default:
2568 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002569 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002570 SDValue N = Op.getOperand(0);
2571 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002572
Dan Gohman475871a2008-07-27 21:46:04 +00002573 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2574 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002575
2576 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2577 }
2578
2579 case MVT::i16: {
2580 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002581 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002582
Chris Lattner84bc5422007-12-31 04:13:23 +00002583 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002584
Dan Gohman475871a2008-07-27 21:46:04 +00002585 SDValue N = Op.getOperand(0);
2586 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2587 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
2588 SDValue Shift1 = DAG.getConstant(8, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002589
Dan Gohman475871a2008-07-27 21:46:04 +00002590 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2591 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002592
2593 // CNTB_result becomes the chain to which all of the virtual registers
2594 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002595 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002596 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002597
Dan Gohman475871a2008-07-27 21:46:04 +00002598 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002599 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2600
Dan Gohman475871a2008-07-27 21:46:04 +00002601 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002602
2603 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002604 DAG.getNode(ISD::ADD, MVT::i16,
2605 DAG.getNode(ISD::SRL, MVT::i16,
2606 Tmp1, Shift1),
2607 Tmp1),
2608 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002609 }
2610
2611 case MVT::i32: {
2612 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002613 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002614
Chris Lattner84bc5422007-12-31 04:13:23 +00002615 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2616 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002617
Dan Gohman475871a2008-07-27 21:46:04 +00002618 SDValue N = Op.getOperand(0);
2619 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2620 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2621 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2622 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002623
Dan Gohman475871a2008-07-27 21:46:04 +00002624 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2625 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002626
2627 // CNTB_result becomes the chain to which all of the virtual registers
2628 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002629 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002630 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002631
Dan Gohman475871a2008-07-27 21:46:04 +00002632 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002633 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2634
Dan Gohman475871a2008-07-27 21:46:04 +00002635 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002636 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002637 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002638
Dan Gohman475871a2008-07-27 21:46:04 +00002639 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002640 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002641 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002642
Dan Gohman475871a2008-07-27 21:46:04 +00002643 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002644 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2645
Dan Gohman475871a2008-07-27 21:46:04 +00002646 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002647 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002648 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2649 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002650 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002651 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002652 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002653
2654 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2655 }
2656
2657 case MVT::i64:
2658 break;
2659 }
2660
Dan Gohman475871a2008-07-27 21:46:04 +00002661 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002662}
2663
2664/// LowerOperation - Provide custom lowering hooks for some operations.
2665///
Dan Gohman475871a2008-07-27 21:46:04 +00002666SDValue
2667SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002668{
Scott Michela59d4692008-02-23 18:41:37 +00002669 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002670 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002671
2672 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002673 default: {
2674 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002675 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002676 cerr << "*Op.getNode():\n";
2677 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002678 abort();
2679 }
2680 case ISD::LOAD:
2681 case ISD::SEXTLOAD:
2682 case ISD::ZEXTLOAD:
2683 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2684 case ISD::STORE:
2685 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2686 case ISD::ConstantPool:
2687 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2688 case ISD::GlobalAddress:
2689 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2690 case ISD::JumpTable:
2691 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2692 case ISD::Constant:
2693 return LowerConstant(Op, DAG);
2694 case ISD::ConstantFP:
2695 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002696 case ISD::BRCOND:
2697 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002698 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002699 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002700 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002701 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002702 case ISD::RET:
2703 return LowerRET(Op, DAG, getTargetMachine());
2704
Scott Michela59d4692008-02-23 18:41:37 +00002705
2706 // i8, i64 math ops:
2707 case ISD::ZERO_EXTEND:
2708 case ISD::SIGN_EXTEND:
2709 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002710 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002711 case ISD::SUB:
2712 case ISD::ROTR:
2713 case ISD::ROTL:
2714 case ISD::SRL:
2715 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002716 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002717 if (VT == MVT::i8)
2718 return LowerI8Math(Op, DAG, Opc);
2719 else if (VT == MVT::i64)
2720 return LowerI64Math(Op, DAG, Opc);
2721 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002722 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002723
2724 // Vector-related lowering.
2725 case ISD::BUILD_VECTOR:
2726 return LowerBUILD_VECTOR(Op, DAG);
2727 case ISD::SCALAR_TO_VECTOR:
2728 return LowerSCALAR_TO_VECTOR(Op, DAG);
2729 case ISD::VECTOR_SHUFFLE:
2730 return LowerVECTOR_SHUFFLE(Op, DAG);
2731 case ISD::EXTRACT_VECTOR_ELT:
2732 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2733 case ISD::INSERT_VECTOR_ELT:
2734 return LowerINSERT_VECTOR_ELT(Op, DAG);
2735
2736 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2737 case ISD::AND:
2738 case ISD::OR:
2739 case ISD::XOR:
2740 return LowerByteImmed(Op, DAG);
2741
2742 // Vector and i8 multiply:
2743 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002744 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002745 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002746 else if (VT == MVT::i8)
2747 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002748 else
Scott Michela59d4692008-02-23 18:41:37 +00002749 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002750
2751 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002752 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002753 return LowerFDIVf32(Op, DAG);
2754// else if (Op.getValueType() == MVT::f64)
2755// return LowerFDIVf64(Op, DAG);
2756 else
2757 assert(0 && "Calling FDIV on unsupported MVT");
2758
2759 case ISD::CTPOP:
2760 return LowerCTPOP(Op, DAG);
2761 }
2762
Dan Gohman475871a2008-07-27 21:46:04 +00002763 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002764}
2765
2766//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002767// Target Optimization Hooks
2768//===----------------------------------------------------------------------===//
2769
Dan Gohman475871a2008-07-27 21:46:04 +00002770SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002771SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2772{
2773#if 0
2774 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002775#endif
2776 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002777 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002778 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2779 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002780
2781 switch (N->getOpcode()) {
2782 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002783 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002784 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002785
Scott Michel8bf61e82008-06-02 22:18:03 +00002786 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002787 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002788 if (Op01.getOpcode() == ISD::Constant
2789 || Op01.getOpcode() == ISD::TargetConstant) {
2790 // (add <const>, (SPUindirect <arg>, <const>)) ->
2791 // (SPUindirect <arg>, <const + const>)
2792 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2793 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002794 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002795 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002796 Op0.getValueType());
2797
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002798 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2799 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002800 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002801 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002802 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2803 Op0.getOperand(0), combinedConst);
2804 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002805 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002806 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002807 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002808 if (Op11.getOpcode() == ISD::Constant
2809 || Op11.getOpcode() == ISD::TargetConstant) {
2810 // (add (SPUindirect <arg>, <const>), <const>) ->
2811 // (SPUindirect <arg>, <const + const>)
2812 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2813 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002814 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002815 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002816 Op0.getValueType());
2817
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002818 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2819 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002820 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002821 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002822
2823 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2824 Op1.getOperand(0), combinedConst);
2825 }
2826 }
Scott Michela59d4692008-02-23 18:41:37 +00002827 break;
2828 }
2829 case ISD::SIGN_EXTEND:
2830 case ISD::ZERO_EXTEND:
2831 case ISD::ANY_EXTEND: {
2832 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2833 N->getValueType(0) == Op0.getValueType()) {
2834 // (any_extend (SPUextract_elt0 <arg>)) ->
2835 // (SPUextract_elt0 <arg>)
2836 // Types must match, however...
2837 DEBUG(cerr << "Replace: ");
2838 DEBUG(N->dump(&DAG));
2839 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002840 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002841 DEBUG(cerr << "\n");
2842
2843 return Op0;
2844 }
2845 break;
2846 }
2847 case SPUISD::IndirectAddr: {
2848 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2849 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002850 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002851 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2852 // (SPUaform <addr>, 0)
2853
2854 DEBUG(cerr << "Replace: ");
2855 DEBUG(N->dump(&DAG));
2856 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002857 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002858 DEBUG(cerr << "\n");
2859
2860 return Op0;
2861 }
2862 }
2863 break;
2864 }
2865 case SPUISD::SHLQUAD_L_BITS:
2866 case SPUISD::SHLQUAD_L_BYTES:
2867 case SPUISD::VEC_SHL:
2868 case SPUISD::VEC_SRL:
2869 case SPUISD::VEC_SRA:
2870 case SPUISD::ROTQUAD_RZ_BYTES:
2871 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002872 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002873
2874 if (isa<ConstantSDNode>(Op1)) {
2875 // Kill degenerate vector shifts:
2876 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2877
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002878 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002879 Result = Op0;
2880 }
2881 }
2882 break;
2883 }
2884 case SPUISD::PROMOTE_SCALAR: {
2885 switch (Op0.getOpcode()) {
2886 default:
2887 break;
2888 case ISD::ANY_EXTEND:
2889 case ISD::ZERO_EXTEND:
2890 case ISD::SIGN_EXTEND: {
2891 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2892 // <arg>
2893 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002894 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002895 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00002896 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002897 if (Op000.getValueType() == N->getValueType(0)) {
2898 Result = Op000;
2899 }
2900 }
2901 break;
2902 }
2903 case SPUISD::EXTRACT_ELT0: {
2904 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2905 // <arg>
2906 Result = Op0.getOperand(0);
2907 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002908 }
Scott Michela59d4692008-02-23 18:41:37 +00002909 }
2910 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002911 }
2912 }
Scott Michel58c58182008-01-17 20:38:41 +00002913 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002914#if 1
Gabor Greifba36cb52008-08-28 21:40:38 +00002915 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00002916 DEBUG(cerr << "\nReplace.SPU: ");
2917 DEBUG(N->dump(&DAG));
2918 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002919 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002920 DEBUG(cerr << "\n");
2921 }
2922#endif
2923
2924 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002925}
2926
2927//===----------------------------------------------------------------------===//
2928// Inline Assembly Support
2929//===----------------------------------------------------------------------===//
2930
2931/// getConstraintType - Given a constraint letter, return the type of
2932/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002933SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002934SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2935 if (ConstraintLetter.size() == 1) {
2936 switch (ConstraintLetter[0]) {
2937 default: break;
2938 case 'b':
2939 case 'r':
2940 case 'f':
2941 case 'v':
2942 case 'y':
2943 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002944 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002945 }
2946 return TargetLowering::getConstraintType(ConstraintLetter);
2947}
2948
Scott Michel5af8f0e2008-07-16 17:17:29 +00002949std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002950SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002951 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002952{
2953 if (Constraint.size() == 1) {
2954 // GCC RS6000 Constraint Letters
2955 switch (Constraint[0]) {
2956 case 'b': // R1-R31
2957 case 'r': // R0-R31
2958 if (VT == MVT::i64)
2959 return std::make_pair(0U, SPU::R64CRegisterClass);
2960 return std::make_pair(0U, SPU::R32CRegisterClass);
2961 case 'f':
2962 if (VT == MVT::f32)
2963 return std::make_pair(0U, SPU::R32FPRegisterClass);
2964 else if (VT == MVT::f64)
2965 return std::make_pair(0U, SPU::R64FPRegisterClass);
2966 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002967 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002968 return std::make_pair(0U, SPU::GPRCRegisterClass);
2969 }
2970 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002971
Scott Michel266bc8f2007-12-04 22:23:35 +00002972 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2973}
2974
Scott Michela59d4692008-02-23 18:41:37 +00002975//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002976void
Dan Gohman475871a2008-07-27 21:46:04 +00002977SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002978 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002979 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002980 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002981 const SelectionDAG &DAG,
2982 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002983#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002984 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002985#endif
Scott Michela59d4692008-02-23 18:41:37 +00002986
2987 switch (Op.getOpcode()) {
2988 default:
2989 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2990 break;
2991
2992#if 0
2993 case CALL:
2994 case SHUFB:
2995 case INSERT_MASK:
2996 case CNTB:
2997#endif
2998
2999 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00003000 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00003001 MVT Op0VT = Op0.getValueType();
3002 unsigned Op0VTBits = Op0VT.getSizeInBits();
3003 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003004 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3005 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003006 break;
3007 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003008
Scott Michela59d4692008-02-23 18:41:37 +00003009 case SPUISD::LDRESULT:
3010 case SPUISD::EXTRACT_ELT0:
3011 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00003012 MVT OpVT = Op.getValueType();
3013 unsigned OpVTBits = OpVT.getSizeInBits();
3014 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003015 KnownZero |= APInt(OpVTBits, ~InMask, false);
3016 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003017 break;
3018 }
3019
3020#if 0
3021 case EXTRACT_I1_ZEXT:
3022 case EXTRACT_I1_SEXT:
3023 case EXTRACT_I8_ZEXT:
3024 case EXTRACT_I8_SEXT:
3025 case MPY:
3026 case MPYU:
3027 case MPYH:
3028 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003029 case SPUISD::SHLQUAD_L_BITS:
3030 case SPUISD::SHLQUAD_L_BYTES:
3031 case SPUISD::VEC_SHL:
3032 case SPUISD::VEC_SRL:
3033 case SPUISD::VEC_SRA:
3034 case SPUISD::VEC_ROTL:
3035 case SPUISD::VEC_ROTR:
3036 case SPUISD::ROTQUAD_RZ_BYTES:
3037 case SPUISD::ROTQUAD_RZ_BITS:
3038 case SPUISD::ROTBYTES_RIGHT_S:
3039 case SPUISD::ROTBYTES_LEFT:
3040 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003041 case SPUISD::SELECT_MASK:
3042 case SPUISD::SELB:
3043 case SPUISD::FPInterp:
3044 case SPUISD::FPRecipEst:
3045 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003046#endif
3047 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003048}
3049
Scott Michel203b2d62008-04-30 00:30:08 +00003050// LowerAsmOperandForConstraint
3051void
Dan Gohman475871a2008-07-27 21:46:04 +00003052SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003053 char ConstraintLetter,
Dan Gohman475871a2008-07-27 21:46:04 +00003054 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003055 SelectionDAG &DAG) const {
3056 // Default, for the time being, to the base class handler
3057 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, Ops, DAG);
3058}
3059
Scott Michel266bc8f2007-12-04 22:23:35 +00003060/// isLegalAddressImmediate - Return true if the integer value can be used
3061/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003062bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3063 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003064 // SPU's addresses are 256K:
3065 return (V > -(1 << 18) && V < (1 << 18) - 1);
3066}
3067
3068bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003069 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003070}