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