blob: 3009143d98b823410bb89225d281faa6429ffeb5 [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
527 alignOffs = (int) CN->getValue();
528 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 Gohman475871a2008-07-27 21:46:04 +0000883 SDValue T = DAG.getConstant(CN->getValue(), 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);
Scott Michel266bc8f2007-12-04 22:23:35 +0000941 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
942
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
Scott Michel266bc8f2007-12-04 22:23:35 +00001093 int Addr = C->getValue();
1094 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
Gabor Greifba36cb52008-08-28 21:40:38 +00001098 return DAG.getConstant((int)C->getValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001099}
1100
1101static
Dan Gohman475871a2008-07-27 21:46:04 +00001102SDValue
1103LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
1104 SDValue Chain = Op.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001105#if 0
1106 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
1107 bool isTailCall = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
1108#endif
Dan Gohman475871a2008-07-27 21:46:04 +00001109 SDValue Callee = Op.getOperand(4);
Scott Michel266bc8f2007-12-04 22:23:35 +00001110 unsigned NumOps = (Op.getNumOperands() - 5) / 2;
1111 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1112 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1113 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1114
1115 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001116 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001117
Scott Michel266bc8f2007-12-04 22:23:35 +00001118 // Accumulate how many bytes are to be pushed on the stack, including the
1119 // linkage area, and parameter passing area. According to the SPU ABI,
1120 // we minimally need space for [LR] and [SP]
1121 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001122
Scott Michel266bc8f2007-12-04 22:23:35 +00001123 // Set up a copy of the stack pointer for use loading and storing any
1124 // arguments that may not fit in the registers available for argument
1125 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001126 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001127
Scott Michel266bc8f2007-12-04 22:23:35 +00001128 // Figure out which arguments are going to go in registers, and which in
1129 // memory.
1130 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1131 unsigned ArgRegIdx = 0;
1132
1133 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001134 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001135 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001136 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001137
1138 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001139 SDValue Arg = Op.getOperand(5+2*i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001140
Scott Michel266bc8f2007-12-04 22:23:35 +00001141 // PtrOff will be used to store the current argument to the stack if a
1142 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001143 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001144 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1145
Duncan Sands83ec4b62008-06-06 12:08:01 +00001146 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001147 default: assert(0 && "Unexpected ValueType for argument!");
1148 case MVT::i32:
1149 case MVT::i64:
1150 case MVT::i128:
1151 if (ArgRegIdx != NumArgRegs) {
1152 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1153 } else {
1154 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001155 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001156 }
1157 break;
1158 case MVT::f32:
1159 case MVT::f64:
1160 if (ArgRegIdx != NumArgRegs) {
1161 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1162 } else {
1163 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001164 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001165 }
1166 break;
1167 case MVT::v4f32:
1168 case MVT::v4i32:
1169 case MVT::v8i16:
1170 case MVT::v16i8:
1171 if (ArgRegIdx != NumArgRegs) {
1172 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1173 } else {
1174 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001175 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001176 }
1177 break;
1178 }
1179 }
1180
1181 // Update number of stack bytes actually used, insert a call sequence start
1182 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
1183 Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumStackBytes, PtrVT));
1184
1185 if (!MemOpChains.empty()) {
1186 // Adjust the stack pointer for the stack arguments.
1187 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1188 &MemOpChains[0], MemOpChains.size());
1189 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001190
Scott Michel266bc8f2007-12-04 22:23:35 +00001191 // Build a sequence of copy-to-reg nodes chained together with token chain
1192 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001193 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001194 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1195 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1196 InFlag);
1197 InFlag = Chain.getValue(1);
1198 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001199
Dan Gohman475871a2008-07-27 21:46:04 +00001200 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001201 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001202
Scott Michel266bc8f2007-12-04 22:23:35 +00001203 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1204 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1205 // node so that legalize doesn't hack it.
1206 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1207 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001208 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001209 SDValue Zero = DAG.getConstant(0, PtrVT);
1210 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001211
Scott Michel9de5d0d2008-01-11 02:53:15 +00001212 if (!ST->usingLargeMem()) {
1213 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1214 // style calls, otherwise, external symbols are BRASL calls. This assumes
1215 // that declared/defined symbols are in the same compilation unit and can
1216 // be reached through PC-relative jumps.
1217 //
1218 // NOTE:
1219 // This may be an unsafe assumption for JIT and really large compilation
1220 // units.
1221 if (GV->isDeclaration()) {
1222 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1223 } else {
1224 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1225 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001226 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001227 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1228 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001229 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001230 }
1231 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
1232 Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
Scott Michel9de5d0d2008-01-11 02:53:15 +00001233 else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001234 // If this is an absolute destination address that appears to be a legal
1235 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001236 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001237 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001238
1239 Ops.push_back(Chain);
1240 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001241
Scott Michel266bc8f2007-12-04 22:23:35 +00001242 // Add argument registers to the end of the list so that they are known live
1243 // into the call.
1244 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001245 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001246 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001247
Gabor Greifba36cb52008-08-28 21:40:38 +00001248 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001249 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001250 // Returns a chain and a flag for retval copy to use.
1251 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1252 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001253 InFlag = Chain.getValue(1);
1254
Evan Chengebaaa912008-02-05 22:44:06 +00001255 Chain = DAG.getCALLSEQ_END(Chain,
1256 DAG.getConstant(NumStackBytes, PtrVT),
1257 DAG.getConstant(0, PtrVT),
1258 InFlag);
Gabor Greifba36cb52008-08-28 21:40:38 +00001259 if (Op.getNode()->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001260 InFlag = Chain.getValue(1);
1261
Dan Gohman475871a2008-07-27 21:46:04 +00001262 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001263 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001264
Scott Michel266bc8f2007-12-04 22:23:35 +00001265 // If the call has results, copy the values out of the ret val registers.
Gabor Greifba36cb52008-08-28 21:40:38 +00001266 switch (Op.getNode()->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001267 default: assert(0 && "Unexpected ret value!");
1268 case MVT::Other: break;
1269 case MVT::i32:
Gabor Greifba36cb52008-08-28 21:40:38 +00001270 if (Op.getNode()->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001271 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1272 ResultVals[0] = Chain.getValue(0);
1273 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1274 Chain.getValue(2)).getValue(1);
1275 ResultVals[1] = Chain.getValue(0);
1276 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001277 } else {
1278 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1279 ResultVals[0] = Chain.getValue(0);
1280 NumResults = 1;
1281 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001282 break;
1283 case MVT::i64:
1284 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1285 ResultVals[0] = Chain.getValue(0);
1286 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001287 break;
1288 case MVT::f32:
1289 case MVT::f64:
Gabor Greifba36cb52008-08-28 21:40:38 +00001290 Chain = DAG.getCopyFromReg(Chain, SPU::R3, Op.getNode()->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001291 InFlag).getValue(1);
1292 ResultVals[0] = Chain.getValue(0);
1293 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001294 break;
1295 case MVT::v2f64:
1296 case MVT::v4f32:
1297 case MVT::v4i32:
1298 case MVT::v8i16:
1299 case MVT::v16i8:
Gabor Greifba36cb52008-08-28 21:40:38 +00001300 Chain = DAG.getCopyFromReg(Chain, SPU::R3, Op.getNode()->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001301 InFlag).getValue(1);
1302 ResultVals[0] = Chain.getValue(0);
1303 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001304 break;
1305 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001306
Scott Michel266bc8f2007-12-04 22:23:35 +00001307 // If the function returns void, just return the chain.
1308 if (NumResults == 0)
1309 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001310
Scott Michel266bc8f2007-12-04 22:23:35 +00001311 // Otherwise, merge everything together with a MERGE_VALUES node.
1312 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001313 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001314 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001315}
1316
Dan Gohman475871a2008-07-27 21:46:04 +00001317static SDValue
1318LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001319 SmallVector<CCValAssign, 16> RVLocs;
1320 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
1321 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
1322 CCState CCInfo(CC, isVarArg, TM, RVLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +00001323 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001324
Scott Michel266bc8f2007-12-04 22:23:35 +00001325 // If this is the first return lowered for this function, add the regs to the
1326 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001327 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001328 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001329 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001330 }
1331
Dan Gohman475871a2008-07-27 21:46:04 +00001332 SDValue Chain = Op.getOperand(0);
1333 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001334
Scott Michel266bc8f2007-12-04 22:23:35 +00001335 // Copy the result values into the output registers.
1336 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1337 CCValAssign &VA = RVLocs[i];
1338 assert(VA.isRegLoc() && "Can only return in registers!");
1339 Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag);
1340 Flag = Chain.getValue(1);
1341 }
1342
Gabor Greifba36cb52008-08-28 21:40:38 +00001343 if (Flag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001344 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain, Flag);
1345 else
1346 return DAG.getNode(SPUISD::RET_FLAG, MVT::Other, Chain);
1347}
1348
1349
1350//===----------------------------------------------------------------------===//
1351// Vector related lowering:
1352//===----------------------------------------------------------------------===//
1353
1354static ConstantSDNode *
1355getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001356 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001357
Scott Michel266bc8f2007-12-04 22:23:35 +00001358 // Check to see if this buildvec has a single non-undef value in its elements.
1359 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1360 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001361 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001362 OpVal = N->getOperand(i);
1363 else if (OpVal != N->getOperand(i))
1364 return 0;
1365 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001366
Gabor Greifba36cb52008-08-28 21:40:38 +00001367 if (OpVal.getNode() != 0) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001368 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1369 return CN;
1370 }
1371 }
1372
1373 return 0; // All UNDEF: use implicit def.; not Constant node
1374}
1375
1376/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1377/// and the value fits into an unsigned 18-bit constant, and if so, return the
1378/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001379SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001380 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001381 if (ConstantSDNode *CN = getVecImm(N)) {
1382 uint64_t Value = CN->getValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001383 if (ValueType == MVT::i64) {
1384 uint64_t UValue = CN->getValue();
1385 uint32_t upper = uint32_t(UValue >> 32);
1386 uint32_t lower = uint32_t(UValue);
1387 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001388 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001389 Value = Value >> 32;
1390 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001391 if (Value <= 0x3ffff)
1392 return DAG.getConstant(Value, ValueType);
1393 }
1394
Dan Gohman475871a2008-07-27 21:46:04 +00001395 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001396}
1397
1398/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1399/// and the value fits into a signed 16-bit constant, and if so, return the
1400/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001401SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001402 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001403 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001404 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001405 if (ValueType == MVT::i64) {
1406 uint64_t UValue = CN->getValue();
1407 uint32_t upper = uint32_t(UValue >> 32);
1408 uint32_t lower = uint32_t(UValue);
1409 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001410 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001411 Value = Value >> 32;
1412 }
Scott Michelad2715e2008-03-05 23:02:02 +00001413 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
1414 return DAG.getConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001415 }
1416 }
1417
Dan Gohman475871a2008-07-27 21:46:04 +00001418 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001419}
1420
1421/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1422/// and the value fits into a signed 10-bit constant, and if so, return the
1423/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001424SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001425 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001426 if (ConstantSDNode *CN = getVecImm(N)) {
Scott Michelad2715e2008-03-05 23:02:02 +00001427 int64_t Value = CN->getSignExtended();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001428 if (ValueType == MVT::i64) {
1429 uint64_t UValue = CN->getValue();
1430 uint32_t upper = uint32_t(UValue >> 32);
1431 uint32_t lower = uint32_t(UValue);
1432 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001433 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001434 Value = Value >> 32;
1435 }
Scott Michelad2715e2008-03-05 23:02:02 +00001436 if (isS10Constant(Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001437 return DAG.getConstant(Value, ValueType);
1438 }
1439
Dan Gohman475871a2008-07-27 21:46:04 +00001440 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001441}
1442
1443/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1444/// and the value fits into a signed 8-bit constant, and if so, return the
1445/// constant.
1446///
1447/// @note: The incoming vector is v16i8 because that's the only way we can load
1448/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1449/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001450SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001451 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001452 if (ConstantSDNode *CN = getVecImm(N)) {
1453 int Value = (int) CN->getValue();
1454 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001455 && Value <= 0xffff /* truncated from uint64_t */
1456 && ((short) Value >> 8) == ((short) Value & 0xff))
Scott Michel266bc8f2007-12-04 22:23:35 +00001457 return DAG.getConstant(Value & 0xff, ValueType);
1458 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001459 && (Value & 0xff) == Value)
Scott Michel266bc8f2007-12-04 22:23:35 +00001460 return DAG.getConstant(Value, ValueType);
1461 }
1462
Dan Gohman475871a2008-07-27 21:46:04 +00001463 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001464}
1465
1466/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1467/// and the value fits into a signed 16-bit constant, and if so, return the
1468/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001469SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001470 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001471 if (ConstantSDNode *CN = getVecImm(N)) {
1472 uint64_t Value = CN->getValue();
1473 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001474 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1475 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Scott Michel266bc8f2007-12-04 22:23:35 +00001476 return DAG.getConstant(Value >> 16, ValueType);
1477 }
1478
Dan Gohman475871a2008-07-27 21:46:04 +00001479 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001480}
1481
1482/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001483SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001484 if (ConstantSDNode *CN = getVecImm(N)) {
1485 return DAG.getConstant((unsigned) CN->getValue(), MVT::i32);
1486 }
1487
Dan Gohman475871a2008-07-27 21:46:04 +00001488 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001489}
1490
1491/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001492SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001493 if (ConstantSDNode *CN = getVecImm(N)) {
1494 return DAG.getConstant((unsigned) CN->getValue(), MVT::i64);
1495 }
1496
Dan Gohman475871a2008-07-27 21:46:04 +00001497 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001498}
1499
1500// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001501// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001502// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
1503// zero. Return true if this is not an array of constants, false if it is.
1504//
1505static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
1506 uint64_t UndefBits[2]) {
1507 // Start with zero'd results.
1508 VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001509
Duncan Sands83ec4b62008-06-06 12:08:01 +00001510 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001511 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001512 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001513
Scott Michel266bc8f2007-12-04 22:23:35 +00001514 unsigned PartNo = i >= e/2; // In the upper 128 bits?
1515 unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
1516
1517 uint64_t EltBits = 0;
1518 if (OpVal.getOpcode() == ISD::UNDEF) {
1519 uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
1520 UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
1521 continue;
1522 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1523 EltBits = CN->getValue() & (~0ULL >> (64-EltBitSize));
1524 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
1525 const APFloat &apf = CN->getValueAPF();
1526 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001527 ? FloatToBits(apf.convertToFloat())
1528 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001529 } else {
1530 // Nonconstant element.
1531 return true;
1532 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001533
Scott Michel266bc8f2007-12-04 22:23:35 +00001534 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1535 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001536
1537 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-12-04 22:23:35 +00001538 // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
1539 return false;
1540}
1541
1542/// If this is a splat (repetition) of a value across the whole vector, return
1543/// the smallest size that splats it. For example, "0x01010101010101..." is a
Scott Michel5af8f0e2008-07-16 17:17:29 +00001544/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001545/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001546static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001547 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001548 int MinSplatBits,
Scott Michel266bc8f2007-12-04 22:23:35 +00001549 uint64_t &SplatBits, uint64_t &SplatUndef,
1550 int &SplatSize) {
1551 // Don't let undefs prevent splats from matching. See if the top 64-bits are
1552 // the same as the lower 64-bits, ignoring undefs.
1553 uint64_t Bits64 = Bits128[0] | Bits128[1];
1554 uint64_t Undef64 = Undef128[0] & Undef128[1];
1555 uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
1556 uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
1557 uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
1558 uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
1559
1560 if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
1561 if (MinSplatBits < 64) {
Scott Michel5af8f0e2008-07-16 17:17:29 +00001562
Scott Michel266bc8f2007-12-04 22:23:35 +00001563 // Check that the top 32-bits are the same as the lower 32-bits, ignoring
1564 // undefs.
1565 if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001566 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001567
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001568 // If the top 16-bits are different than the lower 16-bits, ignoring
1569 // undefs, we have an i32 splat.
1570 if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
1571 if (MinSplatBits < 16) {
1572 // If the top 8-bits are different than the lower 8-bits, ignoring
1573 // undefs, we have an i16 splat.
Gabor Greif93c53e52008-08-31 15:37:04 +00001574 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1575 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001576 // Otherwise, we have an 8-bit splat.
1577 SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
1578 SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
1579 SplatSize = 1;
1580 return true;
1581 }
1582 } else {
1583 SplatBits = Bits16;
1584 SplatUndef = Undef16;
1585 SplatSize = 2;
1586 return true;
1587 }
1588 }
1589 } else {
1590 SplatBits = Bits32;
1591 SplatUndef = Undef32;
1592 SplatSize = 4;
1593 return true;
1594 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001595 }
1596 } else {
1597 SplatBits = Bits128[0];
1598 SplatUndef = Undef128[0];
1599 SplatSize = 8;
1600 return true;
1601 }
1602 }
1603
1604 return false; // Can't be a splat if two pieces don't match.
1605}
1606
1607// If this is a case we can't handle, return null and let the default
1608// expansion code take care of it. If we CAN select this case, and if it
1609// selects to a single instruction, return Op. Otherwise, if we can codegen
1610// this case more efficiently than a constant pool load, lower it to the
1611// sequence of ops that should be used.
Dan Gohman475871a2008-07-27 21:46:04 +00001612static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001613 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001614 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001615 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001616 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001617 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001618 uint64_t VectorBits[2];
1619 uint64_t UndefBits[2];
1620 uint64_t SplatBits, SplatUndef;
1621 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001622 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001623 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001624 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001625 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001626 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001627
Duncan Sands83ec4b62008-06-06 12:08:01 +00001628 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001629 default:
1630 case MVT::v4f32: {
1631 uint32_t Value32 = SplatBits;
1632 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001633 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001634 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001635 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001636 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001637 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001638 break;
1639 }
1640 case MVT::v2f64: {
1641 uint64_t f64val = SplatBits;
1642 assert(SplatSize == 8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001643 && "LowerBUILD_VECTOR: 64-bit float vector element: unexpected size.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001644 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001645 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001646 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001647 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001648 break;
1649 }
1650 case MVT::v16i8: {
1651 // 8-bit constants have to be expanded to 16-bits
1652 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001653 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001654 for (int i = 0; i < 8; ++i)
1655 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1656 return DAG.getNode(ISD::BIT_CONVERT, VT,
1657 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1658 }
1659 case MVT::v8i16: {
1660 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001661 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001662 Value16 = (unsigned short) (SplatBits & 0xffff);
1663 else
1664 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001665 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1666 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001667 for (int i = 0; i < 8; ++i) Ops[i] = T;
1668 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1669 }
1670 case MVT::v4i32: {
1671 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001672 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001673 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1674 }
1675 case MVT::v2i64: {
1676 uint64_t val = SplatBits;
1677 uint32_t upper = uint32_t(val >> 32);
1678 uint32_t lower = uint32_t(val);
1679
Scott Michel4cb8bd82008-03-06 04:02:54 +00001680 if (upper == lower) {
1681 // Magic constant that can be matched by IL, ILA, et. al.
Dan Gohman475871a2008-07-27 21:46:04 +00001682 SDValue Val = DAG.getTargetConstant(val, MVT::i64);
Scott Michel4cb8bd82008-03-06 04:02:54 +00001683 return DAG.getNode(ISD::BUILD_VECTOR, VT, Val, Val);
Scott Michelad2715e2008-03-05 23:02:02 +00001684 } else {
Dan Gohman475871a2008-07-27 21:46:04 +00001685 SDValue LO32;
1686 SDValue HI32;
1687 SmallVector<SDValue, 16> ShufBytes;
1688 SDValue Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001689 bool upper_special, lower_special;
1690
1691 // NOTE: This code creates common-case shuffle masks that can be easily
1692 // detected as common expressions. It is not attempting to create highly
1693 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1694
1695 // Detect if the upper or lower half is a special shuffle mask pattern:
1696 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1697 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1698
1699 // Create lower vector if not a special pattern
1700 if (!lower_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001701 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001702 LO32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1703 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1704 LO32C, LO32C, LO32C, LO32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001705 }
1706
1707 // Create upper vector if not a special pattern
1708 if (!upper_special) {
Dan Gohman475871a2008-07-27 21:46:04 +00001709 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001710 HI32 = DAG.getNode(ISD::BIT_CONVERT, VT,
1711 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1712 HI32C, HI32C, HI32C, HI32C));
Scott Michel266bc8f2007-12-04 22:23:35 +00001713 }
1714
1715 // If either upper or lower are special, then the two input operands are
1716 // the same (basically, one of them is a "don't care")
1717 if (lower_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001718 LO32 = HI32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001719 if (upper_special)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001720 HI32 = LO32;
Scott Michel266bc8f2007-12-04 22:23:35 +00001721 if (lower_special && upper_special) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001722 // Unhappy situation... both upper and lower are special, so punt with
1723 // a target constant:
Dan Gohman475871a2008-07-27 21:46:04 +00001724 SDValue Zero = DAG.getConstant(0, MVT::i32);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001725 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
Scott Michel266bc8f2007-12-04 22:23:35 +00001726 Zero, Zero);
1727 }
1728
1729 for (int i = 0; i < 4; ++i) {
Scott Michel8bf61e82008-06-02 22:18:03 +00001730 uint64_t val = 0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001731 for (int j = 0; j < 4; ++j) {
Dan Gohman475871a2008-07-27 21:46:04 +00001732 SDValue V;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001733 bool process_upper, process_lower;
Scott Michel8bf61e82008-06-02 22:18:03 +00001734 val <<= 8;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001735 process_upper = (upper_special && (i & 1) == 0);
1736 process_lower = (lower_special && (i & 1) == 1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001737
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001738 if (process_upper || process_lower) {
1739 if ((process_upper && upper == 0)
1740 || (process_lower && lower == 0))
Scott Michel8bf61e82008-06-02 22:18:03 +00001741 val |= 0x80;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001742 else if ((process_upper && upper == 0xffffffff)
1743 || (process_lower && lower == 0xffffffff))
Scott Michel8bf61e82008-06-02 22:18:03 +00001744 val |= 0xc0;
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001745 else if ((process_upper && upper == 0x80000000)
1746 || (process_lower && lower == 0x80000000))
Scott Michel8bf61e82008-06-02 22:18:03 +00001747 val |= (j == 0 ? 0xe0 : 0x80);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001748 } else
Scott Michel8bf61e82008-06-02 22:18:03 +00001749 val |= i * 4 + j + ((i & 1) * 16);
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001750 }
Scott Michel8bf61e82008-06-02 22:18:03 +00001751
1752 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001753 }
1754
1755 return DAG.getNode(SPUISD::SHUFB, VT, HI32, LO32,
Scott Michel8bf61e82008-06-02 22:18:03 +00001756 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001757 &ShufBytes[0], ShufBytes.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001758 }
1759 }
1760 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001761
Dan Gohman475871a2008-07-27 21:46:04 +00001762 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001763}
1764
1765/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1766/// which the Cell can operate. The code inspects V3 to ascertain whether the
1767/// permutation vector, V3, is monotonically increasing with one "exception"
1768/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1769/// INSERT_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1770/// In either case, the net result is going to eventually invoke SHUFB to
1771/// permute/shuffle the bytes from V1 and V2.
1772/// \note
1773/// INSERT_MASK is eventually selected as one of the C*D instructions, generate
1774/// control word for byte/halfword/word insertion. This takes care of a single
1775/// element move from V2 into V1.
1776/// \note
1777/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001778static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1779 SDValue V1 = Op.getOperand(0);
1780 SDValue V2 = Op.getOperand(1);
1781 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001782
Scott Michel266bc8f2007-12-04 22:23:35 +00001783 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001784
Scott Michel266bc8f2007-12-04 22:23:35 +00001785 // If we have a single element being moved from V1 to V2, this can be handled
1786 // using the C*[DX] compute mask instructions, but the vector elements have
1787 // to be monotonically increasing with one exception element.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001788 MVT EltVT = V1.getValueType().getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001789 unsigned EltsFromV2 = 0;
1790 unsigned V2Elt = 0;
1791 unsigned V2EltIdx0 = 0;
1792 unsigned CurrElt = 0;
1793 bool monotonic = true;
1794 if (EltVT == MVT::i8)
1795 V2EltIdx0 = 16;
1796 else if (EltVT == MVT::i16)
1797 V2EltIdx0 = 8;
1798 else if (EltVT == MVT::i32)
1799 V2EltIdx0 = 4;
1800 else
1801 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1802
1803 for (unsigned i = 0, e = PermMask.getNumOperands();
1804 EltsFromV2 <= 1 && monotonic && i != e;
1805 ++i) {
1806 unsigned SrcElt;
1807 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
1808 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001809 else
Scott Michel266bc8f2007-12-04 22:23:35 +00001810 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getValue();
1811
1812 if (SrcElt >= V2EltIdx0) {
1813 ++EltsFromV2;
1814 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1815 } else if (CurrElt != SrcElt) {
1816 monotonic = false;
1817 }
1818
1819 ++CurrElt;
1820 }
1821
1822 if (EltsFromV2 == 1 && monotonic) {
1823 // Compute mask and shuffle
1824 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001825 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1826 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001827 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001828 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001829 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001830 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
1831 // Copy register's contents as index in INSERT_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001832 SDValue ShufMaskOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001833 DAG.getNode(SPUISD::INSERT_MASK, V1.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001834 DAG.getTargetConstant(V2Elt, MVT::i32),
1835 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001836 // Use shuffle mask in SHUFB synthetic instruction:
1837 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
1838 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001839 // Convert the SHUFFLE_VECTOR mask's input element units to the
1840 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001841 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001842
Dan Gohman475871a2008-07-27 21:46:04 +00001843 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001844 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1845 unsigned SrcElt;
1846 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001847 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001848 else
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001849 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001850
Scott Michela59d4692008-02-23 18:41:37 +00001851 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001852 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1853 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001854 }
1855 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001856
Dan Gohman475871a2008-07-27 21:46:04 +00001857 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001858 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001859 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1860 }
1861}
1862
Dan Gohman475871a2008-07-27 21:46:04 +00001863static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1864 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001865
Gabor Greifba36cb52008-08-28 21:40:38 +00001866 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001867 // For a constant, build the appropriate constant vector, which will
1868 // eventually simplify to a vector register load.
1869
Gabor Greifba36cb52008-08-28 21:40:38 +00001870 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001871 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001872 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001873 size_t n_copies;
1874
1875 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001876 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001877 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001878 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001879 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1880 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1881 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1882 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1883 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1884 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1885 }
1886
Dan Gohman475871a2008-07-27 21:46:04 +00001887 SDValue CValue = DAG.getConstant(CN->getValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001888 for (size_t j = 0; j < n_copies; ++j)
1889 ConstVecValues.push_back(CValue);
1890
1891 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001892 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001893 } else {
1894 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001895 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001896 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1897 case MVT::i8:
1898 case MVT::i16:
1899 case MVT::i32:
1900 case MVT::i64:
1901 case MVT::f32:
1902 case MVT::f64:
1903 return DAG.getNode(SPUISD::PROMOTE_SCALAR, Op.getValueType(), Op0, Op0);
1904 }
1905 }
1906
Dan Gohman475871a2008-07-27 21:46:04 +00001907 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001908}
1909
Dan Gohman475871a2008-07-27 21:46:04 +00001910static SDValue LowerVectorMUL(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001911 switch (Op.getValueType().getSimpleVT()) {
1912 default:
1913 cerr << "CellSPU: Unknown vector multiplication, got "
1914 << Op.getValueType().getMVTString()
1915 << "\n";
1916 abort();
1917 /*NOTREACHED*/
1918
Scott Michel266bc8f2007-12-04 22:23:35 +00001919 case MVT::v4i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00001920 SDValue rA = Op.getOperand(0);
1921 SDValue rB = Op.getOperand(1);
1922 SDValue HiProd1 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rA, rB);
1923 SDValue HiProd2 = DAG.getNode(SPUISD::MPYH, MVT::v4i32, rB, rA);
1924 SDValue LoProd = DAG.getNode(SPUISD::MPYU, MVT::v4i32, rA, rB);
1925 SDValue Residual1 = DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd1);
Scott Michel266bc8f2007-12-04 22:23:35 +00001926
1927 return DAG.getNode(ISD::ADD, MVT::v4i32, Residual1, HiProd2);
1928 break;
1929 }
1930
1931 // Multiply two v8i16 vectors (pipeline friendly version):
1932 // a) multiply lower halves, mask off upper 16-bit of 32-bit product
1933 // b) multiply upper halves, rotate left by 16 bits (inserts 16 lower zeroes)
1934 // c) Use SELB to select upper and lower halves from the intermediate results
1935 //
Scott Michel8bf61e82008-06-02 22:18:03 +00001936 // NOTE: We really want to move the SELECT_MASK to earlier to actually get the
Scott Michel266bc8f2007-12-04 22:23:35 +00001937 // dual-issue. This code does manage to do this, even if it's a little on
1938 // the wacky side
1939 case MVT::v8i16: {
1940 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001941 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman475871a2008-07-27 21:46:04 +00001942 SDValue Chain = Op.getOperand(0);
1943 SDValue rA = Op.getOperand(0);
1944 SDValue rB = Op.getOperand(1);
Chris Lattner84bc5422007-12-31 04:13:23 +00001945 unsigned FSMBIreg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
1946 unsigned HiProdReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00001947
Dan Gohman475871a2008-07-27 21:46:04 +00001948 SDValue FSMBOp =
Scott Michel266bc8f2007-12-04 22:23:35 +00001949 DAG.getCopyToReg(Chain, FSMBIreg,
Scott Michel8bf61e82008-06-02 22:18:03 +00001950 DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001951 DAG.getConstant(0xcccc, MVT::i16)));
Scott Michel266bc8f2007-12-04 22:23:35 +00001952
Dan Gohman475871a2008-07-27 21:46:04 +00001953 SDValue HHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001954 DAG.getCopyToReg(FSMBOp, HiProdReg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001955 DAG.getNode(SPUISD::MPYHH, MVT::v8i16, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001956
Dan Gohman475871a2008-07-27 21:46:04 +00001957 SDValue HHProd_v4i32 =
Scott Michel266bc8f2007-12-04 22:23:35 +00001958 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001959 DAG.getCopyFromReg(HHProd, HiProdReg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001960
1961 return DAG.getNode(SPUISD::SELB, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001962 DAG.getNode(SPUISD::MPY, MVT::v8i16, rA, rB),
1963 DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(),
1964 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32,
1965 HHProd_v4i32,
1966 DAG.getConstant(16, MVT::i16))),
1967 DAG.getCopyFromReg(FSMBOp, FSMBIreg, MVT::v4i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00001968 }
1969
1970 // This M00sE is N@stI! (apologies to Monty Python)
1971 //
1972 // SPU doesn't know how to do any 8-bit multiplication, so the solution
1973 // is to break it all apart, sign extend, and reassemble the various
1974 // intermediate products.
1975 case MVT::v16i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00001976 SDValue rA = Op.getOperand(0);
1977 SDValue rB = Op.getOperand(1);
1978 SDValue c8 = DAG.getConstant(8, MVT::i32);
1979 SDValue c16 = DAG.getConstant(16, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001980
Dan Gohman475871a2008-07-27 21:46:04 +00001981 SDValue LLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001982 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001983 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rA),
1984 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00001985
Dan Gohman475871a2008-07-27 21:46:04 +00001986 SDValue rALH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rA, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001987
Dan Gohman475871a2008-07-27 21:46:04 +00001988 SDValue rBLH = DAG.getNode(SPUISD::VEC_SRA, MVT::v8i16, rB, c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001989
Dan Gohman475871a2008-07-27 21:46:04 +00001990 SDValue LHProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00001991 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001992 DAG.getNode(SPUISD::MPY, MVT::v8i16, rALH, rBLH), c8);
Scott Michel266bc8f2007-12-04 22:23:35 +00001993
Dan Gohman475871a2008-07-27 21:46:04 +00001994 SDValue FSMBmask = DAG.getNode(SPUISD::SELECT_MASK, MVT::v8i16,
Scott Michel203b2d62008-04-30 00:30:08 +00001995 DAG.getConstant(0x2222, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001996
Dan Gohman475871a2008-07-27 21:46:04 +00001997 SDValue LoProdParts =
Scott Michela59d4692008-02-23 18:41:37 +00001998 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
1999 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2000 LLProd, LHProd, FSMBmask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002001
Dan Gohman475871a2008-07-27 21:46:04 +00002002 SDValue LoProdMask = DAG.getConstant(0xffff, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002003
Dan Gohman475871a2008-07-27 21:46:04 +00002004 SDValue LoProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002005 DAG.getNode(ISD::AND, MVT::v4i32,
Scott Michela59d4692008-02-23 18:41:37 +00002006 LoProdParts,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002007 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2008 LoProdMask, LoProdMask,
2009 LoProdMask, LoProdMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002010
Dan Gohman475871a2008-07-27 21:46:04 +00002011 SDValue rAH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002012 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002013 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rA), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002014
Dan Gohman475871a2008-07-27 21:46:04 +00002015 SDValue rBH =
Scott Michel266bc8f2007-12-04 22:23:35 +00002016 DAG.getNode(SPUISD::VEC_SRA, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002017 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, rB), c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002018
Dan Gohman475871a2008-07-27 21:46:04 +00002019 SDValue HLProd =
Scott Michel266bc8f2007-12-04 22:23:35 +00002020 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002021 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rAH),
2022 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, rBH));
Scott Michel266bc8f2007-12-04 22:23:35 +00002023
Dan Gohman475871a2008-07-27 21:46:04 +00002024 SDValue HHProd_1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002025 DAG.getNode(SPUISD::MPY, MVT::v8i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002026 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002027 DAG.getNode(SPUISD::VEC_SRA,
2028 MVT::v4i32, rAH, c8)),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002029 DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16,
Gabor Greif93c53e52008-08-31 15:37:04 +00002030 DAG.getNode(SPUISD::VEC_SRA,
2031 MVT::v4i32, rBH, c8)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002032
Dan Gohman475871a2008-07-27 21:46:04 +00002033 SDValue HHProd =
Scott Michela59d4692008-02-23 18:41:37 +00002034 DAG.getNode(SPUISD::SELB, MVT::v8i16,
2035 HLProd,
2036 DAG.getNode(SPUISD::VEC_SHL, MVT::v8i16, HHProd_1, c8),
2037 FSMBmask);
Scott Michel266bc8f2007-12-04 22:23:35 +00002038
Dan Gohman475871a2008-07-27 21:46:04 +00002039 SDValue HiProd =
Scott Michela59d4692008-02-23 18:41:37 +00002040 DAG.getNode(SPUISD::VEC_SHL, MVT::v4i32, HHProd, c16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002041
2042 return DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002043 DAG.getNode(ISD::OR, MVT::v4i32,
2044 LoProd, HiProd));
Scott Michel266bc8f2007-12-04 22:23:35 +00002045 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002046 }
2047
Dan Gohman475871a2008-07-27 21:46:04 +00002048 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002049}
2050
Dan Gohman475871a2008-07-27 21:46:04 +00002051static SDValue LowerFDIVf32(SDValue Op, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002052 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002053 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002054
Dan Gohman475871a2008-07-27 21:46:04 +00002055 SDValue A = Op.getOperand(0);
2056 SDValue B = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002057 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002058
2059 unsigned VRegBR, VRegC;
2060
2061 if (VT == MVT::f32) {
Chris Lattner84bc5422007-12-31 04:13:23 +00002062 VRegBR = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
2063 VRegC = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002064 } else {
Chris Lattner84bc5422007-12-31 04:13:23 +00002065 VRegBR = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
2066 VRegC = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002067 }
2068 // TODO: make sure we're feeding FPInterp the right arguments
2069 // Right now: fi B, frest(B)
2070
2071 // Computes BRcpl =
2072 // (Floating Interpolate (FP Reciprocal Estimate B))
Dan Gohman475871a2008-07-27 21:46:04 +00002073 SDValue BRcpl =
Scott Michel5af8f0e2008-07-16 17:17:29 +00002074 DAG.getCopyToReg(DAG.getEntryNode(), VRegBR,
2075 DAG.getNode(SPUISD::FPInterp, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002076 DAG.getNode(SPUISD::FPRecipEst, VT, B)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002077
Scott Michel266bc8f2007-12-04 22:23:35 +00002078 // Computes A * BRcpl and stores in a temporary register
Dan Gohman475871a2008-07-27 21:46:04 +00002079 SDValue AxBRcpl =
Scott Michel266bc8f2007-12-04 22:23:35 +00002080 DAG.getCopyToReg(BRcpl, VRegC,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002081 DAG.getNode(ISD::FMUL, VT, A,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002082 DAG.getCopyFromReg(BRcpl, VRegBR, VT)));
Scott Michel266bc8f2007-12-04 22:23:35 +00002083 // What's the Chain variable do? It's magic!
2084 // TODO: set Chain = Op(0).getEntryNode()
Scott Michel5af8f0e2008-07-16 17:17:29 +00002085
2086 return DAG.getNode(ISD::FADD, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002087 DAG.getCopyFromReg(AxBRcpl, VRegC, VT),
Scott Michel5af8f0e2008-07-16 17:17:29 +00002088 DAG.getNode(ISD::FMUL, VT,
2089 DAG.getCopyFromReg(AxBRcpl, VRegBR, VT),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002090 DAG.getNode(ISD::FSUB, VT, A,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002091 DAG.getNode(ISD::FMUL, VT, B,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002092 DAG.getCopyFromReg(AxBRcpl, VRegC, VT)))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002093}
2094
Dan Gohman475871a2008-07-27 21:46:04 +00002095static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002096 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002097 SDValue N = Op.getOperand(0);
2098 SDValue Elt = Op.getOperand(1);
2099 SDValue ShufMask[16];
Scott Michel266bc8f2007-12-04 22:23:35 +00002100 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt);
2101
2102 assert(C != 0 && "LowerEXTRACT_VECTOR_ELT expecting constant SDNode");
2103
2104 int EltNo = (int) C->getValue();
2105
2106 // sanity checks:
2107 if (VT == MVT::i8 && EltNo >= 16)
2108 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2109 else if (VT == MVT::i16 && EltNo >= 8)
2110 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2111 else if (VT == MVT::i32 && EltNo >= 4)
2112 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2113 else if (VT == MVT::i64 && EltNo >= 2)
2114 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2115
2116 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2117 // i32 and i64: Element 0 is the preferred slot
2118 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT, N);
2119 }
2120
2121 // Need to generate shuffle mask and extract:
Scott Michel0e5665b2007-12-19 21:17:42 +00002122 int prefslot_begin = -1, prefslot_end = -1;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002123 int elt_byte = EltNo * VT.getSizeInBits() / 8;
Scott Michel266bc8f2007-12-04 22:23:35 +00002124
Duncan Sands83ec4b62008-06-06 12:08:01 +00002125 switch (VT.getSimpleVT()) {
2126 default:
2127 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002128 case MVT::i8: {
2129 prefslot_begin = prefslot_end = 3;
2130 break;
2131 }
2132 case MVT::i16: {
2133 prefslot_begin = 2; prefslot_end = 3;
2134 break;
2135 }
2136 case MVT::i32: {
2137 prefslot_begin = 0; prefslot_end = 3;
2138 break;
2139 }
2140 case MVT::i64: {
2141 prefslot_begin = 0; prefslot_end = 7;
2142 break;
2143 }
2144 }
2145
Scott Michel0e5665b2007-12-19 21:17:42 +00002146 assert(prefslot_begin != -1 && prefslot_end != -1 &&
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002147 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
Scott Michel0e5665b2007-12-19 21:17:42 +00002148
Scott Michel266bc8f2007-12-04 22:23:35 +00002149 for (int i = 0; i < 16; ++i) {
2150 // zero fill uppper part of preferred slot, don't care about the
2151 // other slots:
2152 unsigned int mask_val;
2153
2154 if (i <= prefslot_end) {
2155 mask_val =
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002156 ((i < prefslot_begin)
2157 ? 0x80
2158 : elt_byte + (i - prefslot_begin));
Scott Michel266bc8f2007-12-04 22:23:35 +00002159
Scott Michel0e5665b2007-12-19 21:17:42 +00002160 ShufMask[i] = DAG.getConstant(mask_val, MVT::i8);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002161 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00002162 ShufMask[i] = ShufMask[i % (prefslot_end + 1)];
2163 }
2164
Dan Gohman475871a2008-07-27 21:46:04 +00002165 SDValue ShufMaskVec =
Scott Michel266bc8f2007-12-04 22:23:35 +00002166 DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002167 &ShufMask[0],
2168 sizeof(ShufMask) / sizeof(ShufMask[0]));
Scott Michel266bc8f2007-12-04 22:23:35 +00002169
2170 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002171 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2172 N, N, ShufMaskVec));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002173
Scott Michel266bc8f2007-12-04 22:23:35 +00002174}
2175
Dan Gohman475871a2008-07-27 21:46:04 +00002176static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2177 SDValue VecOp = Op.getOperand(0);
2178 SDValue ValOp = Op.getOperand(1);
2179 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002180 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002181
2182 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2183 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2184
Duncan Sands83ec4b62008-06-06 12:08:01 +00002185 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002186 // Use $2 because it's always 16-byte aligned and it's available:
Dan Gohman475871a2008-07-27 21:46:04 +00002187 SDValue PtrBase = DAG.getRegister(SPU::R2, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00002188
Dan Gohman475871a2008-07-27 21:46:04 +00002189 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002190 DAG.getNode(SPUISD::SHUFB, VT,
2191 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
2192 VecOp,
2193 DAG.getNode(SPUISD::INSERT_MASK, VT,
2194 DAG.getNode(ISD::ADD, PtrVT,
2195 PtrBase,
2196 DAG.getConstant(CN->getValue(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002197 PtrVT))));
Scott Michel266bc8f2007-12-04 22:23:35 +00002198
2199 return result;
2200}
2201
Dan Gohman475871a2008-07-27 21:46:04 +00002202static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002203{
Dan Gohman475871a2008-07-27 21:46:04 +00002204 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002205
2206 assert(Op.getValueType() == MVT::i8);
2207 switch (Opc) {
2208 default:
2209 assert(0 && "Unhandled i8 math operator");
2210 /*NOTREACHED*/
2211 break;
2212 case ISD::SUB: {
2213 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2214 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002215 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002216 N0 = (N0.getOpcode() != ISD::Constant
2217 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
2218 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
2219 N1 = (N1.getOpcode() != ISD::Constant
2220 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1)
2221 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002222 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002223 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002224 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002225 case ISD::ROTR:
2226 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002227 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002228 unsigned N1Opc;
2229 N0 = (N0.getOpcode() != ISD::Constant
2230 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
2231 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002232 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2233 ? ISD::ZERO_EXTEND
2234 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002235 N1 = (N1.getOpcode() != ISD::Constant
2236 ? DAG.getNode(N1Opc, MVT::i16, N1)
2237 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002238 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002239 DAG.getNode(ISD::OR, MVT::i16, N0,
2240 DAG.getNode(ISD::SHL, MVT::i16,
2241 N0, DAG.getConstant(8, MVT::i16)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002242 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002243 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2244 }
2245 case ISD::SRL:
2246 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002247 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002248 unsigned N1Opc;
2249 N0 = (N0.getOpcode() != ISD::Constant
2250 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
2251 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002252 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2253 ? ISD::ZERO_EXTEND
2254 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002255 N1 = (N1.getOpcode() != ISD::Constant
2256 ? DAG.getNode(N1Opc, MVT::i16, N1)
2257 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002258 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002259 DAG.getNode(Opc, MVT::i16, N0, N1));
2260 }
2261 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002262 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002263 unsigned N1Opc;
2264 N0 = (N0.getOpcode() != ISD::Constant
2265 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
2266 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Gabor Greif93c53e52008-08-31 15:37:04 +00002267 N1Opc = N1.getValueType().bitsLT(MVT::i16)
2268 ? ISD::SIGN_EXTEND
2269 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002270 N1 = (N1.getOpcode() != ISD::Constant
2271 ? DAG.getNode(N1Opc, MVT::i16, N1)
2272 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002273 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002274 DAG.getNode(Opc, MVT::i16, N0, N1));
2275 }
2276 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002277 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002278 unsigned N1Opc;
2279 N0 = (N0.getOpcode() != ISD::Constant
2280 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
2281 : DAG.getConstant(cast<ConstantSDNode>(N0)->getValue(), MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002282 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002283 N1 = (N1.getOpcode() != ISD::Constant
2284 ? DAG.getNode(N1Opc, MVT::i16, N1)
2285 : DAG.getConstant(cast<ConstantSDNode>(N1)->getValue(), MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002286 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002287 DAG.getNode(Opc, MVT::i16, N0, N1));
2288 break;
2289 }
2290 }
2291
Dan Gohman475871a2008-07-27 21:46:04 +00002292 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002293}
2294
Dan Gohman475871a2008-07-27 21:46:04 +00002295static SDValue LowerI64Math(SDValue Op, SelectionDAG &DAG, unsigned Opc)
Scott Michela59d4692008-02-23 18:41:37 +00002296{
Duncan Sands83ec4b62008-06-06 12:08:01 +00002297 MVT VT = Op.getValueType();
2298 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002299
Dan Gohman475871a2008-07-27 21:46:04 +00002300 SDValue Op0 = Op.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002301
2302 switch (Opc) {
2303 case ISD::ZERO_EXTEND:
2304 case ISD::SIGN_EXTEND:
2305 case ISD::ANY_EXTEND: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002306 MVT Op0VT = Op0.getValueType();
2307 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
Scott Michela59d4692008-02-23 18:41:37 +00002308
2309 assert(Op0VT == MVT::i32
2310 && "CellSPU: Zero/sign extending something other than i32");
Scott Michel203b2d62008-04-30 00:30:08 +00002311 DEBUG(cerr << "CellSPU: LowerI64Math custom lowering zero/sign/any extend\n");
Scott Michela59d4692008-02-23 18:41:37 +00002312
2313 unsigned NewOpc = (Opc == ISD::SIGN_EXTEND
2314 ? SPUISD::ROTBYTES_RIGHT_S
2315 : SPUISD::ROTQUAD_RZ_BYTES);
Dan Gohman475871a2008-07-27 21:46:04 +00002316 SDValue PromoteScalar =
Scott Michela59d4692008-02-23 18:41:37 +00002317 DAG.getNode(SPUISD::PROMOTE_SCALAR, Op0VecVT, Op0);
2318
2319 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2320 DAG.getNode(ISD::BIT_CONVERT, VecVT,
2321 DAG.getNode(NewOpc, Op0VecVT,
2322 PromoteScalar,
2323 DAG.getConstant(4, MVT::i32))));
2324 }
2325
Scott Michel8bf61e82008-06-02 22:18:03 +00002326 case ISD::ADD: {
2327 // Turn operands into vectors to satisfy type checking (shufb works on
2328 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002329 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002330 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002331 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002332 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002333 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002334
2335 // Create the shuffle mask for "rotating" the borrow up one register slot
2336 // once the borrow is generated.
2337 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2338 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2339 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2340 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2341
Dan Gohman475871a2008-07-27 21:46:04 +00002342 SDValue CarryGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002343 DAG.getNode(SPUISD::CARRY_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002344 SDValue ShiftedCarry =
Scott Michel8bf61e82008-06-02 22:18:03 +00002345 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2346 CarryGen, CarryGen,
2347 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2348 &ShufBytes[0], ShufBytes.size()));
2349
2350 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2351 DAG.getNode(SPUISD::ADD_EXTENDED, MVT::v2i64,
2352 Op0, Op1, ShiftedCarry));
2353 }
2354
2355 case ISD::SUB: {
2356 // Turn operands into vectors to satisfy type checking (shufb works on
2357 // vectors)
Dan Gohman475871a2008-07-27 21:46:04 +00002358 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002359 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002360 SDValue Op1 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002361 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(1));
Dan Gohman475871a2008-07-27 21:46:04 +00002362 SmallVector<SDValue, 16> ShufBytes;
Scott Michel8bf61e82008-06-02 22:18:03 +00002363
2364 // Create the shuffle mask for "rotating" the borrow up one register slot
2365 // once the borrow is generated.
2366 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2367 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2368 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2369 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2370
Dan Gohman475871a2008-07-27 21:46:04 +00002371 SDValue BorrowGen =
Scott Michel8bf61e82008-06-02 22:18:03 +00002372 DAG.getNode(SPUISD::BORROW_GENERATE, MVT::v2i64, Op0, Op1);
Dan Gohman475871a2008-07-27 21:46:04 +00002373 SDValue ShiftedBorrow =
Scott Michel8bf61e82008-06-02 22:18:03 +00002374 DAG.getNode(SPUISD::SHUFB, MVT::v2i64,
2375 BorrowGen, BorrowGen,
2376 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2377 &ShufBytes[0], ShufBytes.size()));
2378
2379 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2380 DAG.getNode(SPUISD::SUB_EXTENDED, MVT::v2i64,
2381 Op0, Op1, ShiftedBorrow));
2382 }
2383
Scott Michela59d4692008-02-23 18:41:37 +00002384 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002385 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002386 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002387 SDValue Op0Vec = DAG.getNode(SPUISD::PROMOTE_SCALAR, VecVT, Op0);
2388 SDValue MaskLower =
Scott Michela59d4692008-02-23 18:41:37 +00002389 DAG.getNode(SPUISD::SELB, VecVT,
2390 Op0Vec,
2391 DAG.getConstant(0, VecVT),
Scott Michel8bf61e82008-06-02 22:18:03 +00002392 DAG.getNode(SPUISD::SELECT_MASK, VecVT,
Scott Michela59d4692008-02-23 18:41:37 +00002393 DAG.getConstant(0xff00ULL, MVT::i16)));
Dan Gohman475871a2008-07-27 21:46:04 +00002394 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002395 DAG.getNode(ISD::SRL, ShiftAmtVT,
2396 ShiftAmt,
2397 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002398 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002399 DAG.getNode(ISD::AND, ShiftAmtVT,
2400 ShiftAmt,
2401 DAG.getConstant(7, ShiftAmtVT));
2402
2403 return DAG.getNode(SPUISD::EXTRACT_ELT0, VT,
2404 DAG.getNode(SPUISD::SHLQUAD_L_BITS, VecVT,
2405 DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT,
2406 MaskLower, ShiftAmtBytes),
2407 ShiftAmtBits));
2408 }
2409
2410 case ISD::SRL: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002411 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002412 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002413 MVT ShiftAmtVT = ShiftAmt.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002414 SDValue ShiftAmtBytes =
Scott Michela59d4692008-02-23 18:41:37 +00002415 DAG.getNode(ISD::SRL, ShiftAmtVT,
2416 ShiftAmt,
2417 DAG.getConstant(3, ShiftAmtVT));
Dan Gohman475871a2008-07-27 21:46:04 +00002418 SDValue ShiftAmtBits =
Scott Michela59d4692008-02-23 18:41:37 +00002419 DAG.getNode(ISD::AND, ShiftAmtVT,
2420 ShiftAmt,
2421 DAG.getConstant(7, ShiftAmtVT));
2422
2423 return DAG.getNode(SPUISD::ROTQUAD_RZ_BITS, VT,
2424 DAG.getNode(SPUISD::ROTQUAD_RZ_BYTES, VT,
2425 Op0, ShiftAmtBytes),
2426 ShiftAmtBits);
2427 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002428
2429 case ISD::SRA: {
2430 // Promote Op0 to vector
Dan Gohman475871a2008-07-27 21:46:04 +00002431 SDValue Op0 =
Scott Michel8bf61e82008-06-02 22:18:03 +00002432 DAG.getNode(SPUISD::PROMOTE_SCALAR, MVT::v2i64, Op.getOperand(0));
Dan Gohman475871a2008-07-27 21:46:04 +00002433 SDValue ShiftAmt = Op.getOperand(1);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002434 MVT ShiftVT = ShiftAmt.getValueType();
Scott Michel8bf61e82008-06-02 22:18:03 +00002435
2436 // Negate variable shift amounts
2437 if (!isa<ConstantSDNode>(ShiftAmt)) {
2438 ShiftAmt = DAG.getNode(ISD::SUB, ShiftVT,
2439 DAG.getConstant(0, ShiftVT), ShiftAmt);
2440 }
2441
Dan Gohman475871a2008-07-27 21:46:04 +00002442 SDValue UpperHalfSign =
Scott Michel8bf61e82008-06-02 22:18:03 +00002443 DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i32,
2444 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32,
2445 DAG.getNode(SPUISD::VEC_SRA, MVT::v2i64,
2446 Op0, DAG.getConstant(31, MVT::i32))));
Dan Gohman475871a2008-07-27 21:46:04 +00002447 SDValue UpperHalfSignMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002448 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64, UpperHalfSign);
Dan Gohman475871a2008-07-27 21:46:04 +00002449 SDValue UpperLowerMask =
Scott Michel8bf61e82008-06-02 22:18:03 +00002450 DAG.getNode(SPUISD::SELECT_MASK, MVT::v2i64,
2451 DAG.getConstant(0xff00, MVT::i16));
Dan Gohman475871a2008-07-27 21:46:04 +00002452 SDValue UpperLowerSelect =
Scott Michel8bf61e82008-06-02 22:18:03 +00002453 DAG.getNode(SPUISD::SELB, MVT::v2i64,
2454 UpperHalfSignMask, Op0, UpperLowerMask);
Dan Gohman475871a2008-07-27 21:46:04 +00002455 SDValue RotateLeftBytes =
Scott Michel8bf61e82008-06-02 22:18:03 +00002456 DAG.getNode(SPUISD::ROTBYTES_LEFT_BITS, MVT::v2i64,
2457 UpperLowerSelect, ShiftAmt);
Dan Gohman475871a2008-07-27 21:46:04 +00002458 SDValue RotateLeftBits =
Scott Michel8bf61e82008-06-02 22:18:03 +00002459 DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v2i64,
2460 RotateLeftBytes, ShiftAmt);
2461
2462 return DAG.getNode(SPUISD::EXTRACT_ELT0, MVT::i64,
2463 RotateLeftBits);
2464 }
Scott Michela59d4692008-02-23 18:41:37 +00002465 }
2466
Dan Gohman475871a2008-07-27 21:46:04 +00002467 return SDValue();
Scott Michela59d4692008-02-23 18:41:37 +00002468}
2469
Scott Michel266bc8f2007-12-04 22:23:35 +00002470//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002471static SDValue
2472LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2473 SDValue ConstVec;
2474 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002475 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002476
2477 ConstVec = Op.getOperand(0);
2478 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002479 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2480 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002481 ConstVec = ConstVec.getOperand(0);
2482 } else {
2483 ConstVec = Op.getOperand(1);
2484 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002485 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002486 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002487 }
2488 }
2489 }
2490
Gabor Greifba36cb52008-08-28 21:40:38 +00002491 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002492 uint64_t VectorBits[2];
2493 uint64_t UndefBits[2];
2494 uint64_t SplatBits, SplatUndef;
2495 int SplatSize;
2496
Gabor Greifba36cb52008-08-28 21:40:38 +00002497 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002498 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002499 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002500 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002501 SDValue tcVec[16];
2502 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002503 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2504
2505 // Turn the BUILD_VECTOR into a set of target constants:
2506 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002507 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002508
Gabor Greifba36cb52008-08-28 21:40:38 +00002509 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002510 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002511 }
2512 }
Nate Begeman24dc3462008-07-29 19:07:27 +00002513 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2514 // lowered. Return the operation, rather than a null SDValue.
2515 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002516}
2517
2518//! Lower i32 multiplication
Dan Gohman475871a2008-07-27 21:46:04 +00002519static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG, MVT VT,
Scott Michel266bc8f2007-12-04 22:23:35 +00002520 unsigned Opc) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002521 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002522 default:
2523 cerr << "CellSPU: Unknown LowerMUL value type, got "
Duncan Sands83ec4b62008-06-06 12:08:01 +00002524 << Op.getValueType().getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002525 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +00002526 abort();
2527 /*NOTREACHED*/
2528
2529 case MVT::i32: {
Dan Gohman475871a2008-07-27 21:46:04 +00002530 SDValue rA = Op.getOperand(0);
2531 SDValue rB = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002532
2533 return DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002534 DAG.getNode(ISD::ADD, MVT::i32,
2535 DAG.getNode(SPUISD::MPYH, MVT::i32, rA, rB),
2536 DAG.getNode(SPUISD::MPYH, MVT::i32, rB, rA)),
2537 DAG.getNode(SPUISD::MPYU, MVT::i32, rA, rB));
Scott Michel266bc8f2007-12-04 22:23:35 +00002538 }
2539 }
2540
Dan Gohman475871a2008-07-27 21:46:04 +00002541 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002542}
2543
2544//! Custom lowering for CTPOP (count population)
2545/*!
2546 Custom lowering code that counts the number ones in the input
2547 operand. SPU has such an instruction, but it counts the number of
2548 ones per byte, which then have to be accumulated.
2549*/
Dan Gohman475871a2008-07-27 21:46:04 +00002550static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002551 MVT VT = Op.getValueType();
2552 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002553
Duncan Sands83ec4b62008-06-06 12:08:01 +00002554 switch (VT.getSimpleVT()) {
2555 default:
2556 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002557 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002558 SDValue N = Op.getOperand(0);
2559 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002560
Dan Gohman475871a2008-07-27 21:46:04 +00002561 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2562 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002563
2564 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2565 }
2566
2567 case MVT::i16: {
2568 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002569 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002570
Chris Lattner84bc5422007-12-31 04:13:23 +00002571 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002572
Dan Gohman475871a2008-07-27 21:46:04 +00002573 SDValue N = Op.getOperand(0);
2574 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2575 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
2576 SDValue Shift1 = DAG.getConstant(8, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002577
Dan Gohman475871a2008-07-27 21:46:04 +00002578 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2579 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002580
2581 // CNTB_result becomes the chain to which all of the virtual registers
2582 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002583 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002584 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002585
Dan Gohman475871a2008-07-27 21:46:04 +00002586 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002587 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2588
Dan Gohman475871a2008-07-27 21:46:04 +00002589 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002590
2591 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002592 DAG.getNode(ISD::ADD, MVT::i16,
2593 DAG.getNode(ISD::SRL, MVT::i16,
2594 Tmp1, Shift1),
2595 Tmp1),
2596 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002597 }
2598
2599 case MVT::i32: {
2600 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002601 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002602
Chris Lattner84bc5422007-12-31 04:13:23 +00002603 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2604 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002605
Dan Gohman475871a2008-07-27 21:46:04 +00002606 SDValue N = Op.getOperand(0);
2607 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2608 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2609 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2610 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002611
Dan Gohman475871a2008-07-27 21:46:04 +00002612 SDValue Promote = DAG.getNode(SPUISD::PROMOTE_SCALAR, vecVT, N, N);
2613 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002614
2615 // CNTB_result becomes the chain to which all of the virtual registers
2616 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002617 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002618 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002619
Dan Gohman475871a2008-07-27 21:46:04 +00002620 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002621 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2622
Dan Gohman475871a2008-07-27 21:46:04 +00002623 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002624 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002625 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002626
Dan Gohman475871a2008-07-27 21:46:04 +00002627 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002628 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002629 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002630
Dan Gohman475871a2008-07-27 21:46:04 +00002631 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002632 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2633
Dan Gohman475871a2008-07-27 21:46:04 +00002634 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002635 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002636 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2637 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002638 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002639 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002640 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002641
2642 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2643 }
2644
2645 case MVT::i64:
2646 break;
2647 }
2648
Dan Gohman475871a2008-07-27 21:46:04 +00002649 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002650}
2651
2652/// LowerOperation - Provide custom lowering hooks for some operations.
2653///
Dan Gohman475871a2008-07-27 21:46:04 +00002654SDValue
2655SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002656{
Scott Michela59d4692008-02-23 18:41:37 +00002657 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002658 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002659
2660 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002661 default: {
2662 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002663 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002664 cerr << "*Op.getNode():\n";
2665 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002666 abort();
2667 }
2668 case ISD::LOAD:
2669 case ISD::SEXTLOAD:
2670 case ISD::ZEXTLOAD:
2671 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2672 case ISD::STORE:
2673 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2674 case ISD::ConstantPool:
2675 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2676 case ISD::GlobalAddress:
2677 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2678 case ISD::JumpTable:
2679 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2680 case ISD::Constant:
2681 return LowerConstant(Op, DAG);
2682 case ISD::ConstantFP:
2683 return LowerConstantFP(Op, DAG);
Scott Michel58c58182008-01-17 20:38:41 +00002684 case ISD::BRCOND:
2685 return LowerBRCOND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002686 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002687 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002688 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002689 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002690 case ISD::RET:
2691 return LowerRET(Op, DAG, getTargetMachine());
2692
Scott Michela59d4692008-02-23 18:41:37 +00002693
2694 // i8, i64 math ops:
2695 case ISD::ZERO_EXTEND:
2696 case ISD::SIGN_EXTEND:
2697 case ISD::ANY_EXTEND:
Scott Michel8bf61e82008-06-02 22:18:03 +00002698 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002699 case ISD::SUB:
2700 case ISD::ROTR:
2701 case ISD::ROTL:
2702 case ISD::SRL:
2703 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002704 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002705 if (VT == MVT::i8)
2706 return LowerI8Math(Op, DAG, Opc);
2707 else if (VT == MVT::i64)
2708 return LowerI64Math(Op, DAG, Opc);
2709 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002710 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002711
2712 // Vector-related lowering.
2713 case ISD::BUILD_VECTOR:
2714 return LowerBUILD_VECTOR(Op, DAG);
2715 case ISD::SCALAR_TO_VECTOR:
2716 return LowerSCALAR_TO_VECTOR(Op, DAG);
2717 case ISD::VECTOR_SHUFFLE:
2718 return LowerVECTOR_SHUFFLE(Op, DAG);
2719 case ISD::EXTRACT_VECTOR_ELT:
2720 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2721 case ISD::INSERT_VECTOR_ELT:
2722 return LowerINSERT_VECTOR_ELT(Op, DAG);
2723
2724 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2725 case ISD::AND:
2726 case ISD::OR:
2727 case ISD::XOR:
2728 return LowerByteImmed(Op, DAG);
2729
2730 // Vector and i8 multiply:
2731 case ISD::MUL:
Duncan Sands83ec4b62008-06-06 12:08:01 +00002732 if (VT.isVector())
Scott Michel266bc8f2007-12-04 22:23:35 +00002733 return LowerVectorMUL(Op, DAG);
Scott Michela59d4692008-02-23 18:41:37 +00002734 else if (VT == MVT::i8)
2735 return LowerI8Math(Op, DAG, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002736 else
Scott Michela59d4692008-02-23 18:41:37 +00002737 return LowerMUL(Op, DAG, VT, Opc);
Scott Michel266bc8f2007-12-04 22:23:35 +00002738
2739 case ISD::FDIV:
Scott Michela59d4692008-02-23 18:41:37 +00002740 if (VT == MVT::f32 || VT == MVT::v4f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00002741 return LowerFDIVf32(Op, DAG);
2742// else if (Op.getValueType() == MVT::f64)
2743// return LowerFDIVf64(Op, DAG);
2744 else
2745 assert(0 && "Calling FDIV on unsupported MVT");
2746
2747 case ISD::CTPOP:
2748 return LowerCTPOP(Op, DAG);
2749 }
2750
Dan Gohman475871a2008-07-27 21:46:04 +00002751 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002752}
2753
2754//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002755// Target Optimization Hooks
2756//===----------------------------------------------------------------------===//
2757
Dan Gohman475871a2008-07-27 21:46:04 +00002758SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002759SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2760{
2761#if 0
2762 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002763#endif
2764 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002765 SelectionDAG &DAG = DCI.DAG;
Dan Gohman475871a2008-07-27 21:46:04 +00002766 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2767 SDValue Result; // Initially, NULL result
Scott Michel266bc8f2007-12-04 22:23:35 +00002768
2769 switch (N->getOpcode()) {
2770 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002771 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002772 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002773
Scott Michel8bf61e82008-06-02 22:18:03 +00002774 if (isa<ConstantSDNode>(Op1) && Op0.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002775 SDValue Op01 = Op0.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002776 if (Op01.getOpcode() == ISD::Constant
2777 || Op01.getOpcode() == ISD::TargetConstant) {
2778 // (add <const>, (SPUindirect <arg>, <const>)) ->
2779 // (SPUindirect <arg>, <const + const>)
2780 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
2781 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
Dan Gohman475871a2008-07-27 21:46:04 +00002782 SDValue combinedConst =
Scott Michel053c1da2008-01-29 02:16:57 +00002783 DAG.getConstant(CN0->getValue() + CN1->getValue(),
2784 Op0.getValueType());
2785
2786 DEBUG(cerr << "Replace: (add " << CN0->getValue() << ", "
2787 << "(SPUindirect <arg>, " << CN1->getValue() << "))\n");
2788 DEBUG(cerr << "With: (SPUindirect <arg>, "
2789 << CN0->getValue() + CN1->getValue() << ")\n");
2790 return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
2791 Op0.getOperand(0), combinedConst);
2792 }
Scott Michel8bf61e82008-06-02 22:18:03 +00002793 } else if (isa<ConstantSDNode>(Op0)
Scott Michel053c1da2008-01-29 02:16:57 +00002794 && Op1.getOpcode() == SPUISD::IndirectAddr) {
Dan Gohman475871a2008-07-27 21:46:04 +00002795 SDValue Op11 = Op1.getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002796 if (Op11.getOpcode() == ISD::Constant
2797 || Op11.getOpcode() == ISD::TargetConstant) {
2798 // (add (SPUindirect <arg>, <const>), <const>) ->
2799 // (SPUindirect <arg>, <const + const>)
2800 ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
2801 ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
Dan Gohman475871a2008-07-27 21:46:04 +00002802 SDValue combinedConst =
Scott Michel053c1da2008-01-29 02:16:57 +00002803 DAG.getConstant(CN0->getValue() + CN1->getValue(),
2804 Op0.getValueType());
2805
2806 DEBUG(cerr << "Replace: (add " << CN0->getValue() << ", "
2807 << "(SPUindirect <arg>, " << CN1->getValue() << "))\n");
2808 DEBUG(cerr << "With: (SPUindirect <arg>, "
2809 << CN0->getValue() + CN1->getValue() << ")\n");
2810
2811 return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
2812 Op1.getOperand(0), combinedConst);
2813 }
2814 }
Scott Michela59d4692008-02-23 18:41:37 +00002815 break;
2816 }
2817 case ISD::SIGN_EXTEND:
2818 case ISD::ZERO_EXTEND:
2819 case ISD::ANY_EXTEND: {
2820 if (Op0.getOpcode() == SPUISD::EXTRACT_ELT0 &&
2821 N->getValueType(0) == Op0.getValueType()) {
2822 // (any_extend (SPUextract_elt0 <arg>)) ->
2823 // (SPUextract_elt0 <arg>)
2824 // Types must match, however...
2825 DEBUG(cerr << "Replace: ");
2826 DEBUG(N->dump(&DAG));
2827 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002828 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002829 DEBUG(cerr << "\n");
2830
2831 return Op0;
2832 }
2833 break;
2834 }
2835 case SPUISD::IndirectAddr: {
2836 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2837 ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
2838 if (CN->getValue() == 0) {
2839 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2840 // (SPUaform <addr>, 0)
2841
2842 DEBUG(cerr << "Replace: ");
2843 DEBUG(N->dump(&DAG));
2844 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002845 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002846 DEBUG(cerr << "\n");
2847
2848 return Op0;
2849 }
2850 }
2851 break;
2852 }
2853 case SPUISD::SHLQUAD_L_BITS:
2854 case SPUISD::SHLQUAD_L_BYTES:
2855 case SPUISD::VEC_SHL:
2856 case SPUISD::VEC_SRL:
2857 case SPUISD::VEC_SRA:
2858 case SPUISD::ROTQUAD_RZ_BYTES:
2859 case SPUISD::ROTQUAD_RZ_BITS: {
Dan Gohman475871a2008-07-27 21:46:04 +00002860 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002861
2862 if (isa<ConstantSDNode>(Op1)) {
2863 // Kill degenerate vector shifts:
2864 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
2865
2866 if (CN->getValue() == 0) {
2867 Result = Op0;
2868 }
2869 }
2870 break;
2871 }
2872 case SPUISD::PROMOTE_SCALAR: {
2873 switch (Op0.getOpcode()) {
2874 default:
2875 break;
2876 case ISD::ANY_EXTEND:
2877 case ISD::ZERO_EXTEND:
2878 case ISD::SIGN_EXTEND: {
2879 // (SPUpromote_scalar (any|sign|zero_extend (SPUextract_elt0 <arg>))) ->
2880 // <arg>
2881 // but only if the SPUpromote_scalar and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002882 SDValue Op00 = Op0.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002883 if (Op00.getOpcode() == SPUISD::EXTRACT_ELT0) {
Dan Gohman475871a2008-07-27 21:46:04 +00002884 SDValue Op000 = Op00.getOperand(0);
Scott Michela59d4692008-02-23 18:41:37 +00002885 if (Op000.getValueType() == N->getValueType(0)) {
2886 Result = Op000;
2887 }
2888 }
2889 break;
2890 }
2891 case SPUISD::EXTRACT_ELT0: {
2892 // (SPUpromote_scalar (SPUextract_elt0 <arg>)) ->
2893 // <arg>
2894 Result = Op0.getOperand(0);
2895 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002896 }
Scott Michela59d4692008-02-23 18:41:37 +00002897 }
2898 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002899 }
2900 }
Scott Michel58c58182008-01-17 20:38:41 +00002901 // Otherwise, return unchanged.
Scott Michel203b2d62008-04-30 00:30:08 +00002902#if 1
Gabor Greifba36cb52008-08-28 21:40:38 +00002903 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00002904 DEBUG(cerr << "\nReplace.SPU: ");
2905 DEBUG(N->dump(&DAG));
2906 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002907 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002908 DEBUG(cerr << "\n");
2909 }
2910#endif
2911
2912 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002913}
2914
2915//===----------------------------------------------------------------------===//
2916// Inline Assembly Support
2917//===----------------------------------------------------------------------===//
2918
2919/// getConstraintType - Given a constraint letter, return the type of
2920/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002921SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002922SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2923 if (ConstraintLetter.size() == 1) {
2924 switch (ConstraintLetter[0]) {
2925 default: break;
2926 case 'b':
2927 case 'r':
2928 case 'f':
2929 case 'v':
2930 case 'y':
2931 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002932 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002933 }
2934 return TargetLowering::getConstraintType(ConstraintLetter);
2935}
2936
Scott Michel5af8f0e2008-07-16 17:17:29 +00002937std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002938SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002939 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002940{
2941 if (Constraint.size() == 1) {
2942 // GCC RS6000 Constraint Letters
2943 switch (Constraint[0]) {
2944 case 'b': // R1-R31
2945 case 'r': // R0-R31
2946 if (VT == MVT::i64)
2947 return std::make_pair(0U, SPU::R64CRegisterClass);
2948 return std::make_pair(0U, SPU::R32CRegisterClass);
2949 case 'f':
2950 if (VT == MVT::f32)
2951 return std::make_pair(0U, SPU::R32FPRegisterClass);
2952 else if (VT == MVT::f64)
2953 return std::make_pair(0U, SPU::R64FPRegisterClass);
2954 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002955 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00002956 return std::make_pair(0U, SPU::GPRCRegisterClass);
2957 }
2958 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002959
Scott Michel266bc8f2007-12-04 22:23:35 +00002960 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
2961}
2962
Scott Michela59d4692008-02-23 18:41:37 +00002963//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00002964void
Dan Gohman475871a2008-07-27 21:46:04 +00002965SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00002966 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00002967 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00002968 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002969 const SelectionDAG &DAG,
2970 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00002971#if 0
Scott Michela59d4692008-02-23 18:41:37 +00002972 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
Scott Michel203b2d62008-04-30 00:30:08 +00002973#endif
Scott Michela59d4692008-02-23 18:41:37 +00002974
2975 switch (Op.getOpcode()) {
2976 default:
2977 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
2978 break;
2979
2980#if 0
2981 case CALL:
2982 case SHUFB:
2983 case INSERT_MASK:
2984 case CNTB:
2985#endif
2986
2987 case SPUISD::PROMOTE_SCALAR: {
Dan Gohman475871a2008-07-27 21:46:04 +00002988 SDValue Op0 = Op.getOperand(0);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002989 MVT Op0VT = Op0.getValueType();
2990 unsigned Op0VTBits = Op0VT.getSizeInBits();
2991 uint64_t InMask = Op0VT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00002992 KnownZero |= APInt(Op0VTBits, ~InMask, false);
2993 KnownOne |= APInt(Op0VTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00002994 break;
2995 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00002996
Scott Michela59d4692008-02-23 18:41:37 +00002997 case SPUISD::LDRESULT:
2998 case SPUISD::EXTRACT_ELT0:
2999 case SPUISD::EXTRACT_ELT0_CHAINED: {
Duncan Sands83ec4b62008-06-06 12:08:01 +00003000 MVT OpVT = Op.getValueType();
3001 unsigned OpVTBits = OpVT.getSizeInBits();
3002 uint64_t InMask = OpVT.getIntegerVTBitMask();
Scott Michel203b2d62008-04-30 00:30:08 +00003003 KnownZero |= APInt(OpVTBits, ~InMask, false);
3004 KnownOne |= APInt(OpVTBits, InMask, false);
Scott Michela59d4692008-02-23 18:41:37 +00003005 break;
3006 }
3007
3008#if 0
3009 case EXTRACT_I1_ZEXT:
3010 case EXTRACT_I1_SEXT:
3011 case EXTRACT_I8_ZEXT:
3012 case EXTRACT_I8_SEXT:
3013 case MPY:
3014 case MPYU:
3015 case MPYH:
3016 case MPYHH:
Scott Michel203b2d62008-04-30 00:30:08 +00003017 case SPUISD::SHLQUAD_L_BITS:
3018 case SPUISD::SHLQUAD_L_BYTES:
3019 case SPUISD::VEC_SHL:
3020 case SPUISD::VEC_SRL:
3021 case SPUISD::VEC_SRA:
3022 case SPUISD::VEC_ROTL:
3023 case SPUISD::VEC_ROTR:
3024 case SPUISD::ROTQUAD_RZ_BYTES:
3025 case SPUISD::ROTQUAD_RZ_BITS:
3026 case SPUISD::ROTBYTES_RIGHT_S:
3027 case SPUISD::ROTBYTES_LEFT:
3028 case SPUISD::ROTBYTES_LEFT_CHAINED:
Scott Michel8bf61e82008-06-02 22:18:03 +00003029 case SPUISD::SELECT_MASK:
3030 case SPUISD::SELB:
3031 case SPUISD::FPInterp:
3032 case SPUISD::FPRecipEst:
3033 case SPUISD::SEXT32TO64:
Scott Michela59d4692008-02-23 18:41:37 +00003034#endif
3035 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003036}
3037
Scott Michel203b2d62008-04-30 00:30:08 +00003038// LowerAsmOperandForConstraint
3039void
Dan Gohman475871a2008-07-27 21:46:04 +00003040SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003041 char ConstraintLetter,
Dan Gohman475871a2008-07-27 21:46:04 +00003042 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003043 SelectionDAG &DAG) const {
3044 // Default, for the time being, to the base class handler
3045 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, Ops, DAG);
3046}
3047
Scott Michel266bc8f2007-12-04 22:23:35 +00003048/// isLegalAddressImmediate - Return true if the integer value can be used
3049/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003050bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3051 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003052 // SPU's addresses are 256K:
3053 return (V > -(1 << 18) && V < (1 << 18) - 1);
3054}
3055
3056bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003057 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003058}