blob: 384755d6657b239e7b895772029bf97e5ac5ade6 [file] [log] [blame]
Scott Michel266bc8f2007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel266bc8f2007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SPUTargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPURegisterNames.h"
15#include "SPUISelLowering.h"
16#include "SPUTargetMachine.h"
Scott Michel203b2d62008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000018#include "llvm/ADT/VectorExtras.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000019#include "llvm/CodeGen/CallingConvLower.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner84bc5422007-12-31 04:13:23 +000023#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000025#include "llvm/Constants.h"
26#include "llvm/Function.h"
27#include "llvm/Intrinsics.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/MathExtras.h"
30#include "llvm/Target/TargetOptions.h"
31
32#include <map>
33
34using namespace llvm;
35
36// Used in getTargetNodeName() below
37namespace {
38 std::map<unsigned, const char *> node_names;
39
Duncan Sands83ec4b62008-06-06 12:08:01 +000040 //! MVT mapping to useful data for Cell SPU
Scott Michel266bc8f2007-12-04 22:23:35 +000041 struct valtype_map_s {
Duncan Sands83ec4b62008-06-06 12:08:01 +000042 const MVT valtype;
Scott Michel7f9ba9b2008-01-30 02:55:46 +000043 const int prefslot_byte;
Scott Michel266bc8f2007-12-04 22:23:35 +000044 };
Scott Michel5af8f0e2008-07-16 17:17:29 +000045
Scott Michel266bc8f2007-12-04 22:23:35 +000046 const valtype_map_s valtype_map[] = {
47 { MVT::i1, 3 },
48 { MVT::i8, 3 },
49 { MVT::i16, 2 },
50 { MVT::i32, 0 },
51 { MVT::f32, 0 },
52 { MVT::i64, 0 },
53 { MVT::f64, 0 },
54 { MVT::i128, 0 }
55 };
56
57 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
58
Duncan Sands83ec4b62008-06-06 12:08:01 +000059 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel266bc8f2007-12-04 22:23:35 +000060 const valtype_map_s *retval = 0;
61
62 for (size_t i = 0; i < n_valtype_map; ++i) {
63 if (valtype_map[i].valtype == VT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +000064 retval = valtype_map + i;
65 break;
Scott Michel266bc8f2007-12-04 22:23:35 +000066 }
67 }
68
69#ifndef NDEBUG
70 if (retval == 0) {
71 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands83ec4b62008-06-06 12:08:01 +000072 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +000073 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +000074 abort();
75 }
76#endif
77
78 return retval;
79 }
80
81 //! Predicate that returns true if operand is a memory target
82 /*!
83 \arg Op Operand to test
84 \return true if the operand is a memory target (i.e., global
Scott Michel9de5d0d2008-01-11 02:53:15 +000085 address, external symbol, constant pool) or an A-form
Scott Michel266bc8f2007-12-04 22:23:35 +000086 address.
87 */
Dan Gohman475871a2008-07-27 21:46:04 +000088 bool isMemoryOperand(const SDValue &Op)
Scott Michel266bc8f2007-12-04 22:23:35 +000089 {
90 const unsigned Opc = Op.getOpcode();
91 return (Opc == ISD::GlobalAddress
92 || Opc == ISD::GlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000093 || Opc == ISD::JumpTable
94 || Opc == ISD::ConstantPool
95 || Opc == ISD::ExternalSymbol
96 || Opc == ISD::TargetGlobalAddress
97 || Opc == ISD::TargetGlobalTLSAddress
Scott Michel266bc8f2007-12-04 22:23:35 +000098 || Opc == ISD::TargetJumpTable
99 || Opc == ISD::TargetConstantPool
100 || Opc == ISD::TargetExternalSymbol
Scott Michel9de5d0d2008-01-11 02:53:15 +0000101 || Opc == SPUISD::AFormAddr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000102 }
Scott Michel58c58182008-01-17 20:38:41 +0000103
104 //! Predicate that returns true if the operand is an indirect target
Dan Gohman475871a2008-07-27 21:46:04 +0000105 bool isIndirectOperand(const SDValue &Op)
Scott Michel58c58182008-01-17 20:38:41 +0000106 {
107 const unsigned Opc = Op.getOpcode();
108 return (Opc == ISD::Register
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000109 || Opc == SPUISD::LDRESULT);
Scott Michel58c58182008-01-17 20:38:41 +0000110 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000111}
112
113SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
114 : TargetLowering(TM),
115 SPUTM(TM)
116{
117 // Fold away setcc operations if possible.
118 setPow2DivIsCheap();
119
120 // Use _setjmp/_longjmp instead of setjmp/longjmp.
121 setUseUnderscoreSetJmp(true);
122 setUseUnderscoreLongJmp(true);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000123
Scott Michel266bc8f2007-12-04 22:23:35 +0000124 // Set up the SPU's register classes:
Scott Michel504c3692007-12-17 22:32:34 +0000125 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
126 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
127 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
128 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
129 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
130 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel266bc8f2007-12-04 22:23:35 +0000131 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000132
Scott Michel266bc8f2007-12-04 22:23:35 +0000133 // SPU has no sign or zero extended loads for i1, i8, i16:
Scott Michel58c58182008-01-17 20:38:41 +0000134 setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +0000135 setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote);
136 setLoadXAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Chris Lattnerddf89562008-01-17 19:59:44 +0000137 setTruncStoreAction(MVT::i8, MVT::i1, Custom);
138 setTruncStoreAction(MVT::i16, MVT::i1, Custom);
139 setTruncStoreAction(MVT::i32, MVT::i1, Custom);
140 setTruncStoreAction(MVT::i64, MVT::i1, Custom);
141 setTruncStoreAction(MVT::i128, MVT::i1, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000142
143 setLoadXAction(ISD::EXTLOAD, MVT::i8, Custom);
144 setLoadXAction(ISD::SEXTLOAD, MVT::i8, Custom);
145 setLoadXAction(ISD::ZEXTLOAD, MVT::i8, Custom);
Chris Lattnerddf89562008-01-17 19:59:44 +0000146 setTruncStoreAction(MVT::i8 , MVT::i8, Custom);
147 setTruncStoreAction(MVT::i16 , MVT::i8, Custom);
148 setTruncStoreAction(MVT::i32 , MVT::i8, Custom);
149 setTruncStoreAction(MVT::i64 , MVT::i8, Custom);
150 setTruncStoreAction(MVT::i128, MVT::i8, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000151
Scott Michel266bc8f2007-12-04 22:23:35 +0000152 setLoadXAction(ISD::EXTLOAD, MVT::i16, Custom);
153 setLoadXAction(ISD::SEXTLOAD, MVT::i16, Custom);
154 setLoadXAction(ISD::ZEXTLOAD, MVT::i16, Custom);
155
156 // SPU constant load actions are custom lowered:
157 setOperationAction(ISD::Constant, MVT::i64, Custom);
Nate Begemanccef5802008-02-14 18:43:04 +0000158 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000159 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
160
161 // SPU's loads and stores have to be custom lowered:
162 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
163 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000164 MVT VT = (MVT::SimpleValueType)sctype;
165
166 setOperationAction(ISD::LOAD, VT, Custom);
167 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000168 }
169
Scott Michel58c58182008-01-17 20:38:41 +0000170 // Custom lower BRCOND for i1, i8 to "promote" the result to
171 // i32 and i16, respectively.
172 setOperationAction(ISD::BRCOND, MVT::Other, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000173
174 // Expand the jumptable branches
175 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
176 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000177 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000178
179 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000180 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
181
Scott Michel266bc8f2007-12-04 22:23:35 +0000182 // PowerPC has no SREM/UREM instructions
183 setOperationAction(ISD::SREM, MVT::i32, Expand);
184 setOperationAction(ISD::UREM, MVT::i32, Expand);
185 setOperationAction(ISD::SREM, MVT::i64, Expand);
186 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000187
Scott Michel266bc8f2007-12-04 22:23:35 +0000188 // We don't support sin/cos/sqrt/fmod
189 setOperationAction(ISD::FSIN , MVT::f64, Expand);
190 setOperationAction(ISD::FCOS , MVT::f64, Expand);
191 setOperationAction(ISD::FREM , MVT::f64, Expand);
Dale Johannesen7794f2a2008-09-04 00:47:13 +0000192 setOperationAction(ISD::FLOG , MVT::f64, Expand);
193 setOperationAction(ISD::FLOG2, MVT::f64, Expand);
194 setOperationAction(ISD::FLOG10,MVT::f64, Expand);
195 setOperationAction(ISD::FEXP , MVT::f64, Expand);
196 setOperationAction(ISD::FEXP2, MVT::f64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000197 setOperationAction(ISD::FSIN , MVT::f32, Expand);
198 setOperationAction(ISD::FCOS , MVT::f32, Expand);
199 setOperationAction(ISD::FREM , MVT::f32, Expand);
Dale Johannesen7794f2a2008-09-04 00:47:13 +0000200 setOperationAction(ISD::FLOG , MVT::f32, Expand);
201 setOperationAction(ISD::FLOG2, MVT::f32, Expand);
202 setOperationAction(ISD::FLOG10,MVT::f32, Expand);
203 setOperationAction(ISD::FEXP , MVT::f32, Expand);
204 setOperationAction(ISD::FEXP2, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000205
Scott Michel266bc8f2007-12-04 22:23:35 +0000206 // If we're enabling GP optimizations, use hardware square root
207 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
208 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000209
Scott Michel266bc8f2007-12-04 22:23:35 +0000210 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
211 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
212
213 // SPU can do rotate right and left, so legalize it... but customize for i8
214 // because instructions don't exist.
Bill Wendling9440e352008-08-31 02:59:23 +0000215
216 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
217 // .td files.
218 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
219 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
220 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
221
Scott Michel266bc8f2007-12-04 22:23:35 +0000222 setOperationAction(ISD::ROTL, MVT::i32, Legal);
223 setOperationAction(ISD::ROTL, MVT::i16, Legal);
224 setOperationAction(ISD::ROTL, MVT::i8, Custom);
225 // SPU has no native version of shift left/right for i8
226 setOperationAction(ISD::SHL, MVT::i8, Custom);
227 setOperationAction(ISD::SRL, MVT::i8, Custom);
228 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michela59d4692008-02-23 18:41:37 +0000229 // And SPU needs custom lowering for shift left/right for i64
230 setOperationAction(ISD::SHL, MVT::i64, Custom);
231 setOperationAction(ISD::SRL, MVT::i64, Custom);
232 setOperationAction(ISD::SRA, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000233
Scott Michel5af8f0e2008-07-16 17:17:29 +0000234 // Custom lower i8, i32 and i64 multiplications
235 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000236 setOperationAction(ISD::MUL, MVT::i32, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000237 setOperationAction(ISD::MUL, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000238
Scott Michel8bf61e82008-06-02 22:18:03 +0000239 // Need to custom handle (some) common i8, i64 math ops
240 setOperationAction(ISD::ADD, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000241 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel8bf61e82008-06-02 22:18:03 +0000242 setOperationAction(ISD::SUB, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000243
Scott Michel266bc8f2007-12-04 22:23:35 +0000244 // SPU does not have BSWAP. It does have i32 support CTLZ.
245 // CTPOP has to be custom lowered.
246 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
247 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
248
249 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
250 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
251 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
252 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
253
254 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
255 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
256
257 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000258
Scott Michel8bf61e82008-06-02 22:18:03 +0000259 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000260 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000261 setOperationAction(ISD::SELECT, MVT::i1, Promote);
262 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000263 setOperationAction(ISD::SELECT, MVT::i16, Legal);
264 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000265 setOperationAction(ISD::SELECT, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000266
Scott Michel78c47fa2008-03-10 16:58:52 +0000267 setOperationAction(ISD::SETCC, MVT::i1, Promote);
268 setOperationAction(ISD::SETCC, MVT::i8, Legal);
269 setOperationAction(ISD::SETCC, MVT::i16, Legal);
270 setOperationAction(ISD::SETCC, MVT::i32, Legal);
271 setOperationAction(ISD::SETCC, MVT::i64, Expand);
Scott Michelad2715e2008-03-05 23:02:02 +0000272
Scott Michela59d4692008-02-23 18:41:37 +0000273 // Zero extension and sign extension for i64 have to be
274 // custom legalized
275 setOperationAction(ISD::ZERO_EXTEND, MVT::i64, Custom);
276 setOperationAction(ISD::SIGN_EXTEND, MVT::i64, Custom);
277 setOperationAction(ISD::ANY_EXTEND, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000278
Scott Michel266bc8f2007-12-04 22:23:35 +0000279 // SPU has a legal FP -> signed INT instruction
280 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
281 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
282 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
283 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
284
285 // FDIV on SPU requires custom lowering
286 setOperationAction(ISD::FDIV, MVT::f32, Custom);
287 //setOperationAction(ISD::FDIV, MVT::f64, Custom);
288
289 // SPU has [U|S]INT_TO_FP
290 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
291 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
292 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
293 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
294 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
295 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
296 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
297 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
298
Scott Michel86c041f2007-12-20 00:44:13 +0000299 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
300 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
301 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
302 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000303
304 // We cannot sextinreg(i1). Expand to shifts.
305 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000306
Scott Michel266bc8f2007-12-04 22:23:35 +0000307 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000308 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000309 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000310
311 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000312 // appropriate instructions to materialize the address.
Scott Michel053c1da2008-01-29 02:16:57 +0000313 for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
314 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000315 MVT VT = (MVT::SimpleValueType)sctype;
316
317 setOperationAction(ISD::GlobalAddress, VT, Custom);
318 setOperationAction(ISD::ConstantPool, VT, Custom);
319 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000320 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000321
322 // RET must be custom lowered, to meet ABI requirements
323 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000324
Scott Michel266bc8f2007-12-04 22:23:35 +0000325 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
326 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000327
Scott Michel266bc8f2007-12-04 22:23:35 +0000328 // Use the default implementation.
329 setOperationAction(ISD::VAARG , MVT::Other, Expand);
330 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
331 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000332 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000333 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
334 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
335 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
336
337 // Cell SPU has instructions for converting between i64 and fp.
338 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
339 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000340
Scott Michel266bc8f2007-12-04 22:23:35 +0000341 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
342 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
343
344 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
345 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
346
347 // First set operation action for all vector types to expand. Then we
348 // will selectively turn on ones that can be effectively codegen'd.
349 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
350 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
351 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
352 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
353 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
354 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
355
Duncan Sands83ec4b62008-06-06 12:08:01 +0000356 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
357 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
358 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000359
Duncan Sands83ec4b62008-06-06 12:08:01 +0000360 // add/sub are legal for all supported vector VT's.
361 setOperationAction(ISD::ADD , VT, Legal);
362 setOperationAction(ISD::SUB , VT, Legal);
363 // mul has to be custom lowered.
364 setOperationAction(ISD::MUL , VT, Custom);
365
366 setOperationAction(ISD::AND , VT, Legal);
367 setOperationAction(ISD::OR , VT, Legal);
368 setOperationAction(ISD::XOR , VT, Legal);
369 setOperationAction(ISD::LOAD , VT, Legal);
370 setOperationAction(ISD::SELECT, VT, Legal);
371 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000372
Scott Michel266bc8f2007-12-04 22:23:35 +0000373 // These operations need to be expanded:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000374 setOperationAction(ISD::SDIV, VT, Expand);
375 setOperationAction(ISD::SREM, VT, Expand);
376 setOperationAction(ISD::UDIV, VT, Expand);
377 setOperationAction(ISD::UREM, VT, Expand);
378 setOperationAction(ISD::FDIV, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000379
380 // Custom lower build_vector, constant pool spills, insert and
381 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000382 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
383 setOperationAction(ISD::ConstantPool, VT, Custom);
384 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
385 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
386 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
387 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000388 }
389
390 setOperationAction(ISD::MUL, MVT::v16i8, Custom);
391 setOperationAction(ISD::AND, MVT::v16i8, Custom);
392 setOperationAction(ISD::OR, MVT::v16i8, Custom);
393 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
394 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000395
Scott Michel266bc8f2007-12-04 22:23:35 +0000396 setShiftAmountType(MVT::i32);
397 setSetCCResultContents(ZeroOrOneSetCCResult);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000398
Scott Michel266bc8f2007-12-04 22:23:35 +0000399 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000400
Scott Michel266bc8f2007-12-04 22:23:35 +0000401 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000402 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000403 setTargetDAGCombine(ISD::ZERO_EXTEND);
404 setTargetDAGCombine(ISD::SIGN_EXTEND);
405 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000406
Scott Michel266bc8f2007-12-04 22:23:35 +0000407 computeRegisterProperties();
408}
409
410const char *
411SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
412{
413 if (node_names.empty()) {
414 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
415 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
416 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
417 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000418 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000419 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000420 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
421 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
422 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
423 node_names[(unsigned) SPUISD::INSERT_MASK] = "SPUISD::INSERT_MASK";
424 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
425 node_names[(unsigned) SPUISD::PROMOTE_SCALAR] = "SPUISD::PROMOTE_SCALAR";
426 node_names[(unsigned) SPUISD::EXTRACT_ELT0] = "SPUISD::EXTRACT_ELT0";
Gabor Greif93c53e52008-08-31 15:37:04 +0000427 node_names[(unsigned) SPUISD::EXTRACT_ELT0_CHAINED]
428 = "SPUISD::EXTRACT_ELT0_CHAINED";
Scott Michel266bc8f2007-12-04 22:23:35 +0000429 node_names[(unsigned) SPUISD::EXTRACT_I1_ZEXT] = "SPUISD::EXTRACT_I1_ZEXT";
430 node_names[(unsigned) SPUISD::EXTRACT_I1_SEXT] = "SPUISD::EXTRACT_I1_SEXT";
431 node_names[(unsigned) SPUISD::EXTRACT_I8_ZEXT] = "SPUISD::EXTRACT_I8_ZEXT";
432 node_names[(unsigned) SPUISD::EXTRACT_I8_SEXT] = "SPUISD::EXTRACT_I8_SEXT";
433 node_names[(unsigned) SPUISD::MPY] = "SPUISD::MPY";
434 node_names[(unsigned) SPUISD::MPYU] = "SPUISD::MPYU";
435 node_names[(unsigned) SPUISD::MPYH] = "SPUISD::MPYH";
436 node_names[(unsigned) SPUISD::MPYHH] = "SPUISD::MPYHH";
Scott Michela59d4692008-02-23 18:41:37 +0000437 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
438 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000439 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
440 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
441 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
442 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
443 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Michela59d4692008-02-23 18:41:37 +0000444 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BYTES] =
445 "SPUISD::ROTQUAD_RZ_BYTES";
446 node_names[(unsigned) SPUISD::ROTQUAD_RZ_BITS] =
447 "SPUISD::ROTQUAD_RZ_BITS";
Scott Michel266bc8f2007-12-04 22:23:35 +0000448 node_names[(unsigned) SPUISD::ROTBYTES_RIGHT_S] =
449 "SPUISD::ROTBYTES_RIGHT_S";
450 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
451 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_CHAINED] =
452 "SPUISD::ROTBYTES_LEFT_CHAINED";
Scott Michel8bf61e82008-06-02 22:18:03 +0000453 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
454 "SPUISD::ROTBYTES_LEFT_BITS";
455 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000456 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel8bf61e82008-06-02 22:18:03 +0000457 node_names[(unsigned) SPUISD::ADD_EXTENDED] = "SPUISD::ADD_EXTENDED";
458 node_names[(unsigned) SPUISD::CARRY_GENERATE] = "SPUISD::CARRY_GENERATE";
459 node_names[(unsigned) SPUISD::SUB_EXTENDED] = "SPUISD::SUB_EXTENDED";
460 node_names[(unsigned) SPUISD::BORROW_GENERATE] = "SPUISD::BORROW_GENERATE";
Scott Michel266bc8f2007-12-04 22:23:35 +0000461 node_names[(unsigned) SPUISD::FPInterp] = "SPUISD::FPInterp";
462 node_names[(unsigned) SPUISD::FPRecipEst] = "SPUISD::FPRecipEst";
463 node_names[(unsigned) SPUISD::SEXT32TO64] = "SPUISD::SEXT32TO64";
464 }
465
466 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
467
468 return ((i != node_names.end()) ? i->second : 0);
469}
470
Dan Gohman475871a2008-07-27 21:46:04 +0000471MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000472 MVT VT = Op.getValueType();
473 if (VT.isInteger())
Scott Michel405fba12008-03-10 23:49:09 +0000474 return VT;
475 else
476 return MVT::i32;
Scott Michel78c47fa2008-03-10 16:58:52 +0000477}
478
Scott Michel266bc8f2007-12-04 22:23:35 +0000479//===----------------------------------------------------------------------===//
480// Calling convention code:
481//===----------------------------------------------------------------------===//
482
483#include "SPUGenCallingConv.inc"
484
485//===----------------------------------------------------------------------===//
486// LowerOperation implementation
487//===----------------------------------------------------------------------===//
488
Scott Michel9de5d0d2008-01-11 02:53:15 +0000489/// Aligned load common code for CellSPU
490/*!
491 \param[in] Op The SelectionDAG load or store operand
492 \param[in] DAG The selection DAG
493 \param[in] ST CellSPU subtarget information structure
494 \param[in,out] alignment Caller initializes this to the load or store node's
495 value from getAlignment(), may be updated while generating the aligned load
496 \param[in,out] alignOffs Aligned offset; set by AlignedLoad to the aligned
497 offset (divisible by 16, modulo 16 == 0)
498 \param[in,out] prefSlotOffs Preferred slot offset; set by AlignedLoad to the
499 offset of the preferred slot (modulo 16 != 0)
500 \param[in,out] VT Caller initializes this value type to the the load or store
501 node's loaded or stored value type; may be updated if an i1-extended load or
502 store.
503 \param[out] was16aligned true if the base pointer had 16-byte alignment,
504 otherwise false. Can help to determine if the chunk needs to be rotated.
505
506 Both load and store lowering load a block of data aligned on a 16-byte
507 boundary. This is the common aligned load code shared between both.
508 */
Dan Gohman475871a2008-07-27 21:46:04 +0000509static SDValue
510AlignedLoad(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST,
Scott Michel9de5d0d2008-01-11 02:53:15 +0000511 LSBaseSDNode *LSN,
512 unsigned &alignment, int &alignOffs, int &prefSlotOffs,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000513 MVT &VT, bool &was16aligned)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000514{
Duncan Sands83ec4b62008-06-06 12:08:01 +0000515 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000516 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
Dan Gohman475871a2008-07-27 21:46:04 +0000517 SDValue basePtr = LSN->getBasePtr();
518 SDValue chain = LSN->getChain();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000519
520 if (basePtr.getOpcode() == ISD::ADD) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000521 SDValue Op1 = basePtr.getNode()->getOperand(1);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000522
Gabor Greif93c53e52008-08-31 15:37:04 +0000523 if (Op1.getOpcode() == ISD::Constant
524 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel58c58182008-01-17 20:38:41 +0000525 const ConstantSDNode *CN = cast<ConstantSDNode>(basePtr.getOperand(1));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000526
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000527 alignOffs = (int) CN->getZExtValue();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000528 prefSlotOffs = (int) (alignOffs & 0xf);
529
530 // Adjust the rotation amount to ensure that the final result ends up in
531 // the preferred slot:
532 prefSlotOffs -= vtm->prefslot_byte;
533 basePtr = basePtr.getOperand(0);
534
Scott Michel58c58182008-01-17 20:38:41 +0000535 // Loading from memory, can we adjust alignment?
536 if (basePtr.getOpcode() == SPUISD::AFormAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +0000537 SDValue APtr = basePtr.getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000538 if (APtr.getOpcode() == ISD::TargetGlobalAddress) {
539 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(APtr);
540 alignment = GSDN->getGlobal()->getAlignment();
541 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000542 }
543 } else {
544 alignOffs = 0;
545 prefSlotOffs = -vtm->prefslot_byte;
546 }
Scott Michel203b2d62008-04-30 00:30:08 +0000547 } else if (basePtr.getOpcode() == ISD::FrameIndex) {
548 FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(basePtr);
549 alignOffs = int(FIN->getIndex() * SPUFrameInfo::stackSlotSize());
550 prefSlotOffs = (int) (alignOffs & 0xf);
551 prefSlotOffs -= vtm->prefslot_byte;
552 basePtr = DAG.getRegister(SPU::R1, VT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000553 } else {
554 alignOffs = 0;
555 prefSlotOffs = -vtm->prefslot_byte;
556 }
557
558 if (alignment == 16) {
559 // Realign the base pointer as a D-Form address:
560 if (!isMemoryOperand(basePtr) || (alignOffs & ~0xf) != 0) {
Scott Michel58c58182008-01-17 20:38:41 +0000561 basePtr = DAG.getNode(ISD::ADD, PtrVT,
562 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000563 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000564 }
565
566 // Emit the vector load:
567 was16aligned = true;
568 return DAG.getLoad(MVT::v16i8, chain, basePtr,
569 LSN->getSrcValue(), LSN->getSrcValueOffset(),
570 LSN->isVolatile(), 16);
571 }
572
573 // Unaligned load or we're using the "large memory" model, which means that
574 // we have to be very pessimistic:
Scott Michel58c58182008-01-17 20:38:41 +0000575 if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
Gabor Greif93c53e52008-08-31 15:37:04 +0000576 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr,
577 DAG.getConstant(0, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000578 }
579
580 // Add the offset
Scott Michel053c1da2008-01-29 02:16:57 +0000581 basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000582 DAG.getConstant((alignOffs & ~0xf), PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000583 was16aligned = false;
584 return DAG.getLoad(MVT::v16i8, chain, basePtr,
585 LSN->getSrcValue(), LSN->getSrcValueOffset(),
586 LSN->isVolatile(), 16);
587}
588
Scott Michel266bc8f2007-12-04 22:23:35 +0000589/// Custom lower loads for CellSPU
590/*!
591 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
592 within a 16-byte block, we have to rotate to extract the requested element.
593 */
Dan Gohman475871a2008-07-27 21:46:04 +0000594static SDValue
595LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000596 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000597 SDValue the_chain = LN->getChain();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000598 MVT VT = LN->getMemoryVT();
Gabor Greifba36cb52008-08-28 21:40:38 +0000599 MVT OpVT = Op.getNode()->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000600 ISD::LoadExtType ExtType = LN->getExtensionType();
601 unsigned alignment = LN->getAlignment();
Dan Gohman475871a2008-07-27 21:46:04 +0000602 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000603
Scott Michel266bc8f2007-12-04 22:23:35 +0000604 switch (LN->getAddressingMode()) {
605 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000606 int offset, rotamt;
607 bool was16aligned;
Dan Gohman475871a2008-07-27 21:46:04 +0000608 SDValue result =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000609 AlignedLoad(Op, DAG, ST, LN,alignment, offset, rotamt, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000610
Gabor Greifba36cb52008-08-28 21:40:38 +0000611 if (result.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +0000612 return result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000613
614 the_chain = result.getValue(1);
615 // Rotate the chunk if necessary
616 if (rotamt < 0)
617 rotamt += 16;
Scott Michel497e8882008-01-11 21:01:19 +0000618 if (rotamt != 0 || !was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000619 SDVTList vecvts = DAG.getVTList(MVT::v16i8, MVT::Other);
620
Scott Michel58c58182008-01-17 20:38:41 +0000621 Ops[0] = the_chain;
622 Ops[1] = result;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000623 if (was16aligned) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000624 Ops[2] = DAG.getConstant(rotamt, MVT::i16);
625 } else {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000626 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000627 LoadSDNode *LN1 = cast<LoadSDNode>(result);
Scott Michel497e8882008-01-11 21:01:19 +0000628 Ops[2] = DAG.getNode(ISD::ADD, PtrVT, LN1->getBasePtr(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000629 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000630 }
631
632 result = DAG.getNode(SPUISD::ROTBYTES_LEFT_CHAINED, vecvts, Ops, 3);
633 the_chain = result.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000634 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000635
636 if (VT == OpVT || ExtType == ISD::EXTLOAD) {
637 SDVTList scalarvts;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000638 MVT vecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000639
Scott Michel9de5d0d2008-01-11 02:53:15 +0000640 // Convert the loaded v16i8 vector to the appropriate vector type
641 // specified by the operand:
642 if (OpVT == VT) {
643 if (VT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000644 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000645 } else
Duncan Sands83ec4b62008-06-06 12:08:01 +0000646 vecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000647
648 Ops[0] = the_chain;
649 Ops[1] = DAG.getNode(ISD::BIT_CONVERT, vecVT, result);
650 scalarvts = DAG.getVTList((OpVT == VT ? VT : OpVT), MVT::Other);
651 result = DAG.getNode(SPUISD::EXTRACT_ELT0_CHAINED, scalarvts, Ops, 2);
652 the_chain = result.getValue(1);
653 } else {
654 // Handle the sign and zero-extending loads for i1 and i8:
655 unsigned NewOpC;
656
657 if (ExtType == ISD::SEXTLOAD) {
658 NewOpC = (OpVT == MVT::i1
659 ? SPUISD::EXTRACT_I1_SEXT
660 : SPUISD::EXTRACT_I8_SEXT);
661 } else {
662 assert(ExtType == ISD::ZEXTLOAD);
663 NewOpC = (OpVT == MVT::i1
664 ? SPUISD::EXTRACT_I1_ZEXT
665 : SPUISD::EXTRACT_I8_ZEXT);
666 }
667
668 result = DAG.getNode(NewOpC, OpVT, result);
669 }
670
671 SDVTList retvts = DAG.getVTList(OpVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000672 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000673 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000674 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000675 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000676
Scott Michel58c58182008-01-17 20:38:41 +0000677 result = DAG.getNode(SPUISD::LDRESULT, retvts,
678 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000679 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000680 }
681 case ISD::PRE_INC:
682 case ISD::PRE_DEC:
683 case ISD::POST_INC:
684 case ISD::POST_DEC:
685 case ISD::LAST_INDEXED_MODE:
686 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
687 "UNINDEXED\n";
688 cerr << (unsigned) LN->getAddressingMode() << "\n";
689 abort();
690 /*NOTREACHED*/
691 }
692
Dan Gohman475871a2008-07-27 21:46:04 +0000693 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000694}
695
696/// Custom lower stores for CellSPU
697/*!
698 All CellSPU stores are aligned to 16-byte boundaries, so for elements
699 within a 16-byte block, we have to generate a shuffle to insert the
700 requested element into its place, then store the resulting block.
701 */
Dan Gohman475871a2008-07-27 21:46:04 +0000702static SDValue
703LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000704 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000705 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000706 MVT VT = Value.getValueType();
707 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
708 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000709 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000710
711 switch (SN->getAddressingMode()) {
712 case ISD::UNINDEXED: {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000713 int chunk_offset, slot_offset;
714 bool was16aligned;
Scott Michel266bc8f2007-12-04 22:23:35 +0000715
716 // The vector type we really want to load from the 16-byte chunk, except
717 // in the case of MVT::i1, which has to be v16i8.
Duncan Sands83ec4b62008-06-06 12:08:01 +0000718 MVT vecVT, stVecVT = MVT::v16i8;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000719
Scott Michel266bc8f2007-12-04 22:23:35 +0000720 if (StVT != MVT::i1)
Duncan Sands83ec4b62008-06-06 12:08:01 +0000721 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
722 vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000723
Dan Gohman475871a2008-07-27 21:46:04 +0000724 SDValue alignLoadVec =
Scott Michel9de5d0d2008-01-11 02:53:15 +0000725 AlignedLoad(Op, DAG, ST, SN, alignment,
726 chunk_offset, slot_offset, VT, was16aligned);
Scott Michel266bc8f2007-12-04 22:23:35 +0000727
Gabor Greifba36cb52008-08-28 21:40:38 +0000728 if (alignLoadVec.getNode() == 0)
Scott Michel9de5d0d2008-01-11 02:53:15 +0000729 return alignLoadVec;
Scott Michel266bc8f2007-12-04 22:23:35 +0000730
Scott Michel9de5d0d2008-01-11 02:53:15 +0000731 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000732 SDValue basePtr = LN->getBasePtr();
733 SDValue the_chain = alignLoadVec.getValue(1);
734 SDValue theValue = SN->getValue();
735 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000736
737 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000738 && (theValue.getOpcode() == ISD::AssertZext
739 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000740 // Drill down and get the value for zero- and sign-extended
741 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000742 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000743 }
744
Scott Michel9de5d0d2008-01-11 02:53:15 +0000745 chunk_offset &= 0xf;
Scott Michel266bc8f2007-12-04 22:23:35 +0000746
Dan Gohman475871a2008-07-27 21:46:04 +0000747 SDValue insertEltOffs = DAG.getConstant(chunk_offset, PtrVT);
748 SDValue insertEltPtr;
749 SDValue insertEltOp;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000750
751 // If the base pointer is already a D-form address, then just create
752 // a new D-form address with a slot offset and the orignal base pointer.
753 // Otherwise generate a D-form address with the slot offset relative
754 // to the stack pointer, which is always aligned.
Scott Michel497e8882008-01-11 21:01:19 +0000755 DEBUG(cerr << "CellSPU LowerSTORE: basePtr = ");
Gabor Greifba36cb52008-08-28 21:40:38 +0000756 DEBUG(basePtr.getNode()->dump(&DAG));
Scott Michel497e8882008-01-11 21:01:19 +0000757 DEBUG(cerr << "\n");
758
Scott Michel053c1da2008-01-29 02:16:57 +0000759 if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
760 (basePtr.getOpcode() == ISD::ADD
761 && basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
Scott Michel497e8882008-01-11 21:01:19 +0000762 insertEltPtr = basePtr;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000763 } else {
Scott Michel053c1da2008-01-29 02:16:57 +0000764 insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000765 }
766
767 insertEltOp = DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
Scott Michel266bc8f2007-12-04 22:23:35 +0000768 result = DAG.getNode(SPUISD::SHUFB, vecVT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000769 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue),
770 alignLoadVec,
771 DAG.getNode(ISD::BIT_CONVERT, vecVT, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000772
Scott Michel9de5d0d2008-01-11 02:53:15 +0000773 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000774 LN->getSrcValue(), LN->getSrcValueOffset(),
775 LN->isVolatile(), LN->getAlignment());
776
777 return result;
778 /*UNREACHED*/
779 }
780 case ISD::PRE_INC:
781 case ISD::PRE_DEC:
782 case ISD::POST_INC:
783 case ISD::POST_DEC:
784 case ISD::LAST_INDEXED_MODE:
785 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
786 "UNINDEXED\n";
787 cerr << (unsigned) SN->getAddressingMode() << "\n";
788 abort();
789 /*NOTREACHED*/
790 }
791
Dan Gohman475871a2008-07-27 21:46:04 +0000792 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000793}
794
795/// Generate the address of a constant pool entry.
Dan Gohman475871a2008-07-27 21:46:04 +0000796static SDValue
797LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000798 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000799 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
800 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000801 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
802 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000803 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000804
805 if (TM.getRelocationModel() == Reloc::Static) {
806 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000807 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000808 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000809 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000810 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
811 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000812 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000813 }
814 }
815
816 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000817 "LowerConstantPool: Relocation model other than static"
818 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000819 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000820}
821
Dan Gohman475871a2008-07-27 21:46:04 +0000822static SDValue
823LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000824 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000825 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000826 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
827 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000828 const TargetMachine &TM = DAG.getTarget();
829
830 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000831 if (!ST->usingLargeMem()) {
832 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
833 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000834 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
835 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000836 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
837 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000838 }
839
840 assert(0 &&
841 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000842 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000843}
844
Dan Gohman475871a2008-07-27 21:46:04 +0000845static SDValue
846LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000847 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000848 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
849 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000850 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000851 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000852 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000853
Scott Michel266bc8f2007-12-04 22:23:35 +0000854 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000855 if (!ST->usingLargeMem()) {
856 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
857 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000858 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
859 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000860 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
861 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000862 } else {
863 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000864 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000865 abort();
866 /*NOTREACHED*/
867 }
868
Dan Gohman475871a2008-07-27 21:46:04 +0000869 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000870}
871
872//! Custom lower i64 integer constants
873/*!
874 This code inserts all of the necessary juggling that needs to occur to load
875 a 64-bit constant into a register.
876 */
Dan Gohman475871a2008-07-27 21:46:04 +0000877static SDValue
878LowerConstant(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000879 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000880 ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000881
882 if (VT == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000883 SDValue T = DAG.getConstant(CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +0000884 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000885 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +0000886 } else {
887 cerr << "LowerConstant: unhandled constant type "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000888 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000889 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000890 abort();
891 /*NOTREACHED*/
892 }
893
Dan Gohman475871a2008-07-27 21:46:04 +0000894 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000895}
896
Nate Begemanccef5802008-02-14 18:43:04 +0000897//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000898static SDValue
899LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000900 MVT VT = Op.getValueType();
Gabor Greifba36cb52008-08-28 21:40:38 +0000901 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
Scott Michel266bc8f2007-12-04 22:23:35 +0000902
903 assert((FP != 0) &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000904 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel266bc8f2007-12-04 22:23:35 +0000905
Nate Begemanccef5802008-02-14 18:43:04 +0000906 if (VT == MVT::f64) {
Scott Michel170783a2007-12-19 20:15:47 +0000907 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel266bc8f2007-12-04 22:23:35 +0000908 return DAG.getNode(ISD::BIT_CONVERT, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000909 LowerConstant(DAG.getConstant(dbits, MVT::i64), DAG));
Scott Michel266bc8f2007-12-04 22:23:35 +0000910 }
911
Dan Gohman475871a2008-07-27 21:46:04 +0000912 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000913}
914
Scott Michel58c58182008-01-17 20:38:41 +0000915//! Lower MVT::i1, MVT::i8 brcond to a promoted type (MVT::i32, MVT::i16)
Dan Gohman475871a2008-07-27 21:46:04 +0000916static SDValue
917LowerBRCOND(SDValue Op, SelectionDAG &DAG)
Scott Michel58c58182008-01-17 20:38:41 +0000918{
Dan Gohman475871a2008-07-27 21:46:04 +0000919 SDValue Cond = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000920 MVT CondVT = Cond.getValueType();
921 MVT CondNVT;
Scott Michel58c58182008-01-17 20:38:41 +0000922
923 if (CondVT == MVT::i1 || CondVT == MVT::i8) {
924 CondNVT = (CondVT == MVT::i1 ? MVT::i32 : MVT::i16);
925 return DAG.getNode(ISD::BRCOND, Op.getValueType(),
926 Op.getOperand(0),
927 DAG.getNode(ISD::ZERO_EXTEND, CondNVT, Op.getOperand(1)),
928 Op.getOperand(2));
929 } else
Dan Gohman475871a2008-07-27 21:46:04 +0000930 return SDValue(); // Unchanged
Scott Michel58c58182008-01-17 20:38:41 +0000931}
932
Dan Gohman475871a2008-07-27 21:46:04 +0000933static SDValue
934LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000935{
936 MachineFunction &MF = DAG.getMachineFunction();
937 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000938 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +0000939 SmallVector<SDValue, 8> ArgValues;
940 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000941 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000942
943 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
944 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000945
Scott Michel266bc8f2007-12-04 22:23:35 +0000946 unsigned ArgOffset = SPUFrameInfo::minStackSize();
947 unsigned ArgRegIdx = 0;
948 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000949
Duncan Sands83ec4b62008-06-06 12:08:01 +0000950 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000951
Scott Michel266bc8f2007-12-04 22:23:35 +0000952 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000953 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
954 ArgNo != e; ++ArgNo) {
Dan Gohman475871a2008-07-27 21:46:04 +0000955 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000956 bool needsLoad = false;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000957 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
958 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Michel266bc8f2007-12-04 22:23:35 +0000959
Duncan Sands83ec4b62008-06-06 12:08:01 +0000960 switch (ObjectVT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000961 default: {
962 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000963 << ObjectVT.getMVTString()
Scott Michel266bc8f2007-12-04 22:23:35 +0000964 << "\n";
965 abort();
966 }
967 case MVT::i8:
968 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000969 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R8CRegClass);
970 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000971 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i8);
972 ++ArgRegIdx;
973 } else {
974 needsLoad = true;
975 }
976 break;
977 case MVT::i16:
978 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000979 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
980 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000981 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i16);
982 ++ArgRegIdx;
983 } else {
984 needsLoad = true;
985 }
986 break;
987 case MVT::i32:
988 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000989 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
990 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +0000991 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
992 ++ArgRegIdx;
993 } else {
994 needsLoad = true;
995 }
996 break;
997 case MVT::i64:
998 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +0000999 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64CRegClass);
1000 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001001 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64);
1002 ++ArgRegIdx;
1003 } else {
1004 needsLoad = true;
1005 }
1006 break;
1007 case MVT::f32:
1008 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001009 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
1010 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001011 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f32);
1012 ++ArgRegIdx;
1013 } else {
1014 needsLoad = true;
1015 }
1016 break;
1017 case MVT::f64:
1018 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001019 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64FPRegClass);
1020 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001021 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f64);
1022 ++ArgRegIdx;
1023 } else {
1024 needsLoad = true;
1025 }
1026 break;
1027 case MVT::v2f64:
1028 case MVT::v4f32:
Scott Michelad2715e2008-03-05 23:02:02 +00001029 case MVT::v2i64:
Scott Michel266bc8f2007-12-04 22:23:35 +00001030 case MVT::v4i32:
1031 case MVT::v8i16:
1032 case MVT::v16i8:
1033 if (!isVarArg && ArgRegIdx < NumArgRegs) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001034 unsigned VReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1035 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Scott Michel266bc8f2007-12-04 22:23:35 +00001036 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
1037 ++ArgRegIdx;
1038 } else {
1039 needsLoad = true;
1040 }
1041 break;
1042 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001043
Scott Michel266bc8f2007-12-04 22:23:35 +00001044 // We need to load the argument to a virtual register if we determined above
1045 // that we ran out of physical registers of the appropriate type
1046 if (needsLoad) {
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001047 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001048 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +00001049 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001050 ArgOffset += StackSlotSize;
1051 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001052
Scott Michel266bc8f2007-12-04 22:23:35 +00001053 ArgValues.push_back(ArgVal);
1054 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001055
Scott Michel266bc8f2007-12-04 22:23:35 +00001056 // If the function takes variable number of arguments, make a frame index for
1057 // the start of the first vararg value... for expansion of llvm.va_start.
1058 if (isVarArg) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001059 VarArgsFrameIndex = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8,
Scott Michel266bc8f2007-12-04 22:23:35 +00001060 ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +00001061 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001062 // If this function is vararg, store any remaining integer argument regs to
1063 // their spots on the stack so that they may be loaded by deferencing the
1064 // result of va_next.
Dan Gohman475871a2008-07-27 21:46:04 +00001065 SmallVector<SDValue, 8> MemOps;
Scott Michel266bc8f2007-12-04 22:23:35 +00001066 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Chris Lattner84bc5422007-12-31 04:13:23 +00001067 unsigned VReg = RegInfo.createVirtualRegister(&SPU::GPRCRegClass);
1068 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
Dan Gohman475871a2008-07-27 21:46:04 +00001069 SDValue Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
1070 SDValue Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001071 MemOps.push_back(Store);
1072 // Increment the address by four for the next argument to store
Dan Gohman475871a2008-07-27 21:46:04 +00001073 SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001074 FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
1075 }
1076 if (!MemOps.empty())
1077 Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
1078 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001079
Scott Michel266bc8f2007-12-04 22:23:35 +00001080 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001081
Scott Michel266bc8f2007-12-04 22:23:35 +00001082 // Return the new list of results.
Gabor Greifba36cb52008-08-28 21:40:38 +00001083 return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
Duncan Sandsf9516202008-06-30 10:19:09 +00001084 ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001085}
1086
1087/// isLSAAddress - Return the immediate to use if the specified
1088/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001089static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001090 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
1091 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001092
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001093 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001094 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1095 (Addr << 14 >> 14) != Addr)
1096 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001097
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001098 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001099}
1100
1101static
Dan Gohman475871a2008-07-27 21:46:04 +00001102SDValue
1103LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
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
Scott Michel266bc8f2007-12-04 22:23:35 +00001204 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1205 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1206 // node so that legalize doesn't hack it.
1207 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 }
1232 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
1233 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001234 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001235 // If this is an absolute destination address that appears to be a legal
1236 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001237 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001238 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001239
1240 Ops.push_back(Chain);
1241 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001242
Scott Michel266bc8f2007-12-04 22:23:35 +00001243 // Add argument registers to the end of the list so that they are known live
1244 // into the call.
1245 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001246 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001247 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001248
Gabor Greifba36cb52008-08-28 21:40:38 +00001249 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001250 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001251 // Returns a chain and a flag for retval copy to use.
1252 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1253 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001254 InFlag = Chain.getValue(1);
1255
Evan Chengebaaa912008-02-05 22:44:06 +00001256 Chain = DAG.getCALLSEQ_END(Chain,
1257 DAG.getConstant(NumStackBytes, PtrVT),
1258 DAG.getConstant(0, PtrVT),
1259 InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001260 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001261 InFlag = Chain.getValue(1);
1262
Dan Gohman475871a2008-07-27 21:46:04 +00001263 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001264 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001265
Scott Michel266bc8f2007-12-04 22:23:35 +00001266 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001267 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001268 default: assert(0 && "Unexpected ret value!");
1269 case MVT::Other: break;
1270 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001271 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001272 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1273 ResultVals[0] = Chain.getValue(0);
1274 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1275 Chain.getValue(2)).getValue(1);
1276 ResultVals[1] = Chain.getValue(0);
1277 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001278 } else {
1279 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1280 ResultVals[0] = Chain.getValue(0);
1281 NumResults = 1;
1282 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001283 break;
1284 case MVT::i64:
1285 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1286 ResultVals[0] = Chain.getValue(0);
1287 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001288 break;
1289 case MVT::f32:
1290 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001291 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001292 InFlag).getValue(1);
1293 ResultVals[0] = Chain.getValue(0);
1294 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001295 break;
1296 case MVT::v2f64:
1297 case MVT::v4f32:
1298 case MVT::v4i32:
1299 case MVT::v8i16:
1300 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001301 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001302 InFlag).getValue(1);
1303 ResultVals[0] = Chain.getValue(0);
1304 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001305 break;
1306 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001307
Scott Michel266bc8f2007-12-04 22:23:35 +00001308 // If the function returns void, just return the chain.
1309 if (NumResults == 0)
1310 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001311
Scott Michel266bc8f2007-12-04 22:23:35 +00001312 // Otherwise, merge everything together with a MERGE_VALUES node.
1313 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001314 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001315 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001316}
1317
Dan Gohman475871a2008-07-27 21:46:04 +00001318static SDValue
1319LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001320 SmallVector<CCValAssign, 16> RVLocs;
1321 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1322 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1323 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001324 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001325
Scott Michel266bc8f2007-12-04 22:23:35 +00001326 // If this is the first return lowered for this function, add the regs to the
1327 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001328 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001329 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001330 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001331 }
1332
Dan Gohman475871a2008-07-27 21:46:04 +00001333 SDValue Chain = Op.getOperand(0);
1334 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001335
Scott Michel266bc8f2007-12-04 22:23:35 +00001336 // Copy the result values into the output registers.
1337 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1338 CCValAssign &VA = RVLocs[i];
1339 assert(VA.isRegLoc() && "Can only return in registers!");
1340 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1341 Flag = Chain.getValue(1);
1342 }
1343
Gabor Greifba36cb52008-08-28 21:40:38 +00001344 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001345 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1346 else
1347 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1348}
1349
1350
1351//===----------------------------------------------------------------------===//
1352// Vector related lowering:
1353//===----------------------------------------------------------------------===//
1354
1355static ConstantSDNode *
1356getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001357 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001358
Scott Michel266bc8f2007-12-04 22:23:35 +00001359 // Check to see if this buildvec has a single non-undef value in its elements.
1360 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1361 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001362 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001363 OpVal = N->getOperand(i);
1364 else if (OpVal != N->getOperand(i))
1365 return 0;
1366 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001367
Gabor Greifba36cb52008-08-28 21:40:38 +00001368 if (OpVal.getNode() != 0) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001369 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1370 return CN;
1371 }
1372 }
1373
1374 return 0; // All UNDEF: use implicit def.; not Constant node
1375}
1376
1377/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1378/// and the value fits into an unsigned 18-bit constant, and if so, return the
1379/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001380SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001381 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001382 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001383 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001384 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001385 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001386 uint32_t upper = uint32_t(UValue >> 32);
1387 uint32_t lower = uint32_t(UValue);
1388 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001389 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001390 Value = Value >> 32;
1391 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001392 if (Value <= 0x3ffff)
1393 return DAG.getConstant(Value, ValueType);
1394 }
1395
Dan Gohman475871a2008-07-27 21:46:04 +00001396 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001397}
1398
1399/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1400/// and the value fits into a signed 16-bit constant, and if so, return the
1401/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001402SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001403 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001404 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001405 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001406 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001407 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001408 uint32_t upper = uint32_t(UValue >> 32);
1409 uint32_t lower = uint32_t(UValue);
1410 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001411 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001412 Value = Value >> 32;
1413 }
Scott Michelad2715e2008-03-05 23:02:02 +00001414 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
1415 return DAG.getConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001416 }
1417 }
1418
Dan Gohman475871a2008-07-27 21:46:04 +00001419 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001420}
1421
1422/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1423/// and the value fits into a signed 10-bit constant, and if so, return the
1424/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001425SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001426 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001427 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001428 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001429 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001430 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001431 uint32_t upper = uint32_t(UValue >> 32);
1432 uint32_t lower = uint32_t(UValue);
1433 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001434 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001435 Value = Value >> 32;
1436 }
Scott Michelad2715e2008-03-05 23:02:02 +00001437 if (isS10Constant(Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001438 return DAG.getConstant(Value, ValueType);
1439 }
1440
Dan Gohman475871a2008-07-27 21:46:04 +00001441 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001442}
1443
1444/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1445/// and the value fits into a signed 8-bit constant, and if so, return the
1446/// constant.
1447///
1448/// @note: The incoming vector is v16i8 because that's the only way we can load
1449/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1450/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001451SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001452 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001453 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001454 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001455 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001456 && Value <= 0xffff /* truncated from uint64_t */
1457 && ((short) Value >> 8) == ((short) Value & 0xff))
Scott Michel266bc8f2007-12-04 22:23:35 +00001458 return DAG.getConstant(Value & 0xff, ValueType);
1459 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001460 && (Value & 0xff) == Value)
Scott Michel266bc8f2007-12-04 22:23:35 +00001461 return DAG.getConstant(Value, ValueType);
1462 }
1463
Dan Gohman475871a2008-07-27 21:46:04 +00001464 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001465}
1466
1467/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1468/// and the value fits into a signed 16-bit constant, and if so, return the
1469/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001470SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001471 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001472 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001473 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001474 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001475 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1476 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001477 return DAG.getConstant(Value >> 16, ValueType);
1478 }
1479
Dan Gohman475871a2008-07-27 21:46:04 +00001480 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001481}
1482
1483/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001484SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001485 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001486 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001487 }
1488
Dan Gohman475871a2008-07-27 21:46:04 +00001489 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001490}
1491
1492/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001493SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001494 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001495 return DAG.getConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001496 }
1497
Dan Gohman475871a2008-07-27 21:46:04 +00001498 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001499}
1500
1501// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001502// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001503// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1504// zero. Return true if this is not an array of constants, false if it is.
1505//
1506static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1507 uint64_t UndefBits[2]) {
1508 // Start with zero'd results.
1509 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001510
Duncan Sands83ec4b62008-06-06 12:08:01 +00001511 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001512 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001513 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001514
Scott Michel266bc8f2007-12-04 22:23:35 +00001515 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1516 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1517
1518 uint64_t EltBits = 0;
1519 if (OpVal.getOpcode() == ISD::UNDEF) {
1520 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1521 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1522 continue;
1523 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001524 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00001525 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
1526 const APFloat &apf = CN->getValueAPF();
1527 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001528 ? FloatToBits(apf.convertToFloat())
1529 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001530 } else {
1531 // Nonconstant element.
1532 return true;
1533 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001534
Scott Michel266bc8f2007-12-04 22:23:35 +00001535 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1536 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001537
1538 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001539 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1540 return false;
1541}
1542
1543/// If this is a splat (repetition) of a value across the whole vector, return
1544/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001545/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001546/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001547static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001548 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001549 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001550 uint64_t &SplatBits, uint64_t &SplatUndef,
1551 int &SplatSize) {
1552 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1553 // the same as the lower 64-bits, ignoring undefs.
1554 uint64_t Bits64 = Bits128[0] | Bits128[1];
1555 uint64_t Undef64 = Undef128[0] & Undef128[1];
1556 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1557 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1558 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1559 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1560
1561 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1562 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001563
Scott Michel266bc8f2007-12-04 22:23:35 +00001564 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1565 // undefs.
1566 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001567 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001568
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001569 // If the top 16-bits are different than the lower 16-bits, ignoring
1570 // undefs, we have an i32 splat.
1571 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1572 if (MinSplatBits < 16) {
1573 // If the top 8-bits are different than the lower 8-bits, ignoring
1574 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001575 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1576 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001577 // Otherwise, we have an 8-bit splat.
1578 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1579 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1580 SplatSize = 1;
1581 return true;
1582 }
1583 } else {
1584 SplatBits = Bits16;
1585 SplatUndef = Undef16;
1586 SplatSize = 2;
1587 return true;
1588 }
1589 }
1590 } else {
1591 SplatBits = Bits32;
1592 SplatUndef = Undef32;
1593 SplatSize = 4;
1594 return true;
1595 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001596 }
1597 } else {
1598 SplatBits = Bits128[0];
1599 SplatUndef = Undef128[0];
1600 SplatSize = 8;
1601 return true;
1602 }
1603 }
1604
1605 return false; // Can't be a splat if two pieces don't match.
1606}
1607
1608// If this is a case we can't handle, return null and let the default
1609// expansion code take care of it. If we CAN select this case, and if it
1610// selects to a single instruction, return Op. Otherwise, if we can codegen
1611// this case more efficiently than a constant pool load, lower it to the
1612// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001613static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001614 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001615 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001616 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001617 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001618 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001619 uint64_t VectorBits[2];
1620 uint64_t UndefBits[2];
1621 uint64_t SplatBits, SplatUndef;
1622 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001623 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001624 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001625 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001626 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001627 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001628
Duncan Sands83ec4b62008-06-06 12:08:01 +00001629 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001630 default:
1631 case MVT::v4f32: {
1632 uint32_t Value32 = SplatBits;
1633 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001634 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001635 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001636 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001637 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001638 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001639 break;
1640 }
1641 case MVT::v2f64: {
1642 uint64_t f64val = SplatBits;
1643 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001644 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001645 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001646 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001647 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001648 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001649 break;
1650 }
1651 case MVT::v16i8: {
1652 // 8-bit constants have to be expanded to 16-bits
1653 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001654 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001655 for (int i = 0; i < 8; ++i)
1656 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1657 return DAG.getNode(ISD::BIT_CONVERT, VT,
1658 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1659 }
1660 case MVT::v8i16: {
1661 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001662 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001663 Value16 = (unsigned short) (SplatBits & 0xffff);
1664 else
1665 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001666 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1667 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001668 for (int i = 0; i < 8; ++i) Ops[i] = T;
1669 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1670 }
1671 case MVT::v4i32: {
1672 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001673 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001674 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1675 }
1676 case MVT::v2i64: {
1677 uint64_t val = SplatBits;
1678 uint32_t upper = uint32_t(val >> 32);
1679 uint32_t lower = uint32_t(val);
1680
Scott Michel4cb8bd82008-03-06 04:02:54 +00001681 if (upper == lower) {
1682 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001683 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001684 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001685 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001686 SDValue LO32;
1687 SDValue HI32;
1688 SmallVector<SDValue, 16> ShufBytes;
1689 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001690 bool upper_special, lower_special;
1691
1692 // NOTE: This code creates common-case shuffle masks that can be easily
1693 // detected as common expressions. It is not attempting to create highly
1694 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1695
1696 // Detect if the upper or lower half is a special shuffle mask pattern:
1697 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1698 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1699
1700 // Create lower vector if not a special pattern
1701 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001702 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001703 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1704 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1705 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001706 }
1707
1708 // Create upper vector if not a special pattern
1709 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001710 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001711 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1712 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1713 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001714 }
1715
1716 // If either upper or lower are special, then the two input operands are
1717 // the same (basically, one of them is a "don't care")
1718 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001719 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001720 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001721 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001722 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001723 // Unhappy situation... both upper and lower are special, so punt with
1724 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001725 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001726 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001727 Zero, Zero);
1728 }
1729
1730 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001731 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001732 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001733 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001734 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001735 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001736 process_upper = (upper_special && (i & 1) == 0);
1737 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001738
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001739 if (process_upper || process_lower) {
1740 if ((process_upper && upper == 0)
1741 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001742 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001743 else if ((process_upper && upper == 0xffffffff)
1744 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001745 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001746 else if ((process_upper && upper == 0x80000000)
1747 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001748 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001749 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001750 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001751 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001752
1753 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001754 }
1755
1756 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001757 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001758 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001759 }
1760 }
1761 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001762
Dan Gohman475871a2008-07-27 21:46:04 +00001763 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001764}
1765
1766/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1767/// which the Cell can operate. The code inspects V3 to ascertain whether the
1768/// permutation vector, V3, is monotonically increasing with one "exception"
1769/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1770/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1771/// In either case, the net result is going to eventually invoke SHUFB to
1772/// permute/shuffle the bytes from V1 and V2.
1773/// \note
1774/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1775/// control word for byte/halfword/word insertion. This takes care of a single
1776/// element move from V2 into V1.
1777/// \note
1778/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001779static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1780 SDValue V1 = Op.getOperand(0);
1781 SDValue V2 = Op.getOperand(1);
1782 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001783
Scott Michel266bc8f2007-12-04 22:23:35 +00001784 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001785
Scott Michel266bc8f2007-12-04 22:23:35 +00001786 // If we have a single element being moved from V1 to V2, this can be handled
1787 // using the C*[DX] compute mask instructions, but the vector elements have
1788 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001789 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001790 unsigned EltsFromV2 = 0;
1791 unsigned V2Elt = 0;
1792 unsigned V2EltIdx0 = 0;
1793 unsigned CurrElt = 0;
1794 bool monotonic = true;
1795 if (EltVT == MVT::i8)
1796 V2EltIdx0 = 16;
1797 else if (EltVT == MVT::i16)
1798 V2EltIdx0 = 8;
1799 else if (EltVT == MVT::i32)
1800 V2EltIdx0 = 4;
1801 else
1802 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1803
1804 for (unsigned i = 0, e = PermMask.getNumOperands();
1805 EltsFromV2 <= 1 && monotonic && i != e;
1806 ++i) {
1807 unsigned SrcElt;
1808 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1809 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001810 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001811 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001812
1813 if (SrcElt >= V2EltIdx0) {
1814 ++EltsFromV2;
1815 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1816 } else if (CurrElt != SrcElt) {
1817 monotonic = false;
1818 }
1819
1820 ++CurrElt;
1821 }
1822
1823 if (EltsFromV2 == 1 && monotonic) {
1824 // Compute mask and shuffle
1825 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001826 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1827 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001828 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001829 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001830 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001831 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1832 // Copy register's contents as index in INSERT_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001833 SDValue ShufMaskOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001834 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001835 DAG.getTargetConstant(V2Elt, MVT::i32),
1836 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001837 // Use shuffle mask in SHUFB synthetic instruction:
1838 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1839 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001840 // Convert the SHUFFLE_VECTOR mask's input element units to the
1841 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001842 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001843
Dan Gohman475871a2008-07-27 21:46:04 +00001844 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001845 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1846 unsigned SrcElt;
1847 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001848 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001849 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001850 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001851
Scott Michela59d4692008-02-23 18:41:37 +00001852 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001853 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1854 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001855 }
1856 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001857
Dan Gohman475871a2008-07-27 21:46:04 +00001858 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001859 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001860 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1861 }
1862}
1863
Dan Gohman475871a2008-07-27 21:46:04 +00001864static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1865 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001866
Gabor Greifba36cb52008-08-28 21:40:38 +00001867 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001868 // For a constant, build the appropriate constant vector, which will
1869 // eventually simplify to a vector register load.
1870
Gabor Greifba36cb52008-08-28 21:40:38 +00001871 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001872 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001873 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001874 size_t n_copies;
1875
1876 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001877 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001878 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001879 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001880 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1881 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1882 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1883 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1884 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1885 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1886 }
1887
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001888 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001889 for (size_t j = 0; j < n_copies; ++j)
1890 ConstVecValues.push_back(CValue);
1891
1892 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001893 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001894 } else {
1895 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001896 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001897 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1898 case MVT::i8:
1899 case MVT::i16:
1900 case MVT::i32:
1901 case MVT::i64:
1902 case MVT::f32:
1903 case MVT::f64:
1904 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1905 }
1906 }
1907
Dan Gohman475871a2008-07-27 21:46:04 +00001908 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001909}
1910
Dan Gohman475871a2008-07-27 21:46:04 +00001911static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001912 switch (Op.getValueType().getSimpleVT()) {
1913 default:
1914 cerr << "CellSPU: Unknown vector multiplication, got "
1915 << Op.getValueType().getMVTString()
1916 << "\n";
1917 abort();
1918 /*NOTREACHED*/
1919
Scott Michel266bc8f2007-12-04 22:23:35 +00001920 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001921 SDValue rA = Op.getOperand(0);
1922 SDValue rB = Op.getOperand(1);
1923 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1924 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1925 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1926 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001927
1928 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1929 break;
1930 }
1931
1932 // Multiply two v8i16 vectors (pipeline friendly version):
1933 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1934 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1935 // c) Use SELB to select upper and lower halves from the intermediate results
1936 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001937 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001938 // dual-issue. This code does manage to do this, even if it's a little on
1939 // the wacky side
1940 case MVT::v8i16: {
1941 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001942 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001943 SDValue Chain = Op.getOperand(0);
1944 SDValue rA = Op.getOperand(0);
1945 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001946 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1947 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001948
Dan Gohman475871a2008-07-27 21:46:04 +00001949 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001950 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001951 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001952 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001953
Dan Gohman475871a2008-07-27 21:46:04 +00001954 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001955 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001956 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001957
Dan Gohman475871a2008-07-27 21:46:04 +00001958 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001959 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001960 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001961
1962 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001963 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1964 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1965 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1966 HHProd_v4i32,
1967 DAG.getConstant(16, MVT::i16))),
1968 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001969 }
1970
1971 // This M00sE is N@stI! (apologies to Monty Python)
1972 //
1973 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1974 // is to break it all apart, sign extend, and reassemble the various
1975 // intermediate products.
1976 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001977 SDValue rA = Op.getOperand(0);
1978 SDValue rB = Op.getOperand(1);
1979 SDValue c8 = DAG.getConstant(8, MVT::i32);
1980 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001981
Dan Gohman475871a2008-07-27 21:46:04 +00001982 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001983 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001984 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1985 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001986
Dan Gohman475871a2008-07-27 21:46:04 +00001987 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001988
Dan Gohman475871a2008-07-27 21:46:04 +00001989 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001990
Dan Gohman475871a2008-07-27 21:46:04 +00001991 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001992 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001993 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001994
Dan Gohman475871a2008-07-27 21:46:04 +00001995 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001996 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001997
Dan Gohman475871a2008-07-27 21:46:04 +00001998 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001999 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2000 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2001 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002002
Dan Gohman475871a2008-07-27 21:46:04 +00002003 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002004
Dan Gohman475871a2008-07-27 21:46:04 +00002005 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002006 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00002007 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002008 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2009 LoProdMask, LoProdMask,
2010 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002011
Dan Gohman475871a2008-07-27 21:46:04 +00002012 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002013 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002014 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002015
Dan Gohman475871a2008-07-27 21:46:04 +00002016 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002017 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002018 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002019
Dan Gohman475871a2008-07-27 21:46:04 +00002020 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002021 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002022 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2023 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00002024
Dan Gohman475871a2008-07-27 21:46:04 +00002025 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002026 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002027 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002028 DAG.getNode(SPUISD::VEC_SRA,
2029 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002030 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002031 DAG.getNode(SPUISD::VEC_SRA,
2032 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002033
Dan Gohman475871a2008-07-27 21:46:04 +00002034 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00002035 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2036 HLProd,
2037 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2038 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002039
Dan Gohman475871a2008-07-27 21:46:04 +00002040 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002041 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002042
2043 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002044 DAG.getNode(ISD::OR, MVT::v4i32,
2045 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002046 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002047 }
2048
Dan Gohman475871a2008-07-27 21:46:04 +00002049 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002050}
2051
Dan Gohman475871a2008-07-27 21:46:04 +00002052static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002053 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002054 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002055
Dan Gohman475871a2008-07-27 21:46:04 +00002056 SDValue A = Op.getOperand(0);
2057 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002058 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002059
2060 unsigned VRegBR, VRegC;
2061
2062 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002063 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2064 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002065 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002066 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2067 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002068 }
2069 // TODO: make sure we're feeding FPInterp the right arguments
2070 // Right now: fi B, frest(B)
2071
2072 // Computes BRcpl =
2073 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002074 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002075 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2076 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002077 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002078
Scott Michel266bc8f2007-12-04 22:23:35 +00002079 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002080 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002081 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002082 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002083 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002084 // What's the Chain variable do? It's magic!
2085 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002086
2087 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002088 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002089 DAG.getNode(ISD::FMUL, VT,
2090 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002091 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002092 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002093 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002094}
2095
Dan Gohman475871a2008-07-27 21:46:04 +00002096static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002097 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002098 SDValue N = Op.getOperand(0);
2099 SDValue Elt = Op.getOperand(1);
2100 SDValue ShufMask[16];
Scott Michel266bc8f2007-12-04 22:23:35 +00002101 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
2102
2103 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2104
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002105 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002106
2107 // sanity checks:
2108 if (VT == MVT::i8 && EltNo >= 16)
2109 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2110 else if (VT == MVT::i16 && EltNo >= 8)
2111 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2112 else if (VT == MVT::i32 && EltNo >= 4)
2113 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2114 else if (VT == MVT::i64 && EltNo >= 2)
2115 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2116
2117 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2118 // i32 and i64: Element 0 is the preferred slot
2119 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2120 }
2121
2122 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002123 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002124 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002125
Duncan Sands83ec4b62008-06-06 12:08:01 +00002126 switch (VT.getSimpleVT()) {
2127 default:
2128 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002129 case MVT::i8: {
2130 prefslot_begin = prefslot_end = 3;
2131 break;
2132 }
2133 case MVT::i16: {
2134 prefslot_begin = 2; prefslot_end = 3;
2135 break;
2136 }
2137 case MVT::i32: {
2138 prefslot_begin = 0; prefslot_end = 3;
2139 break;
2140 }
2141 case MVT::i64: {
2142 prefslot_begin = 0; prefslot_end = 7;
2143 break;
2144 }
2145 }
2146
Scott Michel0e5665b2007-12-19 21:17:42 +00002147 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002148 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002149
Scott Michel266bc8f2007-12-04 22:23:35 +00002150 for (int i = 0; i < 16; ++i) {
2151 // zero fill uppper part of preferred slot, don't care about the
2152 // other slots:
2153 unsigned int mask_val;
2154
2155 if (i <= prefslot_end) {
2156 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002157 ((i < prefslot_begin)
2158 ? 0x80
2159 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002160
Scott Michel0e5665b2007-12-19 21:17:42 +00002161 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002162 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002163 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2164 }
2165
Dan Gohman475871a2008-07-27 21:46:04 +00002166 SDValue ShufMaskVec =
Scott Michel266bc8f2007-12-04 22:23:35 +00002167 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002168 &ShufMask[0],
2169 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002170
2171 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002172 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2173 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002174
Scott Michel266bc8f2007-12-04 22:23:35 +00002175}
2176
Dan Gohman475871a2008-07-27 21:46:04 +00002177static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2178 SDValue VecOp = Op.getOperand(0);
2179 SDValue ValOp = Op.getOperand(1);
2180 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002181 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002182
2183 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2184 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2185
Duncan Sands83ec4b62008-06-06 12:08:01 +00002186 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002187 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002188 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002189
Dan Gohman475871a2008-07-27 21:46:04 +00002190 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002191 DAG.getNode(SPUISD::SHUFB, VT,
2192 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2193 VecOp,
2194 DAG.getNode(SPUISD::INSERT_MASK, VT,
2195 DAG.getNode(ISD::ADD, PtrVT,
2196 PtrBase,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002197 DAG.getConstant(CN->getZExtValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002198 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002199
2200 return result;
2201}
2202
Dan Gohman475871a2008-07-27 21:46:04 +00002203static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002204{
Dan Gohman475871a2008-07-27 21:46:04 +00002205 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002206
2207 assert(Op.getValueType() == MVT::i8);
2208 switch (Opc) {
2209 default:
2210 assert(0 && "Unhandled i8 math operator");
2211 /*NOTREACHED*/
2212 break;
2213 case ISD::SUB: {
2214 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2215 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002216 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002217 N0 = (N0.getOpcode() != ISD::Constant
2218 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002219 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2220 MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00002221 N1 = (N1.getOpcode() != ISD::Constant
2222 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002223 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2224 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002225 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002226 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002227 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002228 case ISD::ROTR:
2229 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002230 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002231 unsigned N1Opc;
2232 N0 = (N0.getOpcode() != ISD::Constant
2233 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002234 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2235 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002236 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2237 ? ISD::ZERO_EXTEND
2238 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002239 N1 = (N1.getOpcode() != ISD::Constant
2240 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002241 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2242 MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002243 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002244 DAG.getNode(ISD::OR, MVT::i16, N0,
2245 DAG.getNode(ISD::SHL, MVT::i16,
2246 N0, DAG.getConstant(8, MVT::i16)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002247 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002248 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2249 }
2250 case ISD::SRL:
2251 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002252 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002253 unsigned N1Opc;
2254 N0 = (N0.getOpcode() != ISD::Constant
2255 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002256 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2257 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002258 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2259 ? ISD::ZERO_EXTEND
2260 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002261 N1 = (N1.getOpcode() != ISD::Constant
2262 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002263 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2264 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002265 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002266 DAG.getNode(Opc, MVT::i16, N0, N1));
2267 }
2268 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002269 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002270 unsigned N1Opc;
2271 N0 = (N0.getOpcode() != ISD::Constant
2272 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002273 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2274 MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002275 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2276 ? ISD::SIGN_EXTEND
2277 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002278 N1 = (N1.getOpcode() != ISD::Constant
2279 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002280 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2281 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002282 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002283 DAG.getNode(Opc, MVT::i16, N0, N1));
2284 }
2285 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002286 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002287 unsigned N1Opc;
2288 N0 = (N0.getOpcode() != ISD::Constant
2289 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002290 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2291 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002292 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002293 N1 = (N1.getOpcode() != ISD::Constant
2294 ? DAG.getNode(N1Opc, MVT::i16, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002295 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
2296 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002297 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002298 DAG.getNode(Opc, MVT::i16, N0, N1));
2299 break;
2300 }
2301 }
2302
Dan Gohman475871a2008-07-27 21:46:04 +00002303 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002304}
2305
Dan Gohman475871a2008-07-27 21:46:04 +00002306static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002307{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002308 MVT VT = Op.getValueType();
2309 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002310
Dan Gohman475871a2008-07-27 21:46:04 +00002311 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002312
2313 switch (Opc) {
2314 case ISD::ZERO_EXTEND:
2315 case ISD::SIGN_EXTEND:
2316 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002317 MVT Op0VT = Op0.getValueType();
2318 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002319
2320 assert(Op0VT == MVT::i32
2321 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002322 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002323
2324 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2325 ? SPUISD::ROTBYTES_RIGHT_S
2326 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002327 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002328 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2329
2330 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2331 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2332 DAG.getNode(NewOpc, Op0VecVT,
2333 PromoteScalar,
2334 DAG.getConstant(4, MVT::i32))));
2335 }
2336
Scott Michel8bf61e82008-06-02 22:18:03 +00002337 case ISD::ADD: {
2338 // Turn operands into vectors to satisfy type checking (shufb works on
2339 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002340 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002341 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002342 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002343 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002344 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002345
2346 // Create the shuffle mask for "rotating" the borrow up one register slot
2347 // once the borrow is generated.
2348 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2349 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2350 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2351 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2352
Dan Gohman475871a2008-07-27 21:46:04 +00002353 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002354 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002355 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002356 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2357 CarryGen, CarryGen,
2358 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2359 &ShufBytes[0], ShufBytes.size()));
2360
2361 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2362 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2363 Op0, Op1, ShiftedCarry));
2364 }
2365
2366 case ISD::SUB: {
2367 // Turn operands into vectors to satisfy type checking (shufb works on
2368 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002369 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002370 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002371 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002372 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002373 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002374
2375 // Create the shuffle mask for "rotating" the borrow up one register slot
2376 // once the borrow is generated.
2377 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2378 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2379 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2380 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2381
Dan Gohman475871a2008-07-27 21:46:04 +00002382 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002383 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002384 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002385 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2386 BorrowGen, BorrowGen,
2387 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2388 &ShufBytes[0], ShufBytes.size()));
2389
2390 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2391 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2392 Op0, Op1, ShiftedBorrow));
2393 }
2394
Scott Michela59d4692008-02-23 18:41:37 +00002395 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002396 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002397 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002398 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2399 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002400 DAG.getNode(SPUISD::SELB, VecVT,
2401 Op0Vec,
2402 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002403 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002404 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002405 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002406 DAG.getNode(ISD::SRL, ShiftAmtVT,
2407 ShiftAmt,
2408 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002409 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002410 DAG.getNode(ISD::AND, ShiftAmtVT,
2411 ShiftAmt,
2412 DAG.getConstant(7, ShiftAmtVT));
2413
2414 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2415 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2416 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2417 MaskLower, ShiftAmtBytes),
2418 ShiftAmtBits));
2419 }
2420
2421 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002422 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002423 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002424 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002425 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002426 DAG.getNode(ISD::SRL, ShiftAmtVT,
2427 ShiftAmt,
2428 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002429 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002430 DAG.getNode(ISD::AND, ShiftAmtVT,
2431 ShiftAmt,
2432 DAG.getConstant(7, ShiftAmtVT));
2433
2434 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2435 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2436 Op0, ShiftAmtBytes),
2437 ShiftAmtBits);
2438 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002439
2440 case ISD::SRA: {
2441 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002442 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002443 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002444 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002445 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002446
2447 // Negate variable shift amounts
2448 if (!isa<ConstantSDNode>(ShiftAmt)) {
2449 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2450 DAG.getConstant(0, ShiftVT), ShiftAmt);
2451 }
2452
Dan Gohman475871a2008-07-27 21:46:04 +00002453 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002454 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2455 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2456 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2457 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002458 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002459 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002460 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002461 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2462 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002463 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002464 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2465 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002466 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002467 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2468 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002469 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002470 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2471 RotateLeftBytes, ShiftAmt);
2472
2473 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2474 RotateLeftBits);
2475 }
Scott Michela59d4692008-02-23 18:41:37 +00002476 }
2477
Dan Gohman475871a2008-07-27 21:46:04 +00002478 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002479}
2480
Scott Michel266bc8f2007-12-04 22:23:35 +00002481//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002482static SDValue
2483LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2484 SDValue ConstVec;
2485 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002486 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002487
2488 ConstVec = Op.getOperand(0);
2489 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002490 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2491 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002492 ConstVec = ConstVec.getOperand(0);
2493 } else {
2494 ConstVec = Op.getOperand(1);
2495 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002496 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002497 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002498 }
2499 }
2500 }
2501
Gabor Greifba36cb52008-08-28 21:40:38 +00002502 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002503 uint64_t VectorBits[2];
2504 uint64_t UndefBits[2];
2505 uint64_t SplatBits, SplatUndef;
2506 int SplatSize;
2507
Gabor Greifba36cb52008-08-28 21:40:38 +00002508 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002509 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002510 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002511 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002512 SDValue tcVec[16];
2513 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002514 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2515
2516 // Turn the BUILD_VECTOR into a set of target constants:
2517 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002518 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002519
Gabor Greifba36cb52008-08-28 21:40:38 +00002520 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002521 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002522 }
2523 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002524 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2525 // lowered. Return the operation, rather than a null SDValue.
2526 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002527}
2528
2529//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002530static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002531 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002532 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002533 default:
2534 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002535 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002536 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002537 abort();
2538 /*NOTREACHED*/
2539
2540 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002541 SDValue rA = Op.getOperand(0);
2542 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002543
2544 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002545 DAG.getNode(ISD::ADD, MVT::i32,
2546 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2547 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2548 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002549 }
2550 }
2551
Dan Gohman475871a2008-07-27 21:46:04 +00002552 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002553}
2554
2555//! Custom lowering for CTPOP (count population)
2556/*!
2557 Custom lowering code that counts the number ones in the input
2558 operand. SPU has such an instruction, but it counts the number of
2559 ones per byte, which then have to be accumulated.
2560*/
Dan Gohman475871a2008-07-27 21:46:04 +00002561static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002562 MVT VT = Op.getValueType();
2563 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002564
Duncan Sands83ec4b62008-06-06 12:08:01 +00002565 switch (VT.getSimpleVT()) {
2566 default:
2567 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002568 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002569 SDValue N = Op.getOperand(0);
2570 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002571
Dan Gohman475871a2008-07-27 21:46:04 +00002572 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2573 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002574
2575 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2576 }
2577
2578 case MVT::i16: {
2579 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002580 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002581
Chris Lattner84bc5422007-12-31 04:13:23 +00002582 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002583
Dan Gohman475871a2008-07-27 21:46:04 +00002584 SDValue N = Op.getOperand(0);
2585 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2586 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
2587 SDValue Shift1 = DAG.getConstant(8, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002588
Dan Gohman475871a2008-07-27 21:46:04 +00002589 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2590 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002591
2592 // CNTB_result becomes the chain to which all of the virtual registers
2593 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002594 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002595 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002596
Dan Gohman475871a2008-07-27 21:46:04 +00002597 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002598 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2599
Dan Gohman475871a2008-07-27 21:46:04 +00002600 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002601
2602 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002603 DAG.getNode(ISD::ADD, MVT::i16,
2604 DAG.getNode(ISD::SRL, MVT::i16,
2605 Tmp1, Shift1),
2606 Tmp1),
2607 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002608 }
2609
2610 case MVT::i32: {
2611 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002612 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002613
Chris Lattner84bc5422007-12-31 04:13:23 +00002614 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2615 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002616
Dan Gohman475871a2008-07-27 21:46:04 +00002617 SDValue N = Op.getOperand(0);
2618 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2619 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2620 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2621 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002622
Dan Gohman475871a2008-07-27 21:46:04 +00002623 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2624 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002625
2626 // CNTB_result becomes the chain to which all of the virtual registers
2627 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002628 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002629 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002630
Dan Gohman475871a2008-07-27 21:46:04 +00002631 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002632 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2633
Dan Gohman475871a2008-07-27 21:46:04 +00002634 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002635 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002636 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002637
Dan Gohman475871a2008-07-27 21:46:04 +00002638 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002639 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002640 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002641
Dan Gohman475871a2008-07-27 21:46:04 +00002642 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002643 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2644
Dan Gohman475871a2008-07-27 21:46:04 +00002645 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002646 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002647 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2648 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002649 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002650 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002651 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002652
2653 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2654 }
2655
2656 case MVT::i64:
2657 break;
2658 }
2659
Dan Gohman475871a2008-07-27 21:46:04 +00002660 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002661}
2662
2663/// LowerOperation - Provide custom lowering hooks for some operations.
2664///
Dan Gohman475871a2008-07-27 21:46:04 +00002665SDValue
2666SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002667{
Scott Michela59d4692008-02-23 18:41:37 +00002668 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002669 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002670
2671 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002672 default: {
2673 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002674 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002675 cerr << "*Op.getNode():\n";
2676 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002677 abort();
2678 }
2679 case ISD::LOAD:
2680 case ISD::SEXTLOAD:
2681 case ISD::ZEXTLOAD:
2682 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2683 case ISD::STORE:
2684 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2685 case ISD::ConstantPool:
2686 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2687 case ISD::GlobalAddress:
2688 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2689 case ISD::JumpTable:
2690 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2691 case ISD::Constant:
2692 return LowerConstant(Op, DAG);
2693 case ISD::ConstantFP:
2694 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002695 case ISD::BRCOND:
2696 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002697 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002698 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002699 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002700 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002701 case ISD::RET:
2702 return LowerRET(Op, DAG, getTargetMachine());
2703
Scott Michela59d4692008-02-23 18:41:37 +00002704
2705 // i8, i64 math ops:
2706 case ISD::ZERO_EXTEND:
2707 case ISD::SIGN_EXTEND:
2708 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002709 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002710 case ISD::SUB:
2711 case ISD::ROTR:
2712 case ISD::ROTL:
2713 case ISD::SRL:
2714 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002715 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002716 if (VT == MVT::i8)
2717 return LowerI8Math(Op, DAG, Opc);
2718 else if (VT == MVT::i64)
2719 return LowerI64Math(Op, DAG, Opc);
2720 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002721 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002722
2723 // Vector-related lowering.
2724 case ISD::BUILD_VECTOR:
2725 return LowerBUILD_VECTOR(Op, DAG);
2726 case ISD::SCALAR_TO_VECTOR:
2727 return LowerSCALAR_TO_VECTOR(Op, DAG);
2728 case ISD::VECTOR_SHUFFLE:
2729 return LowerVECTOR_SHUFFLE(Op, DAG);
2730 case ISD::EXTRACT_VECTOR_ELT:
2731 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2732 case ISD::INSERT_VECTOR_ELT:
2733 return LowerINSERT_VECTOR_ELT(Op, DAG);
2734
2735 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2736 case ISD::AND:
2737 case ISD::OR:
2738 case ISD::XOR:
2739 return LowerByteImmed(Op, DAG);
2740
2741 // Vector and i8 multiply:
2742 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002743 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002744 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002745 else if (VT == MVT::i8)
2746 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002747 else
Scott Michela59d4692008-02-23 18:41:37 +00002748 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002749
2750 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002751 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002752 return LowerFDIVf32(Op, DAG);
2753// else if (Op.getValueType() == MVT::f64)
2754// return LowerFDIVf64(Op, DAG);
2755 else
2756 assert(0 && "Calling FDIV on unsupported MVT");
2757
2758 case ISD::CTPOP:
2759 return LowerCTPOP(Op, DAG);
2760 }
2761
Dan Gohman475871a2008-07-27 21:46:04 +00002762 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002763}
2764
2765//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002766// Target Optimization Hooks
2767//===----------------------------------------------------------------------===//
2768
Dan Gohman475871a2008-07-27 21:46:04 +00002769SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002770SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2771{
2772#if 0
2773 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002774#endif
2775 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002776 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002777 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2778 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002779
2780 switch (N->getOpcode()) {
2781 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002782 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002783 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002784
Scott Michel8bf61e82008-06-02 22:18:03 +00002785 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002786 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002787 if (Op01.getOpcode() == ISD::Constant
2788 || Op01.getOpcode() == ISD::TargetConstant) {
2789 // (add <const>, (SPUindirect <arg>, <const>)) ->
2790 // (SPUindirect <arg>, <const + const>)
2791 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2792 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002793 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002794 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002795 Op0.getValueType());
2796
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002797 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2798 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002799 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002800 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002801 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2802 Op0.getOperand(0), combinedConst);
2803 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002804 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002805 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002806 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002807 if (Op11.getOpcode() == ISD::Constant
2808 || Op11.getOpcode() == ISD::TargetConstant) {
2809 // (add (SPUindirect <arg>, <const>), <const>) ->
2810 // (SPUindirect <arg>, <const + const>)
2811 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2812 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002813 SDValue combinedConst =
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002814 DAG.getConstant(CN0->getZExtValue() + CN1->getZExtValue(),
Scott Michel053c1da2008-01-29 02:16:57 +00002815 Op0.getValueType());
2816
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002817 DEBUG(cerr << "Replace: (add " << CN0->getZExtValue() << ", "
2818 << "(SPUindirect <arg>, " << CN1->getZExtValue() << "))\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002819 DEBUG(cerr << "With: (SPUindirect <arg>, "
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002820 << CN0->getZExtValue() + CN1->getZExtValue() << ")\n");
Scott Michel053c1da2008-01-29 02:16:57 +00002821
2822 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2823 Op1.getOperand(0), combinedConst);
2824 }
2825 }
Scott Michela59d4692008-02-23 18:41:37 +00002826 break;
2827 }
2828 case ISD::SIGN_EXTEND:
2829 case ISD::ZERO_EXTEND:
2830 case ISD::ANY_EXTEND: {
2831 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2832 N->getValueType(0) == Op0.getValueType()) {
2833 // (any_extend (SPUextract_elt0 <arg>)) ->
2834 // (SPUextract_elt0 <arg>)
2835 // Types must match, however...
2836 DEBUG(cerr << "Replace: ");
2837 DEBUG(N->dump(&DAG));
2838 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002839 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002840 DEBUG(cerr << "\n");
2841
2842 return Op0;
2843 }
2844 break;
2845 }
2846 case SPUISD::IndirectAddr: {
2847 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2848 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002849 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002850 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2851 // (SPUaform <addr>, 0)
2852
2853 DEBUG(cerr << "Replace: ");
2854 DEBUG(N->dump(&DAG));
2855 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002856 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002857 DEBUG(cerr << "\n");
2858
2859 return Op0;
2860 }
2861 }
2862 break;
2863 }
2864 case SPUISD::SHLQUAD_L_BITS:
2865 case SPUISD::SHLQUAD_L_BYTES:
2866 case SPUISD::VEC_SHL:
2867 case SPUISD::VEC_SRL:
2868 case SPUISD::VEC_SRA:
2869 case SPUISD::ROTQUAD_RZ_BYTES:
2870 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002871 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002872
2873 if (isa<ConstantSDNode>(Op1)) {
2874 // Kill degenerate vector shifts:
2875 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2876
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002877 if (CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002878 Result = Op0;
2879 }
2880 }
2881 break;
2882 }
2883 case SPUISD::PROMOTE_SCALAR: {
2884 switch (Op0.getOpcode()) {
2885 default:
2886 break;
2887 case ISD::ANY_EXTEND:
2888 case ISD::ZERO_EXTEND:
2889 case ISD::SIGN_EXTEND: {
2890 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2891 // <arg>
2892 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002893 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002894 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00002895 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002896 if (Op000.getValueType() == N->getValueType(0)) {
2897 Result = Op000;
2898 }
2899 }
2900 break;
2901 }
2902 case SPUISD::EXTRACT_ELT0: {
2903 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2904 // <arg>
2905 Result = Op0.getOperand(0);
2906 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002907 }
Scott Michela59d4692008-02-23 18:41:37 +00002908 }
2909 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002910 }
2911 }
Scott Michel58c58182008-01-17 20:38:41 +00002912 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002913#if 1
Gabor Greifba36cb52008-08-28 21:40:38 +00002914 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00002915 DEBUG(cerr << "\nReplace.SPU: ");
2916 DEBUG(N->dump(&DAG));
2917 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002918 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002919 DEBUG(cerr << "\n");
2920 }
2921#endif
2922
2923 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002924}
2925
2926//===----------------------------------------------------------------------===//
2927// Inline Assembly Support
2928//===----------------------------------------------------------------------===//
2929
2930/// getConstraintType - Given a constraint letter, return the type of
2931/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002932SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002933SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2934 if (ConstraintLetter.size() == 1) {
2935 switch (ConstraintLetter[0]) {
2936 default: break;
2937 case 'b':
2938 case 'r':
2939 case 'f':
2940 case 'v':
2941 case 'y':
2942 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002943 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002944 }
2945 return TargetLowering::getConstraintType(ConstraintLetter);
2946}
2947
Scott Michel5af8f0e2008-07-16 17:17:29 +00002948std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002949SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002950 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002951{
2952 if (Constraint.size() == 1) {
2953 // GCC RS6000 Constraint Letters
2954 switch (Constraint[0]) {
2955 case 'b': // R1-R31
2956 case 'r': // R0-R31
2957 if (VT == MVT::i64)
2958 return std::make_pair(0U, SPU::R64CRegisterClass);
2959 return std::make_pair(0U, SPU::R32CRegisterClass);
2960 case 'f':
2961 if (VT == MVT::f32)
2962 return std::make_pair(0U, SPU::R32FPRegisterClass);
2963 else if (VT == MVT::f64)
2964 return std::make_pair(0U, SPU::R64FPRegisterClass);
2965 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002966 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002967 return std::make_pair(0U, SPU::GPRCRegisterClass);
2968 }
2969 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002970
Scott Michel266bc8f2007-12-04 22:23:35 +00002971 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2972}
2973
Scott Michela59d4692008-02-23 18:41:37 +00002974//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002975void
Dan Gohman475871a2008-07-27 21:46:04 +00002976SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002977 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002978 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002979 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002980 const SelectionDAG &DAG,
2981 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002982#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002983 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002984#endif
Scott Michela59d4692008-02-23 18:41:37 +00002985
2986 switch (Op.getOpcode()) {
2987 default:
2988 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2989 break;
2990
2991#if 0
2992 case CALL:
2993 case SHUFB:
2994 case INSERT_MASK:
2995 case CNTB:
2996#endif
2997
2998 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00002999 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00003000 MVT Op0VT = Op0.getValueType();
3001 unsigned Op0VTBits = Op0VT.getSizeInBits();
3002 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003003 KnownZero |= APInt(Op0VTBits, ~InMask, false);
3004 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003005 break;
3006 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003007
Scott Michela59d4692008-02-23 18:41:37 +00003008 case SPUISD::LDRESULT:
3009 case SPUISD::EXTRACT_ELT0:
3010 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00003011 MVT OpVT = Op.getValueType();
3012 unsigned OpVTBits = OpVT.getSizeInBits();
3013 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003014 KnownZero |= APInt(OpVTBits, ~InMask, false);
3015 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003016 break;
3017 }
3018
3019#if 0
3020 case EXTRACT_I1_ZEXT:
3021 case EXTRACT_I1_SEXT:
3022 case EXTRACT_I8_ZEXT:
3023 case EXTRACT_I8_SEXT:
3024 case MPY:
3025 case MPYU:
3026 case MPYH:
3027 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003028 case SPUISD::SHLQUAD_L_BITS:
3029 case SPUISD::SHLQUAD_L_BYTES:
3030 case SPUISD::VEC_SHL:
3031 case SPUISD::VEC_SRL:
3032 case SPUISD::VEC_SRA:
3033 case SPUISD::VEC_ROTL:
3034 case SPUISD::VEC_ROTR:
3035 case SPUISD::ROTQUAD_RZ_BYTES:
3036 case SPUISD::ROTQUAD_RZ_BITS:
3037 case SPUISD::ROTBYTES_RIGHT_S:
3038 case SPUISD::ROTBYTES_LEFT:
3039 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003040 case SPUISD::SELECT_MASK:
3041 case SPUISD::SELB:
3042 case SPUISD::FPInterp:
3043 case SPUISD::FPRecipEst:
3044 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003045#endif
3046 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003047}
3048
Scott Michel203b2d62008-04-30 00:30:08 +00003049// LowerAsmOperandForConstraint
3050void
Dan Gohman475871a2008-07-27 21:46:04 +00003051SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003052 char ConstraintLetter,
Dan Gohman475871a2008-07-27 21:46:04 +00003053 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003054 SelectionDAG &DAG) const {
3055 // Default, for the time being, to the base class handler
3056 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, Ops, DAG);
3057}
3058
Scott Michel266bc8f2007-12-04 22:23:35 +00003059/// isLegalAddressImmediate - Return true if the integer value can be used
3060/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003061bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3062 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003063 // SPU's addresses are 256K:
3064 return (V > -(1 << 18) && V < (1 << 18) - 1);
3065}
3066
3067bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003068 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003069}