blob: 0718330d422dae67d46ad38d4a260756aa9854ab [file] [log] [blame]
Scott Michel266bc8f2007-12-04 22:23:35 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel266bc8f2007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SPUTargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPURegisterNames.h"
15#include "SPUISelLowering.h"
16#include "SPUTargetMachine.h"
Scott Michel203b2d62008-04-30 00:30:08 +000017#include "SPUFrameInfo.h"
Scott Michelf0569be2008-12-27 04:51:36 +000018#include "llvm/ADT/APInt.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000019#include "llvm/ADT/VectorExtras.h"
Scott Michelc9c8b2a2009-01-26 03:31:40 +000020#include "llvm/CallingConv.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000021#include "llvm/CodeGen/CallingConvLower.h"
22#include "llvm/CodeGen/MachineFrameInfo.h"
23#include "llvm/CodeGen/MachineFunction.h"
24#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner84bc5422007-12-31 04:13:23 +000025#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000026#include "llvm/CodeGen/SelectionDAG.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000027#include "llvm/Constants.h"
28#include "llvm/Function.h"
29#include "llvm/Intrinsics.h"
30#include "llvm/Support/Debug.h"
31#include "llvm/Support/MathExtras.h"
32#include "llvm/Target/TargetOptions.h"
33
34#include <map>
35
36using namespace llvm;
37
38// Used in getTargetNodeName() below
39namespace {
40 std::map<unsigned, const char *> node_names;
41
Duncan Sands83ec4b62008-06-06 12:08:01 +000042 //! MVT mapping to useful data for Cell SPU
Scott Michel266bc8f2007-12-04 22:23:35 +000043 struct valtype_map_s {
Scott Michel7a1c9e92008-11-22 23:50:42 +000044 const MVT valtype;
45 const int prefslot_byte;
Scott Michel266bc8f2007-12-04 22:23:35 +000046 };
Scott Michel5af8f0e2008-07-16 17:17:29 +000047
Scott Michel266bc8f2007-12-04 22:23:35 +000048 const valtype_map_s valtype_map[] = {
49 { MVT::i1, 3 },
50 { MVT::i8, 3 },
51 { MVT::i16, 2 },
52 { MVT::i32, 0 },
53 { MVT::f32, 0 },
54 { MVT::i64, 0 },
55 { MVT::f64, 0 },
56 { MVT::i128, 0 }
57 };
58
59 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
60
Duncan Sands83ec4b62008-06-06 12:08:01 +000061 const valtype_map_s *getValueTypeMapEntry(MVT VT) {
Scott Michel266bc8f2007-12-04 22:23:35 +000062 const valtype_map_s *retval = 0;
63
64 for (size_t i = 0; i < n_valtype_map; ++i) {
65 if (valtype_map[i].valtype == VT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +000066 retval = valtype_map + i;
67 break;
Scott Michel266bc8f2007-12-04 22:23:35 +000068 }
69 }
70
71#ifndef NDEBUG
72 if (retval == 0) {
73 cerr << "getValueTypeMapEntry returns NULL for "
Duncan Sands83ec4b62008-06-06 12:08:01 +000074 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +000075 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +000076 abort();
77 }
78#endif
79
80 return retval;
81 }
Scott Michel94bd57e2009-01-15 04:41:47 +000082
Scott Michelc9c8b2a2009-01-26 03:31:40 +000083 //! Expand a library call into an actual call DAG node
84 /*!
85 \note
86 This code is taken from SelectionDAGLegalize, since it is not exposed as
87 part of the LLVM SelectionDAG API.
88 */
89
90 SDValue
91 ExpandLibCall(RTLIB::Libcall LC, SDValue Op, SelectionDAG &DAG,
92 bool isSigned, SDValue &Hi, SPUTargetLowering &TLI) {
93 // The input chain to this libcall is the entry node of the function.
94 // Legalizing the call will automatically add the previous call to the
95 // dependence.
96 SDValue InChain = DAG.getEntryNode();
97
98 TargetLowering::ArgListTy Args;
99 TargetLowering::ArgListEntry Entry;
100 for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
101 MVT ArgVT = Op.getOperand(i).getValueType();
102 const Type *ArgTy = ArgVT.getTypeForMVT();
103 Entry.Node = Op.getOperand(i);
104 Entry.Ty = ArgTy;
105 Entry.isSExt = isSigned;
106 Entry.isZExt = !isSigned;
107 Args.push_back(Entry);
108 }
109 SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC),
110 TLI.getPointerTy());
111
112 // Splice the libcall in wherever FindInputOutputChains tells us to.
113 const Type *RetTy = Op.getNode()->getValueType(0).getTypeForMVT();
114 std::pair<SDValue, SDValue> CallInfo =
115 TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false,
Dale Johannesen7d2ad622009-01-30 23:10:59 +0000116 CallingConv::C, false, Callee, Args, DAG,
117 Op.getNode()->getDebugLoc());
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000118
119 return CallInfo.first;
120 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000121}
122
123SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
124 : TargetLowering(TM),
125 SPUTM(TM)
126{
127 // Fold away setcc operations if possible.
128 setPow2DivIsCheap();
129
130 // Use _setjmp/_longjmp instead of setjmp/longjmp.
131 setUseUnderscoreSetJmp(true);
132 setUseUnderscoreLongJmp(true);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000133
Scott Micheld1e8d9c2009-01-21 04:58:48 +0000134 // Set RTLIB libcall names as used by SPU:
135 setLibcallName(RTLIB::DIV_F64, "__fast_divdf3");
136
Scott Michel266bc8f2007-12-04 22:23:35 +0000137 // Set up the SPU's register classes:
Scott Michel504c3692007-12-17 22:32:34 +0000138 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
139 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
140 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
141 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
142 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
143 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
Scott Michel266bc8f2007-12-04 22:23:35 +0000144 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000145
Scott Michel266bc8f2007-12-04 22:23:35 +0000146 // SPU has no sign or zero extended loads for i1, i8, i16:
Evan Cheng03294662008-10-14 21:26:46 +0000147 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
148 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
149 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +0000150
Scott Michelf0569be2008-12-27 04:51:36 +0000151 setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
152 setLoadExtAction(ISD::EXTLOAD, MVT::f64, Expand);
Scott Michelb30e8f62008-12-02 19:53:53 +0000153
Scott Michel266bc8f2007-12-04 22:23:35 +0000154 // SPU constant load actions are custom lowered:
Nate Begemanccef5802008-02-14 18:43:04 +0000155 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000156 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
157
158 // SPU's loads and stores have to be custom lowered:
Scott Micheldd950092009-01-06 03:36:14 +0000159 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::i128;
Scott Michel266bc8f2007-12-04 22:23:35 +0000160 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000161 MVT VT = (MVT::SimpleValueType)sctype;
162
Scott Michelf0569be2008-12-27 04:51:36 +0000163 setOperationAction(ISD::LOAD, VT, Custom);
164 setOperationAction(ISD::STORE, VT, Custom);
165 setLoadExtAction(ISD::EXTLOAD, VT, Custom);
166 setLoadExtAction(ISD::ZEXTLOAD, VT, Custom);
167 setLoadExtAction(ISD::SEXTLOAD, VT, Custom);
168
169 for (unsigned stype = sctype - 1; stype >= (unsigned) MVT::i8; --stype) {
170 MVT StoreVT = (MVT::SimpleValueType) stype;
171 setTruncStoreAction(VT, StoreVT, Expand);
172 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000173 }
174
Scott Michelf0569be2008-12-27 04:51:36 +0000175 for (unsigned sctype = (unsigned) MVT::f32; sctype < (unsigned) MVT::f64;
176 ++sctype) {
177 MVT VT = (MVT::SimpleValueType) sctype;
178
179 setOperationAction(ISD::LOAD, VT, Custom);
180 setOperationAction(ISD::STORE, VT, Custom);
181
182 for (unsigned stype = sctype - 1; stype >= (unsigned) MVT::f32; --stype) {
183 MVT StoreVT = (MVT::SimpleValueType) stype;
184 setTruncStoreAction(VT, StoreVT, Expand);
185 }
186 }
187
Scott Michel266bc8f2007-12-04 22:23:35 +0000188 // Expand the jumptable branches
189 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
190 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel7a1c9e92008-11-22 23:50:42 +0000191
192 // Custom lower SELECT_CC for most cases, but expand by default
Scott Michel5af8f0e2008-07-16 17:17:29 +0000193 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Scott Michel7a1c9e92008-11-22 23:50:42 +0000194 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
195 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
196 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
197 setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000198
199 // SPU has no intrinsics for these particular operations:
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000200 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
201
Scott Michelf0569be2008-12-27 04:51:36 +0000202 // SPU has no SREM/UREM instructions
Scott Michel266bc8f2007-12-04 22:23:35 +0000203 setOperationAction(ISD::SREM, MVT::i32, Expand);
204 setOperationAction(ISD::UREM, MVT::i32, Expand);
205 setOperationAction(ISD::SREM, MVT::i64, Expand);
206 setOperationAction(ISD::UREM, MVT::i64, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000207
Scott Michel266bc8f2007-12-04 22:23:35 +0000208 // We don't support sin/cos/sqrt/fmod
209 setOperationAction(ISD::FSIN , MVT::f64, Expand);
210 setOperationAction(ISD::FCOS , MVT::f64, Expand);
211 setOperationAction(ISD::FREM , MVT::f64, Expand);
212 setOperationAction(ISD::FSIN , MVT::f32, Expand);
213 setOperationAction(ISD::FCOS , MVT::f32, Expand);
214 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000215
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000216 // Expand fsqrt to the appropriate libcall (NOTE: should use h/w fsqrt
217 // for f32!)
Scott Michel266bc8f2007-12-04 22:23:35 +0000218 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
219 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000220
Scott Michel266bc8f2007-12-04 22:23:35 +0000221 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
222 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
223
224 // SPU can do rotate right and left, so legalize it... but customize for i8
225 // because instructions don't exist.
Bill Wendling9440e352008-08-31 02:59:23 +0000226
227 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
228 // .td files.
229 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
230 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
231 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
232
Scott Michel266bc8f2007-12-04 22:23:35 +0000233 setOperationAction(ISD::ROTL, MVT::i32, Legal);
234 setOperationAction(ISD::ROTL, MVT::i16, Legal);
235 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Micheldc91bea2008-11-20 16:36:33 +0000236
Scott Michel266bc8f2007-12-04 22:23:35 +0000237 // SPU has no native version of shift left/right for i8
238 setOperationAction(ISD::SHL, MVT::i8, Custom);
239 setOperationAction(ISD::SRL, MVT::i8, Custom);
240 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel9c0c6b22008-11-21 02:56:16 +0000241
Scott Michel02d711b2008-12-30 23:28:25 +0000242 // Make these operations legal and handle them during instruction selection:
243 setOperationAction(ISD::SHL, MVT::i64, Legal);
244 setOperationAction(ISD::SRL, MVT::i64, Legal);
245 setOperationAction(ISD::SRA, MVT::i64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000246
Scott Michel5af8f0e2008-07-16 17:17:29 +0000247 // Custom lower i8, i32 and i64 multiplications
248 setOperationAction(ISD::MUL, MVT::i8, Custom);
Scott Michel1df30c42008-12-29 03:23:36 +0000249 setOperationAction(ISD::MUL, MVT::i32, Legal);
Scott Michel94bd57e2009-01-15 04:41:47 +0000250 setOperationAction(ISD::MUL, MVT::i64, Legal);
Scott Michel9c0c6b22008-11-21 02:56:16 +0000251
Scott Michel8bf61e82008-06-02 22:18:03 +0000252 // Need to custom handle (some) common i8, i64 math ops
Scott Michel02d711b2008-12-30 23:28:25 +0000253 setOperationAction(ISD::ADD, MVT::i8, Custom);
Scott Michel94bd57e2009-01-15 04:41:47 +0000254 setOperationAction(ISD::ADD, MVT::i64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000255 setOperationAction(ISD::SUB, MVT::i8, Custom);
Scott Michel94bd57e2009-01-15 04:41:47 +0000256 setOperationAction(ISD::SUB, MVT::i64, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000257
Scott Michel266bc8f2007-12-04 22:23:35 +0000258 // SPU does not have BSWAP. It does have i32 support CTLZ.
259 // CTPOP has to be custom lowered.
260 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
261 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
262
263 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
264 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
265 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
266 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
267
268 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
269 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
270
271 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000272
Scott Michel8bf61e82008-06-02 22:18:03 +0000273 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000274 // select ought to work:
Scott Michel78c47fa2008-03-10 16:58:52 +0000275 setOperationAction(ISD::SELECT, MVT::i8, Legal);
Scott Michelad2715e2008-03-05 23:02:02 +0000276 setOperationAction(ISD::SELECT, MVT::i16, Legal);
277 setOperationAction(ISD::SELECT, MVT::i32, Legal);
Scott Michelf0569be2008-12-27 04:51:36 +0000278 setOperationAction(ISD::SELECT, MVT::i64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000279
Scott Michel78c47fa2008-03-10 16:58:52 +0000280 setOperationAction(ISD::SETCC, MVT::i8, Legal);
281 setOperationAction(ISD::SETCC, MVT::i16, Legal);
Scott Michel1df30c42008-12-29 03:23:36 +0000282 setOperationAction(ISD::SETCC, MVT::i32, Legal);
283 setOperationAction(ISD::SETCC, MVT::i64, Legal);
Scott Micheld1e8d9c2009-01-21 04:58:48 +0000284 setOperationAction(ISD::SETCC, MVT::f64, Custom);
Scott Michelad2715e2008-03-05 23:02:02 +0000285
Scott Michelf0569be2008-12-27 04:51:36 +0000286 // Custom lower i128 -> i64 truncates
Scott Michelb30e8f62008-12-02 19:53:53 +0000287 setOperationAction(ISD::TRUNCATE, MVT::i64, Custom);
288
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000289 // SPU has a legal FP -> signed INT instruction for f32, but for f64, need
290 // to expand to a libcall, hence the custom lowering:
291 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
292 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000293
294 // FDIV on SPU requires custom lowering
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000295 setOperationAction(ISD::FDIV, MVT::f64, Expand); // to libcall
Scott Michel266bc8f2007-12-04 22:23:35 +0000296
Scott Michel9de57a92009-01-26 22:33:37 +0000297 // SPU has [U|S]INT_TO_FP for f32->i32, but not for f64->i32, f64->i64:
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000298 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000299 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000300 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
301 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000302 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000303 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +0000304 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
305 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
306
Scott Michel86c041f2007-12-20 00:44:13 +0000307 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Legal);
308 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Legal);
309 setOperationAction(ISD::BIT_CONVERT, MVT::i64, Legal);
310 setOperationAction(ISD::BIT_CONVERT, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000311
312 // We cannot sextinreg(i1). Expand to shifts.
313 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000314
Scott Michel266bc8f2007-12-04 22:23:35 +0000315 // Support label based line numbers.
Dan Gohman7f460202008-06-30 20:59:49 +0000316 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000317 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000318
319 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000320 // appropriate instructions to materialize the address.
Scott Michel9c0c6b22008-11-21 02:56:16 +0000321 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel053c1da2008-01-29 02:16:57 +0000322 ++sctype) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000323 MVT VT = (MVT::SimpleValueType)sctype;
324
Scott Michel1df30c42008-12-29 03:23:36 +0000325 setOperationAction(ISD::GlobalAddress, VT, Custom);
326 setOperationAction(ISD::ConstantPool, VT, Custom);
327 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000328 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000329
330 // RET must be custom lowered, to meet ABI requirements
331 setOperationAction(ISD::RET, MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000332
Scott Michel266bc8f2007-12-04 22:23:35 +0000333 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
334 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000335
Scott Michel266bc8f2007-12-04 22:23:35 +0000336 // Use the default implementation.
337 setOperationAction(ISD::VAARG , MVT::Other, Expand);
338 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
339 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000340 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000341 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
342 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
343 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
344
345 // Cell SPU has instructions for converting between i64 and fp.
346 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
347 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000348
Scott Michel266bc8f2007-12-04 22:23:35 +0000349 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
350 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
351
352 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
353 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
354
355 // First set operation action for all vector types to expand. Then we
356 // will selectively turn on ones that can be effectively codegen'd.
357 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
358 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
359 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
360 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
361 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
362 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
363
Scott Michel21213e72009-01-06 23:10:38 +0000364 // "Odd size" vector classes that we're willing to support:
365 addRegisterClass(MVT::v2i32, SPU::VECREGRegisterClass);
366
Duncan Sands83ec4b62008-06-06 12:08:01 +0000367 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
368 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
369 MVT VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000370
Duncan Sands83ec4b62008-06-06 12:08:01 +0000371 // add/sub are legal for all supported vector VT's.
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000372 setOperationAction(ISD::ADD, VT, Legal);
373 setOperationAction(ISD::SUB, VT, Legal);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000374 // mul has to be custom lowered.
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000375 setOperationAction(ISD::MUL, VT, Legal);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000376
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000377 setOperationAction(ISD::AND, VT, Legal);
378 setOperationAction(ISD::OR, VT, Legal);
379 setOperationAction(ISD::XOR, VT, Legal);
380 setOperationAction(ISD::LOAD, VT, Legal);
381 setOperationAction(ISD::SELECT, VT, Legal);
382 setOperationAction(ISD::STORE, VT, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000383
Scott Michel266bc8f2007-12-04 22:23:35 +0000384 // These operations need to be expanded:
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000385 setOperationAction(ISD::SDIV, VT, Expand);
386 setOperationAction(ISD::SREM, VT, Expand);
387 setOperationAction(ISD::UDIV, VT, Expand);
388 setOperationAction(ISD::UREM, VT, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000389
390 // Custom lower build_vector, constant pool spills, insert and
391 // extract vector elements:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000392 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
393 setOperationAction(ISD::ConstantPool, VT, Custom);
394 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
395 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
396 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
397 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000398 }
399
Scott Michel266bc8f2007-12-04 22:23:35 +0000400 setOperationAction(ISD::AND, MVT::v16i8, Custom);
401 setOperationAction(ISD::OR, MVT::v16i8, Custom);
402 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
403 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000404
Scott Michel02d711b2008-12-30 23:28:25 +0000405 setOperationAction(ISD::FDIV, MVT::v4f32, Legal);
Scott Michel1df30c42008-12-29 03:23:36 +0000406
Scott Michel266bc8f2007-12-04 22:23:35 +0000407 setShiftAmountType(MVT::i32);
Scott Michelf0569be2008-12-27 04:51:36 +0000408 setBooleanContents(ZeroOrNegativeOneBooleanContent);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000409
Scott Michel266bc8f2007-12-04 22:23:35 +0000410 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000411
Scott Michel266bc8f2007-12-04 22:23:35 +0000412 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000413 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000414 setTargetDAGCombine(ISD::ZERO_EXTEND);
415 setTargetDAGCombine(ISD::SIGN_EXTEND);
416 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000417
Scott Michel266bc8f2007-12-04 22:23:35 +0000418 computeRegisterProperties();
Scott Michel7a1c9e92008-11-22 23:50:42 +0000419
Scott Michele07d3de2008-12-09 03:37:19 +0000420 // Set pre-RA register scheduler default to BURR, which produces slightly
421 // better code than the default (could also be TDRR, but TargetLowering.h
422 // needs a mod to support that model):
423 setSchedulingPreference(SchedulingForRegPressure);
Scott Michel266bc8f2007-12-04 22:23:35 +0000424}
425
426const char *
427SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
428{
429 if (node_names.empty()) {
430 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
431 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
432 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
433 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000434 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000435 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000436 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
437 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
438 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel7a1c9e92008-11-22 23:50:42 +0000439 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000440 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
Scott Michel1df30c42008-12-29 03:23:36 +0000441 node_names[(unsigned) SPUISD::PREFSLOT2VEC] = "SPUISD::PREFSLOT2VEC";
Scott Michel104de432008-11-24 17:11:17 +0000442 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
Scott Michela59d4692008-02-23 18:41:37 +0000443 node_names[(unsigned) SPUISD::SHLQUAD_L_BITS] = "SPUISD::SHLQUAD_L_BITS";
444 node_names[(unsigned) SPUISD::SHLQUAD_L_BYTES] = "SPUISD::SHLQUAD_L_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000445 node_names[(unsigned) SPUISD::VEC_SHL] = "SPUISD::VEC_SHL";
446 node_names[(unsigned) SPUISD::VEC_SRL] = "SPUISD::VEC_SRL";
447 node_names[(unsigned) SPUISD::VEC_SRA] = "SPUISD::VEC_SRA";
448 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
449 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Micheld1e8d9c2009-01-21 04:58:48 +0000450 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
451 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
452 "SPUISD::ROTBYTES_LEFT_BITS";
Scott Michel8bf61e82008-06-02 22:18:03 +0000453 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000454 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel94bd57e2009-01-15 04:41:47 +0000455 node_names[(unsigned) SPUISD::ADD64_MARKER] = "SPUISD::ADD64_MARKER";
456 node_names[(unsigned) SPUISD::SUB64_MARKER] = "SPUISD::SUB64_MARKER";
457 node_names[(unsigned) SPUISD::MUL64_MARKER] = "SPUISD::MUL64_MARKER";
Scott Michel266bc8f2007-12-04 22:23:35 +0000458 }
459
460 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
461
462 return ((i != node_names.end()) ? i->second : 0);
463}
464
Scott Michelf0569be2008-12-27 04:51:36 +0000465//===----------------------------------------------------------------------===//
466// Return the Cell SPU's SETCC result type
467//===----------------------------------------------------------------------===//
468
Duncan Sands5480c042009-01-01 15:52:00 +0000469MVT SPUTargetLowering::getSetCCResultType(MVT VT) const {
Scott Michelf0569be2008-12-27 04:51:36 +0000470 // i16 and i32 are valid SETCC result types
471 return ((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) ? VT : MVT::i32);
Scott Michel78c47fa2008-03-10 16:58:52 +0000472}
473
Scott Michel266bc8f2007-12-04 22:23:35 +0000474//===----------------------------------------------------------------------===//
475// Calling convention code:
476//===----------------------------------------------------------------------===//
477
478#include "SPUGenCallingConv.inc"
479
480//===----------------------------------------------------------------------===//
481// LowerOperation implementation
482//===----------------------------------------------------------------------===//
483
484/// Custom lower loads for CellSPU
485/*!
486 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
487 within a 16-byte block, we have to rotate to extract the requested element.
Scott Michel30ee7df2008-12-04 03:02:42 +0000488
489 For extending loads, we also want to ensure that the following sequence is
490 emitted, e.g. for MVT::f32 extending load to MVT::f64:
491
492\verbatim
Scott Michel1df30c42008-12-29 03:23:36 +0000493%1 v16i8,ch = load
Scott Michel30ee7df2008-12-04 03:02:42 +0000494%2 v16i8,ch = rotate %1
Scott Michel1df30c42008-12-29 03:23:36 +0000495%3 v4f8, ch = bitconvert %2
Scott Michel30ee7df2008-12-04 03:02:42 +0000496%4 f32 = vec2perfslot %3
497%5 f64 = fp_extend %4
498\endverbatim
499*/
Dan Gohman475871a2008-07-27 21:46:04 +0000500static SDValue
501LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000502 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000503 SDValue the_chain = LN->getChain();
Scott Michelf0569be2008-12-27 04:51:36 +0000504 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel30ee7df2008-12-04 03:02:42 +0000505 MVT InVT = LN->getMemoryVT();
506 MVT OutVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000507 ISD::LoadExtType ExtType = LN->getExtensionType();
508 unsigned alignment = LN->getAlignment();
Scott Michelf0569be2008-12-27 04:51:36 +0000509 const valtype_map_s *vtm = getValueTypeMapEntry(InVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000510
Scott Michel266bc8f2007-12-04 22:23:35 +0000511 switch (LN->getAddressingMode()) {
512 case ISD::UNINDEXED: {
Scott Michelf0569be2008-12-27 04:51:36 +0000513 SDValue result;
514 SDValue basePtr = LN->getBasePtr();
515 SDValue rotate;
Scott Michel266bc8f2007-12-04 22:23:35 +0000516
Scott Michelf0569be2008-12-27 04:51:36 +0000517 if (alignment == 16) {
518 ConstantSDNode *CN;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000519
Scott Michelf0569be2008-12-27 04:51:36 +0000520 // Special cases for a known aligned load to simplify the base pointer
521 // and the rotation amount:
522 if (basePtr.getOpcode() == ISD::ADD
523 && (CN = dyn_cast<ConstantSDNode > (basePtr.getOperand(1))) != 0) {
524 // Known offset into basePtr
525 int64_t offset = CN->getSExtValue();
526 int64_t rotamt = int64_t((offset & 0xf) - vtm->prefslot_byte);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000527
Scott Michelf0569be2008-12-27 04:51:36 +0000528 if (rotamt < 0)
529 rotamt += 16;
530
531 rotate = DAG.getConstant(rotamt, MVT::i16);
532
533 // Simplify the base pointer for this case:
534 basePtr = basePtr.getOperand(0);
535 if ((offset & ~0xf) > 0) {
536 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
537 basePtr,
538 DAG.getConstant((offset & ~0xf), PtrVT));
539 }
540 } else if ((basePtr.getOpcode() == SPUISD::AFormAddr)
541 || (basePtr.getOpcode() == SPUISD::IndirectAddr
542 && basePtr.getOperand(0).getOpcode() == SPUISD::Hi
543 && basePtr.getOperand(1).getOpcode() == SPUISD::Lo)) {
544 // Plain aligned a-form address: rotate into preferred slot
545 // Same for (SPUindirect (SPUhi ...), (SPUlo ...))
546 int64_t rotamt = -vtm->prefslot_byte;
547 if (rotamt < 0)
548 rotamt += 16;
549 rotate = DAG.getConstant(rotamt, MVT::i16);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000550 } else {
Scott Michelf0569be2008-12-27 04:51:36 +0000551 // Offset the rotate amount by the basePtr and the preferred slot
552 // byte offset
553 int64_t rotamt = -vtm->prefslot_byte;
554 if (rotamt < 0)
555 rotamt += 16;
556 rotate = DAG.getNode(ISD::ADD, PtrVT,
557 basePtr,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000558 DAG.getConstant(rotamt, PtrVT));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000559 }
Scott Michelf0569be2008-12-27 04:51:36 +0000560 } else {
561 // Unaligned load: must be more pessimistic about addressing modes:
562 if (basePtr.getOpcode() == ISD::ADD) {
563 MachineFunction &MF = DAG.getMachineFunction();
564 MachineRegisterInfo &RegInfo = MF.getRegInfo();
565 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
566 SDValue Flag;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000567
Scott Michelf0569be2008-12-27 04:51:36 +0000568 SDValue Op0 = basePtr.getOperand(0);
569 SDValue Op1 = basePtr.getOperand(1);
570
571 if (isa<ConstantSDNode>(Op1)) {
572 // Convert the (add <ptr>, <const>) to an indirect address contained
573 // in a register. Note that this is done because we need to avoid
574 // creating a 0(reg) d-form address due to the SPU's block loads.
575 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
576 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
577 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
578 } else {
579 // Convert the (add <arg1>, <arg2>) to an indirect address, which
580 // will likely be lowered as a reg(reg) x-form address.
581 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
582 }
583 } else {
584 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
585 basePtr,
586 DAG.getConstant(0, PtrVT));
587 }
588
589 // Offset the rotate amount by the basePtr and the preferred slot
590 // byte offset
591 rotate = DAG.getNode(ISD::ADD, PtrVT,
592 basePtr,
593 DAG.getConstant(-vtm->prefslot_byte, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +0000594 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000595
Scott Michelf0569be2008-12-27 04:51:36 +0000596 // Re-emit as a v16i8 vector load
597 result = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
598 LN->getSrcValue(), LN->getSrcValueOffset(),
599 LN->isVolatile(), 16);
600
601 // Update the chain
602 the_chain = result.getValue(1);
603
604 // Rotate into the preferred slot:
605 result = DAG.getNode(SPUISD::ROTBYTES_LEFT, MVT::v16i8,
606 result.getValue(0), rotate);
607
Scott Michel30ee7df2008-12-04 03:02:42 +0000608 // Convert the loaded v16i8 vector to the appropriate vector type
609 // specified by the operand:
610 MVT vecVT = MVT::getVectorVT(InVT, (128 / InVT.getSizeInBits()));
611 result = DAG.getNode(SPUISD::VEC2PREFSLOT, InVT,
Scott Michel19c10e62009-01-26 03:37:41 +0000612 DAG.getNode(ISD::BIT_CONVERT, vecVT, result));
Scott Michel5af8f0e2008-07-16 17:17:29 +0000613
Scott Michel30ee7df2008-12-04 03:02:42 +0000614 // Handle extending loads by extending the scalar result:
615 if (ExtType == ISD::SEXTLOAD) {
616 result = DAG.getNode(ISD::SIGN_EXTEND, OutVT, result);
617 } else if (ExtType == ISD::ZEXTLOAD) {
618 result = DAG.getNode(ISD::ZERO_EXTEND, OutVT, result);
619 } else if (ExtType == ISD::EXTLOAD) {
620 unsigned NewOpc = ISD::ANY_EXTEND;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000621
Scott Michel30ee7df2008-12-04 03:02:42 +0000622 if (OutVT.isFloatingPoint())
Scott Michel19c10e62009-01-26 03:37:41 +0000623 NewOpc = ISD::FP_EXTEND;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000624
Scott Michel30ee7df2008-12-04 03:02:42 +0000625 result = DAG.getNode(NewOpc, OutVT, result);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000626 }
627
Scott Michel30ee7df2008-12-04 03:02:42 +0000628 SDVTList retvts = DAG.getVTList(OutVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000629 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000630 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000631 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000632 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000633
Scott Michel58c58182008-01-17 20:38:41 +0000634 result = DAG.getNode(SPUISD::LDRESULT, retvts,
635 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000636 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000637 }
638 case ISD::PRE_INC:
639 case ISD::PRE_DEC:
640 case ISD::POST_INC:
641 case ISD::POST_DEC:
642 case ISD::LAST_INDEXED_MODE:
643 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
644 "UNINDEXED\n";
645 cerr << (unsigned) LN->getAddressingMode() << "\n";
646 abort();
647 /*NOTREACHED*/
648 }
649
Dan Gohman475871a2008-07-27 21:46:04 +0000650 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000651}
652
653/// Custom lower stores for CellSPU
654/*!
655 All CellSPU stores are aligned to 16-byte boundaries, so for elements
656 within a 16-byte block, we have to generate a shuffle to insert the
657 requested element into its place, then store the resulting block.
658 */
Dan Gohman475871a2008-07-27 21:46:04 +0000659static SDValue
660LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000661 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000662 SDValue Value = SN->getValue();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000663 MVT VT = Value.getValueType();
664 MVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
665 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000666 unsigned alignment = SN->getAlignment();
Scott Michel266bc8f2007-12-04 22:23:35 +0000667
668 switch (SN->getAddressingMode()) {
669 case ISD::UNINDEXED: {
Scott Michel9c0c6b22008-11-21 02:56:16 +0000670 // The vector type we really want to load from the 16-byte chunk.
Scott Michel719b0e12008-11-19 17:45:08 +0000671 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits())),
672 stVecVT = MVT::getVectorVT(StVT, (128 / StVT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000673
Scott Michelf0569be2008-12-27 04:51:36 +0000674 SDValue alignLoadVec;
675 SDValue basePtr = SN->getBasePtr();
676 SDValue the_chain = SN->getChain();
677 SDValue insertEltOffs;
Scott Michel266bc8f2007-12-04 22:23:35 +0000678
Scott Michelf0569be2008-12-27 04:51:36 +0000679 if (alignment == 16) {
680 ConstantSDNode *CN;
681
682 // Special cases for a known aligned load to simplify the base pointer
683 // and insertion byte:
684 if (basePtr.getOpcode() == ISD::ADD
685 && (CN = dyn_cast<ConstantSDNode>(basePtr.getOperand(1))) != 0) {
686 // Known offset into basePtr
687 int64_t offset = CN->getSExtValue();
688
689 // Simplify the base pointer for this case:
690 basePtr = basePtr.getOperand(0);
691 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
692 basePtr,
693 DAG.getConstant((offset & 0xf), PtrVT));
694
695 if ((offset & ~0xf) > 0) {
696 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
697 basePtr,
698 DAG.getConstant((offset & ~0xf), PtrVT));
699 }
700 } else {
701 // Otherwise, assume it's at byte 0 of basePtr
702 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
703 basePtr,
704 DAG.getConstant(0, PtrVT));
705 }
706 } else {
707 // Unaligned load: must be more pessimistic about addressing modes:
708 if (basePtr.getOpcode() == ISD::ADD) {
709 MachineFunction &MF = DAG.getMachineFunction();
710 MachineRegisterInfo &RegInfo = MF.getRegInfo();
711 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
712 SDValue Flag;
713
714 SDValue Op0 = basePtr.getOperand(0);
715 SDValue Op1 = basePtr.getOperand(1);
716
717 if (isa<ConstantSDNode>(Op1)) {
718 // Convert the (add <ptr>, <const>) to an indirect address contained
719 // in a register. Note that this is done because we need to avoid
720 // creating a 0(reg) d-form address due to the SPU's block loads.
721 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
722 the_chain = DAG.getCopyToReg(the_chain, VReg, basePtr, Flag);
723 basePtr = DAG.getCopyFromReg(the_chain, VReg, PtrVT);
724 } else {
725 // Convert the (add <arg1>, <arg2>) to an indirect address, which
726 // will likely be lowered as a reg(reg) x-form address.
727 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, Op0, Op1);
728 }
729 } else {
730 basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
731 basePtr,
732 DAG.getConstant(0, PtrVT));
733 }
734
735 // Insertion point is solely determined by basePtr's contents
736 insertEltOffs = DAG.getNode(ISD::ADD, PtrVT,
737 basePtr,
738 DAG.getConstant(0, PtrVT));
739 }
740
741 // Re-emit as a v16i8 vector load
742 alignLoadVec = DAG.getLoad(MVT::v16i8, the_chain, basePtr,
743 SN->getSrcValue(), SN->getSrcValueOffset(),
744 SN->isVolatile(), 16);
745
746 // Update the chain
747 the_chain = alignLoadVec.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000748
Scott Michel9de5d0d2008-01-11 02:53:15 +0000749 LoadSDNode *LN = cast<LoadSDNode>(alignLoadVec);
Dan Gohman475871a2008-07-27 21:46:04 +0000750 SDValue theValue = SN->getValue();
751 SDValue result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000752
753 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000754 && (theValue.getOpcode() == ISD::AssertZext
755 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000756 // Drill down and get the value for zero- and sign-extended
757 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000758 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000759 }
760
Scott Michel9de5d0d2008-01-11 02:53:15 +0000761 // If the base pointer is already a D-form address, then just create
762 // a new D-form address with a slot offset and the orignal base pointer.
763 // Otherwise generate a D-form address with the slot offset relative
764 // to the stack pointer, which is always aligned.
Scott Michelf0569be2008-12-27 04:51:36 +0000765#if !defined(NDEBUG)
766 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
767 cerr << "CellSPU LowerSTORE: basePtr = ";
768 basePtr.getNode()->dump(&DAG);
769 cerr << "\n";
770 }
771#endif
Scott Michel9de5d0d2008-01-11 02:53:15 +0000772
Scott Michel430a5552008-11-19 15:24:16 +0000773 SDValue insertEltOp =
Scott Michelf0569be2008-12-27 04:51:36 +0000774 DAG.getNode(SPUISD::SHUFFLE_MASK, vecVT, insertEltOffs);
Scott Michel719b0e12008-11-19 17:45:08 +0000775 SDValue vectorizeOp =
776 DAG.getNode(ISD::SCALAR_TO_VECTOR, vecVT, theValue);
Scott Michel430a5552008-11-19 15:24:16 +0000777
Scott Michel1a6cdb62008-12-01 17:56:02 +0000778 result = DAG.getNode(SPUISD::SHUFB, vecVT,
Scott Michel19c10e62009-01-26 03:37:41 +0000779 vectorizeOp, alignLoadVec,
780 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000781
Scott Michel9de5d0d2008-01-11 02:53:15 +0000782 result = DAG.getStore(the_chain, result, basePtr,
Scott Michel266bc8f2007-12-04 22:23:35 +0000783 LN->getSrcValue(), LN->getSrcValueOffset(),
784 LN->isVolatile(), LN->getAlignment());
785
Scott Michel23f2ff72008-12-04 17:16:59 +0000786#if 0 && !defined(NDEBUG)
Scott Michel430a5552008-11-19 15:24:16 +0000787 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
788 const SDValue &currentRoot = DAG.getRoot();
789
790 DAG.setRoot(result);
791 cerr << "------- CellSPU:LowerStore result:\n";
792 DAG.dump();
793 cerr << "-------\n";
794 DAG.setRoot(currentRoot);
795 }
796#endif
Scott Michelb30e8f62008-12-02 19:53:53 +0000797
Scott Michel266bc8f2007-12-04 22:23:35 +0000798 return result;
799 /*UNREACHED*/
800 }
801 case ISD::PRE_INC:
802 case ISD::PRE_DEC:
803 case ISD::POST_INC:
804 case ISD::POST_DEC:
805 case ISD::LAST_INDEXED_MODE:
806 cerr << "LowerLOAD: Got a LoadSDNode with an addr mode other than "
807 "UNINDEXED\n";
808 cerr << (unsigned) SN->getAddressingMode() << "\n";
809 abort();
810 /*NOTREACHED*/
811 }
812
Dan Gohman475871a2008-07-27 21:46:04 +0000813 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000814}
815
Scott Michel94bd57e2009-01-15 04:41:47 +0000816//! Generate the address of a constant pool entry.
817SDValue
Dan Gohman475871a2008-07-27 21:46:04 +0000818LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000819 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000820 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
821 Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000822 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
823 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000824 const TargetMachine &TM = DAG.getTarget();
Scott Michel266bc8f2007-12-04 22:23:35 +0000825
826 if (TM.getRelocationModel() == Reloc::Static) {
827 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000828 // Just return the SDValue with the constant pool address in it.
Scott Michel58c58182008-01-17 20:38:41 +0000829 return DAG.getNode(SPUISD::AFormAddr, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +0000830 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000831 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, CPI, Zero);
832 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, CPI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000833 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +0000834 }
835 }
836
837 assert(0 &&
Gabor Greif93c53e52008-08-31 15:37:04 +0000838 "LowerConstantPool: Relocation model other than static"
839 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000840 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000841}
842
Scott Michel94bd57e2009-01-15 04:41:47 +0000843//! Alternate entry point for generating the address of a constant pool entry
844SDValue
845SPU::LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUTargetMachine &TM) {
846 return ::LowerConstantPool(Op, DAG, TM.getSubtargetImpl());
847}
848
Dan Gohman475871a2008-07-27 21:46:04 +0000849static SDValue
850LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000851 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000852 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000853 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
854 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000855 const TargetMachine &TM = DAG.getTarget();
856
857 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +0000858 if (!ST->usingLargeMem()) {
859 return DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
860 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000861 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, JTI, Zero);
862 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +0000863 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
864 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000865 }
866
867 assert(0 &&
868 "LowerJumpTable: Relocation model other than static not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +0000869 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000870}
871
Dan Gohman475871a2008-07-27 21:46:04 +0000872static SDValue
873LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000874 MVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000875 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
876 GlobalValue *GV = GSDN->getGlobal();
Dan Gohman475871a2008-07-27 21:46:04 +0000877 SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +0000878 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +0000879 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000880
Scott Michel266bc8f2007-12-04 22:23:35 +0000881 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +0000882 if (!ST->usingLargeMem()) {
883 return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
884 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000885 SDValue Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
886 SDValue Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +0000887 return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
888 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000889 } else {
890 cerr << "LowerGlobalAddress: Relocation model other than static not "
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000891 << "supported.\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000892 abort();
893 /*NOTREACHED*/
894 }
895
Dan Gohman475871a2008-07-27 21:46:04 +0000896 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000897}
898
Nate Begemanccef5802008-02-14 18:43:04 +0000899//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +0000900static SDValue
901LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000902 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000903
Nate Begemanccef5802008-02-14 18:43:04 +0000904 if (VT == MVT::f64) {
Scott Michel1a6cdb62008-12-01 17:56:02 +0000905 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
906
907 assert((FP != 0) &&
908 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel1df30c42008-12-29 03:23:36 +0000909
Scott Michel170783a2007-12-19 20:15:47 +0000910 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Scott Michel1a6cdb62008-12-01 17:56:02 +0000911 SDValue T = DAG.getConstant(dbits, MVT::i64);
912 SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T);
913 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
914 DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64, Tvec));
Scott Michel266bc8f2007-12-04 22:23:35 +0000915 }
916
Dan Gohman475871a2008-07-27 21:46:04 +0000917 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000918}
919
Dan Gohman475871a2008-07-27 21:46:04 +0000920static SDValue
Dan Gohman475871a2008-07-27 21:46:04 +0000921LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
Scott Michel266bc8f2007-12-04 22:23:35 +0000922{
923 MachineFunction &MF = DAG.getMachineFunction();
924 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +0000925 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Micheld976c212008-10-30 01:51:48 +0000926 SmallVector<SDValue, 48> ArgValues;
Dan Gohman475871a2008-07-27 21:46:04 +0000927 SDValue Root = Op.getOperand(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000928 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
Scott Michel266bc8f2007-12-04 22:23:35 +0000929
930 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
931 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000932
Scott Michel266bc8f2007-12-04 22:23:35 +0000933 unsigned ArgOffset = SPUFrameInfo::minStackSize();
934 unsigned ArgRegIdx = 0;
935 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000936
Duncan Sands83ec4b62008-06-06 12:08:01 +0000937 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +0000938
Scott Michel266bc8f2007-12-04 22:23:35 +0000939 // Add DAG nodes to load the arguments or copy them out of registers.
Gabor Greif93c53e52008-08-31 15:37:04 +0000940 for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
941 ArgNo != e; ++ArgNo) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000942 MVT ObjectVT = Op.getValue(ArgNo).getValueType();
943 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Micheld976c212008-10-30 01:51:48 +0000944 SDValue ArgVal;
Scott Michel266bc8f2007-12-04 22:23:35 +0000945
Scott Micheld976c212008-10-30 01:51:48 +0000946 if (ArgRegIdx < NumArgRegs) {
947 const TargetRegisterClass *ArgRegClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +0000948
Scott Micheld976c212008-10-30 01:51:48 +0000949 switch (ObjectVT.getSimpleVT()) {
950 default: {
Scott Michel9c0c6b22008-11-21 02:56:16 +0000951 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
952 << ObjectVT.getMVTString()
953 << "\n";
954 abort();
Scott Micheld976c212008-10-30 01:51:48 +0000955 }
956 case MVT::i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000957 ArgRegClass = &SPU::R8CRegClass;
958 break;
Scott Micheld976c212008-10-30 01:51:48 +0000959 case MVT::i16:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000960 ArgRegClass = &SPU::R16CRegClass;
961 break;
Scott Micheld976c212008-10-30 01:51:48 +0000962 case MVT::i32:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000963 ArgRegClass = &SPU::R32CRegClass;
964 break;
Scott Micheld976c212008-10-30 01:51:48 +0000965 case MVT::i64:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000966 ArgRegClass = &SPU::R64CRegClass;
967 break;
Scott Micheldd950092009-01-06 03:36:14 +0000968 case MVT::i128:
969 ArgRegClass = &SPU::GPRCRegClass;
970 break;
Scott Micheld976c212008-10-30 01:51:48 +0000971 case MVT::f32:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000972 ArgRegClass = &SPU::R32FPRegClass;
973 break;
Scott Micheld976c212008-10-30 01:51:48 +0000974 case MVT::f64:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000975 ArgRegClass = &SPU::R64FPRegClass;
976 break;
Scott Micheld976c212008-10-30 01:51:48 +0000977 case MVT::v2f64:
978 case MVT::v4f32:
979 case MVT::v2i64:
980 case MVT::v4i32:
981 case MVT::v8i16:
982 case MVT::v16i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +0000983 ArgRegClass = &SPU::VECREGRegClass;
984 break;
Scott Micheld976c212008-10-30 01:51:48 +0000985 }
986
987 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
988 RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
989 ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
990 ++ArgRegIdx;
991 } else {
992 // We need to load the argument to a virtual register if we determined
993 // above that we ran out of physical registers of the appropriate type
994 // or we're forced to do vararg
Chris Lattner9f72d1a2008-02-13 07:35:30 +0000995 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +0000996 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattner9f72d1a2008-02-13 07:35:30 +0000997 ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000998 ArgOffset += StackSlotSize;
999 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001000
Scott Michel266bc8f2007-12-04 22:23:35 +00001001 ArgValues.push_back(ArgVal);
Scott Micheld976c212008-10-30 01:51:48 +00001002 // Update the chain
1003 Root = ArgVal.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001004 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001005
Scott Micheld976c212008-10-30 01:51:48 +00001006 // vararg handling:
Scott Michel266bc8f2007-12-04 22:23:35 +00001007 if (isVarArg) {
Scott Micheld976c212008-10-30 01:51:48 +00001008 // unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
1009 // We will spill (79-3)+1 registers to the stack
1010 SmallVector<SDValue, 79-3+1> MemOps;
1011
1012 // Create the frame slot
1013
Scott Michel266bc8f2007-12-04 22:23:35 +00001014 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Scott Micheld976c212008-10-30 01:51:48 +00001015 VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
1016 SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
1017 SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
1018 SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
1019 Root = Store.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001020 MemOps.push_back(Store);
Scott Micheld976c212008-10-30 01:51:48 +00001021
1022 // Increment address by stack slot size for the next stored argument
1023 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001024 }
1025 if (!MemOps.empty())
Scott Micheld976c212008-10-30 01:51:48 +00001026 Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001027 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001028
Scott Michel266bc8f2007-12-04 22:23:35 +00001029 ArgValues.push_back(Root);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001030
Scott Michel266bc8f2007-12-04 22:23:35 +00001031 // Return the new list of results.
Duncan Sandsaaffa052008-12-01 11:41:29 +00001032 return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
1033 &ArgValues[0], ArgValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001034}
1035
1036/// isLSAAddress - Return the immediate to use if the specified
1037/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001038static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001039 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +00001040 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001041
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001042 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001043 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1044 (Addr << 14 >> 14) != Addr)
1045 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001046
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001047 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001048}
1049
Scott Michel21213e72009-01-06 23:10:38 +00001050static SDValue
Dan Gohman475871a2008-07-27 21:46:04 +00001051LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Dan Gohman095cc292008-09-13 01:54:27 +00001052 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
1053 SDValue Chain = TheCall->getChain();
Dan Gohman095cc292008-09-13 01:54:27 +00001054 SDValue Callee = TheCall->getCallee();
1055 unsigned NumOps = TheCall->getNumArgs();
Scott Michel266bc8f2007-12-04 22:23:35 +00001056 unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
1057 const unsigned *ArgRegs = SPURegisterInfo::getArgRegs();
1058 const unsigned NumArgRegs = SPURegisterInfo::getNumArgRegs();
1059
1060 // Handy pointer type
Duncan Sands83ec4b62008-06-06 12:08:01 +00001061 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001062
Scott Michel266bc8f2007-12-04 22:23:35 +00001063 // Accumulate how many bytes are to be pushed on the stack, including the
1064 // linkage area, and parameter passing area. According to the SPU ABI,
1065 // we minimally need space for [LR] and [SP]
1066 unsigned NumStackBytes = SPUFrameInfo::minStackSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001067
Scott Michel266bc8f2007-12-04 22:23:35 +00001068 // Set up a copy of the stack pointer for use loading and storing any
1069 // arguments that may not fit in the registers available for argument
1070 // passing.
Dan Gohman475871a2008-07-27 21:46:04 +00001071 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001072
Scott Michel266bc8f2007-12-04 22:23:35 +00001073 // Figure out which arguments are going to go in registers, and which in
1074 // memory.
1075 unsigned ArgOffset = SPUFrameInfo::minStackSize(); // Just below [LR]
1076 unsigned ArgRegIdx = 0;
1077
1078 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001079 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001080 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001081 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001082
1083 for (unsigned i = 0; i != NumOps; ++i) {
Dan Gohman095cc292008-09-13 01:54:27 +00001084 SDValue Arg = TheCall->getArg(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001085
Scott Michel266bc8f2007-12-04 22:23:35 +00001086 // PtrOff will be used to store the current argument to the stack if a
1087 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001088 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001089 PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
1090
Duncan Sands83ec4b62008-06-06 12:08:01 +00001091 switch (Arg.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001092 default: assert(0 && "Unexpected ValueType for argument!");
Scott Micheldd950092009-01-06 03:36:14 +00001093 case MVT::i8:
1094 case MVT::i16:
Scott Michel266bc8f2007-12-04 22:23:35 +00001095 case MVT::i32:
1096 case MVT::i64:
1097 case MVT::i128:
1098 if (ArgRegIdx != NumArgRegs) {
1099 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1100 } else {
1101 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001102 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001103 }
1104 break;
1105 case MVT::f32:
1106 case MVT::f64:
1107 if (ArgRegIdx != NumArgRegs) {
1108 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1109 } else {
1110 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001111 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001112 }
1113 break;
Scott Michelcc188272008-12-04 21:01:44 +00001114 case MVT::v2i64:
1115 case MVT::v2f64:
Scott Michel266bc8f2007-12-04 22:23:35 +00001116 case MVT::v4f32:
1117 case MVT::v4i32:
1118 case MVT::v8i16:
1119 case MVT::v16i8:
1120 if (ArgRegIdx != NumArgRegs) {
1121 RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg));
1122 } else {
1123 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001124 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001125 }
1126 break;
1127 }
1128 }
1129
1130 // Update number of stack bytes actually used, insert a call sequence start
1131 NumStackBytes = (ArgOffset - SPUFrameInfo::minStackSize());
Chris Lattnere563bbc2008-10-11 22:08:30 +00001132 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1133 true));
Scott Michel266bc8f2007-12-04 22:23:35 +00001134
1135 if (!MemOpChains.empty()) {
1136 // Adjust the stack pointer for the stack arguments.
1137 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
1138 &MemOpChains[0], MemOpChains.size());
1139 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001140
Scott Michel266bc8f2007-12-04 22:23:35 +00001141 // Build a sequence of copy-to-reg nodes chained together with token chain
1142 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001143 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001144 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1145 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
1146 InFlag);
1147 InFlag = Chain.getValue(1);
1148 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001149
Dan Gohman475871a2008-07-27 21:46:04 +00001150 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001151 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001152
Bill Wendling056292f2008-09-16 21:48:12 +00001153 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1154 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1155 // node so that legalize doesn't hack it.
Scott Michel19fd42a2008-11-11 03:06:06 +00001156 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001157 GlobalValue *GV = G->getGlobal();
Duncan Sands83ec4b62008-06-06 12:08:01 +00001158 MVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001159 SDValue Zero = DAG.getConstant(0, PtrVT);
1160 SDValue GA = DAG.getTargetGlobalAddress(GV, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001161
Scott Michel9de5d0d2008-01-11 02:53:15 +00001162 if (!ST->usingLargeMem()) {
1163 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1164 // style calls, otherwise, external symbols are BRASL calls. This assumes
1165 // that declared/defined symbols are in the same compilation unit and can
1166 // be reached through PC-relative jumps.
1167 //
1168 // NOTE:
1169 // This may be an unsafe assumption for JIT and really large compilation
1170 // units.
1171 if (GV->isDeclaration()) {
1172 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, GA, Zero);
1173 } else {
1174 Callee = DAG.getNode(SPUISD::PCRelAddr, CalleeVT, GA, Zero);
1175 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001176 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001177 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1178 // address pairs:
Scott Michel053c1da2008-01-29 02:16:57 +00001179 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001180 }
Scott Michel1df30c42008-12-29 03:23:36 +00001181 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
1182 MVT CalleeVT = Callee.getValueType();
1183 SDValue Zero = DAG.getConstant(0, PtrVT);
1184 SDValue ExtSym = DAG.getTargetExternalSymbol(S->getSymbol(),
1185 Callee.getValueType());
1186
1187 if (!ST->usingLargeMem()) {
1188 Callee = DAG.getNode(SPUISD::AFormAddr, CalleeVT, ExtSym, Zero);
1189 } else {
1190 Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, ExtSym, Zero);
1191 }
1192 } else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001193 // If this is an absolute destination address that appears to be a legal
1194 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001195 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001196 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001197
1198 Ops.push_back(Chain);
1199 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001200
Scott Michel266bc8f2007-12-04 22:23:35 +00001201 // Add argument registers to the end of the list so that they are known live
1202 // into the call.
1203 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001204 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001205 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001206
Gabor Greifba36cb52008-08-28 21:40:38 +00001207 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001208 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001209 // Returns a chain and a flag for retval copy to use.
1210 Chain = DAG.getNode(CallOpc, DAG.getVTList(MVT::Other, MVT::Flag),
1211 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001212 InFlag = Chain.getValue(1);
1213
Chris Lattnere563bbc2008-10-11 22:08:30 +00001214 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1215 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman095cc292008-09-13 01:54:27 +00001216 if (TheCall->getValueType(0) != MVT::Other)
Evan Chengebaaa912008-02-05 22:44:06 +00001217 InFlag = Chain.getValue(1);
1218
Dan Gohman475871a2008-07-27 21:46:04 +00001219 SDValue ResultVals[3];
Scott Michel266bc8f2007-12-04 22:23:35 +00001220 unsigned NumResults = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001221
Scott Michel266bc8f2007-12-04 22:23:35 +00001222 // If the call has results, copy the values out of the ret val registers.
Dan Gohman095cc292008-09-13 01:54:27 +00001223 switch (TheCall->getValueType(0).getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001224 default: assert(0 && "Unexpected ret value!");
1225 case MVT::Other: break;
1226 case MVT::i32:
Dan Gohman095cc292008-09-13 01:54:27 +00001227 if (TheCall->getValueType(1) == MVT::i32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001228 Chain = DAG.getCopyFromReg(Chain, SPU::R4, MVT::i32, InFlag).getValue(1);
1229 ResultVals[0] = Chain.getValue(0);
1230 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32,
1231 Chain.getValue(2)).getValue(1);
1232 ResultVals[1] = Chain.getValue(0);
1233 NumResults = 2;
Scott Michel266bc8f2007-12-04 22:23:35 +00001234 } else {
1235 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i32, InFlag).getValue(1);
1236 ResultVals[0] = Chain.getValue(0);
1237 NumResults = 1;
1238 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001239 break;
1240 case MVT::i64:
1241 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i64, InFlag).getValue(1);
1242 ResultVals[0] = Chain.getValue(0);
1243 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001244 break;
Scott Micheldd950092009-01-06 03:36:14 +00001245 case MVT::i128:
1246 Chain = DAG.getCopyFromReg(Chain, SPU::R3, MVT::i128, InFlag).getValue(1);
1247 ResultVals[0] = Chain.getValue(0);
1248 NumResults = 1;
1249 break;
Scott Michel266bc8f2007-12-04 22:23:35 +00001250 case MVT::f32:
1251 case MVT::f64:
Dan Gohman095cc292008-09-13 01:54:27 +00001252 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001253 InFlag).getValue(1);
1254 ResultVals[0] = Chain.getValue(0);
1255 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001256 break;
1257 case MVT::v2f64:
Scott Michelcc188272008-12-04 21:01:44 +00001258 case MVT::v2i64:
Scott Michel266bc8f2007-12-04 22:23:35 +00001259 case MVT::v4f32:
1260 case MVT::v4i32:
1261 case MVT::v8i16:
1262 case MVT::v16i8:
Dan Gohman095cc292008-09-13 01:54:27 +00001263 Chain = DAG.getCopyFromReg(Chain, SPU::R3, TheCall->getValueType(0),
Scott Michel266bc8f2007-12-04 22:23:35 +00001264 InFlag).getValue(1);
1265 ResultVals[0] = Chain.getValue(0);
1266 NumResults = 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00001267 break;
1268 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001269
Scott Michel266bc8f2007-12-04 22:23:35 +00001270 // If the function returns void, just return the chain.
1271 if (NumResults == 0)
1272 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001273
Scott Michel266bc8f2007-12-04 22:23:35 +00001274 // Otherwise, merge everything together with a MERGE_VALUES node.
1275 ResultVals[NumResults++] = Chain;
Dan Gohman475871a2008-07-27 21:46:04 +00001276 SDValue Res = DAG.getMergeValues(ResultVals, NumResults);
Gabor Greif99a6cb92008-08-26 22:36:50 +00001277 return Res.getValue(Op.getResNo());
Scott Michel266bc8f2007-12-04 22:23:35 +00001278}
1279
Dan Gohman475871a2008-07-27 21:46:04 +00001280static SDValue
1281LowerRET(SDValue Op, SelectionDAG &DAG, TargetMachine &TM) {
Scott Michel266bc8f2007-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 Greifba36cb52008-08-28 21:40:38 +00001286 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001287
Scott Michel266bc8f2007-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 Lattner84bc5422007-12-31 04:13:23 +00001290 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001291 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001292 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001293 }
1294
Dan Gohman475871a2008-07-27 21:46:04 +00001295 SDValue Chain = Op.getOperand(0);
1296 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001297
Scott Michel266bc8f2007-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 Greifba36cb52008-08-28 21:40:38 +00001306 if (Flag.getNode())
Scott Michel266bc8f2007-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 Gohman475871a2008-07-27 21:46:04 +00001319 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001320
Scott Michel266bc8f2007-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 Greifba36cb52008-08-28 21:40:38 +00001324 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001325 OpVal = N->getOperand(i);
1326 else if (OpVal != N->getOperand(i))
1327 return 0;
1328 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001329
Gabor Greifba36cb52008-08-28 21:40:38 +00001330 if (OpVal.getNode() != 0) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001331 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel266bc8f2007-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 Gohman475871a2008-07-27 21:46:04 +00001342SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001343 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001344 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001345 uint64_t Value = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001346 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001347 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-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 Gohman475871a2008-07-27 21:46:04 +00001351 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001352 Value = Value >> 32;
1353 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001354 if (Value <= 0x3ffff)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001355 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001356 }
1357
Dan Gohman475871a2008-07-27 21:46:04 +00001358 return SDValue();
Scott Michel266bc8f2007-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 Gohman475871a2008-07-27 21:46:04 +00001364SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001365 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001366 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001367 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001368 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001369 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-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 Gohman475871a2008-07-27 21:46:04 +00001373 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001374 Value = Value >> 32;
1375 }
Scott Michelad2715e2008-03-05 23:02:02 +00001376 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001377 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001378 }
1379 }
1380
Dan Gohman475871a2008-07-27 21:46:04 +00001381 return SDValue();
Scott Michel266bc8f2007-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 Gohman475871a2008-07-27 21:46:04 +00001387SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001388 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001389 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001390 int64_t Value = CN->getSExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001391 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001392 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-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 Gohman475871a2008-07-27 21:46:04 +00001396 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001397 Value = Value >> 32;
1398 }
Scott Michelad2715e2008-03-05 23:02:02 +00001399 if (isS10Constant(Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001400 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001401 }
1402
Dan Gohman475871a2008-07-27 21:46:04 +00001403 return SDValue();
Scott Michel266bc8f2007-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 Gohman475871a2008-07-27 21:46:04 +00001413SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001414 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001415 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001416 int Value = (int) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001417 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001418 && Value <= 0xffff /* truncated from uint64_t */
1419 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001420 return DAG.getTargetConstant(Value & 0xff, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001421 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001422 && (Value & 0xff) == Value)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001423 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001424 }
1425
Dan Gohman475871a2008-07-27 21:46:04 +00001426 return SDValue();
Scott Michel266bc8f2007-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 Gohman475871a2008-07-27 21:46:04 +00001432SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001433 MVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001434 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001435 uint64_t Value = CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001436 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001437 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1438 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001439 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001440 }
1441
Dan Gohman475871a2008-07-27 21:46:04 +00001442 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001443}
1444
1445/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001446SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001447 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001448 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001449 }
1450
Dan Gohman475871a2008-07-27 21:46:04 +00001451 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001452}
1453
1454/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001455SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001456 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001457 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001458 }
1459
Dan Gohman475871a2008-07-27 21:46:04 +00001460 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001461}
1462
1463// If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001464// UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-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 Michel5af8f0e2008-07-16 17:17:29 +00001472
Duncan Sands83ec4b62008-06-06 12:08:01 +00001473 unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
Scott Michel266bc8f2007-12-04 22:23:35 +00001474 for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
Dan Gohman475871a2008-07-27 21:46:04 +00001475 SDValue OpVal = BV->getOperand(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001476
Scott Michel266bc8f2007-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 Michel19fd42a2008-11-11 03:06:06 +00001485 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001486 EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
Scott Michel19fd42a2008-11-11 03:06:06 +00001487 } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001488 const APFloat &apf = CN->getValueAPF();
1489 EltBits = (CN->getValueType(0) == MVT::f32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001490 ? FloatToBits(apf.convertToFloat())
1491 : DoubleToBits(apf.convertToDouble()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001492 } else {
1493 // Nonconstant element.
1494 return true;
1495 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001496
Scott Michel266bc8f2007-12-04 22:23:35 +00001497 VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
1498 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001499
1500 //printf("%llx %llx %llx %llx\n",
Scott Michel266bc8f2007-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 Michel5af8f0e2008-07-16 17:17:29 +00001507/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
Scott Michel266bc8f2007-12-04 22:23:35 +00001508/// SplatSize = 1 byte.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001509static bool isConstantSplat(const uint64_t Bits128[2],
Scott Michel266bc8f2007-12-04 22:23:35 +00001510 const uint64_t Undef128[2],
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001511 int MinSplatBits,
Scott Michel266bc8f2007-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 Michel5af8f0e2008-07-16 17:17:29 +00001525
Scott Michel266bc8f2007-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 Michel7f9ba9b2008-01-30 02:55:46 +00001529 if (MinSplatBits < 32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001530
Scott Michel7f9ba9b2008-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 Greif93c53e52008-08-31 15:37:04 +00001537 if ((Bits16 & (uint16_t(~Undef16) >> 8))
1538 == ((Bits16 >> 8) & ~Undef16)) {
Scott Michel7f9ba9b2008-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 Michel266bc8f2007-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
Scott Micheld1e8d9c2009-01-21 04:58:48 +00001570//! Lower a BUILD_VECTOR instruction creatively:
1571SDValue
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001572LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001573 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001574 // If this is a vector of constants or undefs, get the bits. A bit in
Scott Michel5af8f0e2008-07-16 17:17:29 +00001575 // UndefBits is set if the corresponding element of the vector is an
Scott Michel266bc8f2007-12-04 22:23:35 +00001576 // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
Scott Michel5af8f0e2008-07-16 17:17:29 +00001577 // zero.
Scott Michel266bc8f2007-12-04 22:23:35 +00001578 uint64_t VectorBits[2];
1579 uint64_t UndefBits[2];
1580 uint64_t SplatBits, SplatUndef;
1581 int SplatSize;
Gabor Greifba36cb52008-08-28 21:40:38 +00001582 if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
Scott Michel266bc8f2007-12-04 22:23:35 +00001583 || !isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00001584 VT.getVectorElementType().getSizeInBits(),
Scott Michel266bc8f2007-12-04 22:23:35 +00001585 SplatBits, SplatUndef, SplatSize))
Dan Gohman475871a2008-07-27 21:46:04 +00001586 return SDValue(); // Not a constant vector, not a splat.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001587
Duncan Sands83ec4b62008-06-06 12:08:01 +00001588 switch (VT.getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001589 default:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00001590 cerr << "CellSPU: Unhandled VT in LowerBUILD_VECTOR, VT = "
1591 << VT.getMVTString()
1592 << "\n";
1593 abort();
1594 /*NOTREACHED*/
Scott Michel266bc8f2007-12-04 22:23:35 +00001595 case MVT::v4f32: {
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001596 uint32_t Value32 = uint32_t(SplatBits);
Scott Michel266bc8f2007-12-04 22:23:35 +00001597 assert(SplatSize == 4
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001598 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001599 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001600 SDValue T = DAG.getConstant(Value32, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001601 return DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001602 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, T, T, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001603 break;
1604 }
1605 case MVT::v2f64: {
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001606 uint64_t f64val = uint64_t(SplatBits);
Scott Michel266bc8f2007-12-04 22:23:35 +00001607 assert(SplatSize == 8
Scott Michel104de432008-11-24 17:11:17 +00001608 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001609 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Dan Gohman475871a2008-07-27 21:46:04 +00001610 SDValue T = DAG.getConstant(f64val, MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001611 return DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001612 DAG.getNode(ISD::BUILD_VECTOR, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001613 break;
1614 }
1615 case MVT::v16i8: {
1616 // 8-bit constants have to be expanded to 16-bits
1617 unsigned short Value16 = SplatBits | (SplatBits << 8);
Dan Gohman475871a2008-07-27 21:46:04 +00001618 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001619 for (int i = 0; i < 8; ++i)
1620 Ops[i] = DAG.getConstant(Value16, MVT::i16);
1621 return DAG.getNode(ISD::BIT_CONVERT, VT,
1622 DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops, 8));
1623 }
1624 case MVT::v8i16: {
1625 unsigned short Value16;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001626 if (SplatSize == 2)
Scott Michel266bc8f2007-12-04 22:23:35 +00001627 Value16 = (unsigned short) (SplatBits & 0xffff);
1628 else
1629 Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
Dan Gohman475871a2008-07-27 21:46:04 +00001630 SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
1631 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +00001632 for (int i = 0; i < 8; ++i) Ops[i] = T;
1633 return DAG.getNode(ISD::BUILD_VECTOR, VT, Ops, 8);
1634 }
1635 case MVT::v4i32: {
1636 unsigned int Value = SplatBits;
Dan Gohman475871a2008-07-27 21:46:04 +00001637 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
Scott Michel266bc8f2007-12-04 22:23:35 +00001638 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T, T, T);
1639 }
Scott Michel21213e72009-01-06 23:10:38 +00001640 case MVT::v2i32: {
1641 unsigned int Value = SplatBits;
1642 SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
1643 return DAG.getNode(ISD::BUILD_VECTOR, VT, T, T);
1644 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001645 case MVT::v2i64: {
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001646 return SPU::LowerSplat_v2i64(VT, DAG, SplatBits);
Scott Michel266bc8f2007-12-04 22:23:35 +00001647 }
1648 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001649
Dan Gohman475871a2008-07-27 21:46:04 +00001650 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001651}
1652
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001653SDValue
1654SPU::LowerSplat_v2i64(MVT OpVT, SelectionDAG& DAG, uint64_t SplatVal) {
1655 uint32_t upper = uint32_t(SplatVal >> 32);
1656 uint32_t lower = uint32_t(SplatVal);
1657
1658 if (upper == lower) {
1659 // Magic constant that can be matched by IL, ILA, et. al.
1660 SDValue Val = DAG.getTargetConstant(upper, MVT::i32);
1661 return DAG.getNode(ISD::BIT_CONVERT, OpVT,
1662 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1663 Val, Val, Val, Val));
1664 } else {
1665 SDValue LO32;
1666 SDValue HI32;
1667 SmallVector<SDValue, 16> ShufBytes;
1668 SDValue Result;
1669 bool upper_special, lower_special;
1670
1671 // NOTE: This code creates common-case shuffle masks that can be easily
1672 // detected as common expressions. It is not attempting to create highly
1673 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1674
1675 // Detect if the upper or lower half is a special shuffle mask pattern:
1676 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1677 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1678
1679 // Create lower vector if not a special pattern
1680 if (!lower_special) {
1681 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
1682 LO32 = DAG.getNode(ISD::BIT_CONVERT, OpVT,
1683 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1684 LO32C, LO32C, LO32C, LO32C));
1685 }
1686
1687 // Create upper vector if not a special pattern
1688 if (!upper_special) {
1689 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
1690 HI32 = DAG.getNode(ISD::BIT_CONVERT, OpVT,
1691 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1692 HI32C, HI32C, HI32C, HI32C));
1693 }
1694
1695 // If either upper or lower are special, then the two input operands are
1696 // the same (basically, one of them is a "don't care")
1697 if (lower_special)
1698 LO32 = HI32;
1699 if (upper_special)
1700 HI32 = LO32;
1701 if (lower_special && upper_special) {
1702 // Unhappy situation... both upper and lower are special, so punt with
1703 // a target constant:
1704 SDValue Zero = DAG.getConstant(0, MVT::i32);
1705 HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Zero, Zero,
1706 Zero, Zero);
1707 }
1708
1709 for (int i = 0; i < 4; ++i) {
1710 uint64_t val = 0;
1711 for (int j = 0; j < 4; ++j) {
1712 SDValue V;
1713 bool process_upper, process_lower;
1714 val <<= 8;
1715 process_upper = (upper_special && (i & 1) == 0);
1716 process_lower = (lower_special && (i & 1) == 1);
1717
1718 if (process_upper || process_lower) {
1719 if ((process_upper && upper == 0)
1720 || (process_lower && lower == 0))
1721 val |= 0x80;
1722 else if ((process_upper && upper == 0xffffffff)
1723 || (process_lower && lower == 0xffffffff))
1724 val |= 0xc0;
1725 else if ((process_upper && upper == 0x80000000)
1726 || (process_lower && lower == 0x80000000))
1727 val |= (j == 0 ? 0xe0 : 0x80);
1728 } else
1729 val |= i * 4 + j + ((i & 1) * 16);
1730 }
1731
1732 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
1733 }
1734
1735 return DAG.getNode(SPUISD::SHUFB, OpVT, HI32, LO32,
1736 DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1737 &ShufBytes[0], ShufBytes.size()));
1738 }
1739}
1740
Scott Michel266bc8f2007-12-04 22:23:35 +00001741/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1742/// which the Cell can operate. The code inspects V3 to ascertain whether the
1743/// permutation vector, V3, is monotonically increasing with one "exception"
1744/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel7a1c9e92008-11-22 23:50:42 +00001745/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel266bc8f2007-12-04 22:23:35 +00001746/// In either case, the net result is going to eventually invoke SHUFB to
1747/// permute/shuffle the bytes from V1 and V2.
1748/// \note
Scott Michel7a1c9e92008-11-22 23:50:42 +00001749/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel266bc8f2007-12-04 22:23:35 +00001750/// control word for byte/halfword/word insertion. This takes care of a single
1751/// element move from V2 into V1.
1752/// \note
1753/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001754static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1755 SDValue V1 = Op.getOperand(0);
1756 SDValue V2 = Op.getOperand(1);
1757 SDValue PermMask = Op.getOperand(2);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001758
Scott Michel266bc8f2007-12-04 22:23:35 +00001759 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001760
Scott Michel266bc8f2007-12-04 22:23:35 +00001761 // If we have a single element being moved from V1 to V2, this can be handled
1762 // using the C*[DX] compute mask instructions, but the vector elements have
1763 // to be monotonically increasing with one exception element.
Scott Michelcc188272008-12-04 21:01:44 +00001764 MVT VecVT = V1.getValueType();
1765 MVT EltVT = VecVT.getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001766 unsigned EltsFromV2 = 0;
1767 unsigned V2Elt = 0;
1768 unsigned V2EltIdx0 = 0;
1769 unsigned CurrElt = 0;
Scott Michelcc188272008-12-04 21:01:44 +00001770 unsigned MaxElts = VecVT.getVectorNumElements();
1771 unsigned PrevElt = 0;
1772 unsigned V0Elt = 0;
Scott Michel266bc8f2007-12-04 22:23:35 +00001773 bool monotonic = true;
Scott Michelcc188272008-12-04 21:01:44 +00001774 bool rotate = true;
1775
1776 if (EltVT == MVT::i8) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001777 V2EltIdx0 = 16;
Scott Michelcc188272008-12-04 21:01:44 +00001778 } else if (EltVT == MVT::i16) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001779 V2EltIdx0 = 8;
Scott Michelcc188272008-12-04 21:01:44 +00001780 } else if (EltVT == MVT::i32 || EltVT == MVT::f32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001781 V2EltIdx0 = 4;
Scott Michelcc188272008-12-04 21:01:44 +00001782 } else if (EltVT == MVT::i64 || EltVT == MVT::f64) {
1783 V2EltIdx0 = 2;
1784 } else
Scott Michel266bc8f2007-12-04 22:23:35 +00001785 assert(0 && "Unhandled vector type in LowerVECTOR_SHUFFLE");
1786
Scott Michelcc188272008-12-04 21:01:44 +00001787 for (unsigned i = 0; i != PermMask.getNumOperands(); ++i) {
1788 if (PermMask.getOperand(i).getOpcode() != ISD::UNDEF) {
1789 unsigned SrcElt = cast<ConstantSDNode > (PermMask.getOperand(i))->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001790
Scott Michelcc188272008-12-04 21:01:44 +00001791 if (monotonic) {
1792 if (SrcElt >= V2EltIdx0) {
1793 if (1 >= (++EltsFromV2)) {
1794 V2Elt = (V2EltIdx0 - SrcElt) << 2;
1795 }
1796 } else if (CurrElt != SrcElt) {
1797 monotonic = false;
1798 }
1799
1800 ++CurrElt;
1801 }
1802
1803 if (rotate) {
1804 if (PrevElt > 0 && SrcElt < MaxElts) {
1805 if ((PrevElt == SrcElt - 1)
1806 || (PrevElt == MaxElts - 1 && SrcElt == 0)) {
1807 PrevElt = SrcElt;
1808 if (SrcElt == 0)
1809 V0Elt = i;
1810 } else {
1811 rotate = false;
1812 }
1813 } else if (PrevElt == 0) {
1814 // First time through, need to keep track of previous element
1815 PrevElt = SrcElt;
1816 } else {
1817 // This isn't a rotation, takes elements from vector 2
1818 rotate = false;
1819 }
1820 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001821 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001822 }
1823
1824 if (EltsFromV2 == 1 && monotonic) {
1825 // Compute mask and shuffle
1826 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00001827 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1828 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Duncan Sands83ec4b62008-06-06 12:08:01 +00001829 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00001830 // Initialize temporary register to 0
Dan Gohman475871a2008-07-27 21:46:04 +00001831 SDValue InitTempReg =
Scott Michel266bc8f2007-12-04 22:23:35 +00001832 DAG.getCopyToReg(DAG.getEntryNode(), VReg, DAG.getConstant(0, PtrVT));
Scott Michel7a1c9e92008-11-22 23:50:42 +00001833 // Copy register's contents as index in SHUFFLE_MASK:
Dan Gohman475871a2008-07-27 21:46:04 +00001834 SDValue ShufMaskOp =
Scott Michel1a6cdb62008-12-01 17:56:02 +00001835 DAG.getNode(SPUISD::SHUFFLE_MASK, MVT::v4i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001836 DAG.getTargetConstant(V2Elt, MVT::i32),
1837 DAG.getCopyFromReg(InitTempReg, VReg, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +00001838 // Use shuffle mask in SHUFB synthetic instruction:
1839 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V2, V1, ShufMaskOp);
Scott Michelcc188272008-12-04 21:01:44 +00001840 } else if (rotate) {
1841 int rotamt = (MaxElts - V0Elt) * EltVT.getSizeInBits()/8;
Scott Michel1df30c42008-12-29 03:23:36 +00001842
Scott Michelcc188272008-12-04 21:01:44 +00001843 return DAG.getNode(SPUISD::ROTBYTES_LEFT, V1.getValueType(),
1844 V1, DAG.getConstant(rotamt, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001845 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001846 // Convert the SHUFFLE_VECTOR mask's input element units to the
1847 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001848 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001849
Dan Gohman475871a2008-07-27 21:46:04 +00001850 SmallVector<SDValue, 16> ResultMask;
Scott Michel266bc8f2007-12-04 22:23:35 +00001851 for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
1852 unsigned SrcElt;
1853 if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001854 SrcElt = 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001855 else
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001856 SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001857
Scott Michela59d4692008-02-23 18:41:37 +00001858 for (unsigned j = 0; j < BytesPerElement; ++j) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001859 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
1860 MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001861 }
1862 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001863
Dan Gohman475871a2008-07-27 21:46:04 +00001864 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8,
Scott Michel1a6cdb62008-12-01 17:56:02 +00001865 &ResultMask[0], ResultMask.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001866 return DAG.getNode(SPUISD::SHUFB, V1.getValueType(), V1, V2, VPermMask);
1867 }
1868}
1869
Dan Gohman475871a2008-07-27 21:46:04 +00001870static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1871 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Scott Michel266bc8f2007-12-04 22:23:35 +00001872
Gabor Greifba36cb52008-08-28 21:40:38 +00001873 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001874 // For a constant, build the appropriate constant vector, which will
1875 // eventually simplify to a vector register load.
1876
Gabor Greifba36cb52008-08-28 21:40:38 +00001877 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001878 SmallVector<SDValue, 16> ConstVecValues;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001879 MVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001880 size_t n_copies;
1881
1882 // Create a constant vector:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001883 switch (Op.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001884 default: assert(0 && "Unexpected constant value type in "
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001885 "LowerSCALAR_TO_VECTOR");
Scott Michel266bc8f2007-12-04 22:23:35 +00001886 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1887 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1888 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1889 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1890 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1891 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1892 }
1893
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001894 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001895 for (size_t j = 0; j < n_copies; ++j)
1896 ConstVecValues.push_back(CValue);
1897
1898 return DAG.getNode(ISD::BUILD_VECTOR, Op.getValueType(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001899 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001900 } else {
1901 // Otherwise, copy the value from one register to another:
Duncan Sands83ec4b62008-06-06 12:08:01 +00001902 switch (Op0.getValueType().getSimpleVT()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001903 default: assert(0 && "Unexpected value type in LowerSCALAR_TO_VECTOR");
1904 case MVT::i8:
1905 case MVT::i16:
1906 case MVT::i32:
1907 case MVT::i64:
1908 case MVT::f32:
1909 case MVT::f64:
Scott Michelf0569be2008-12-27 04:51:36 +00001910 return DAG.getNode(SPUISD::PREFSLOT2VEC, Op.getValueType(), Op0, Op0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001911 }
1912 }
1913
Dan Gohman475871a2008-07-27 21:46:04 +00001914 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001915}
1916
Dan Gohman475871a2008-07-27 21:46:04 +00001917static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00001918 MVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001919 SDValue N = Op.getOperand(0);
1920 SDValue Elt = Op.getOperand(1);
Scott Michel7a1c9e92008-11-22 23:50:42 +00001921 SDValue retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00001922
Scott Michel7a1c9e92008-11-22 23:50:42 +00001923 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
1924 // Constant argument:
1925 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001926
Scott Michel7a1c9e92008-11-22 23:50:42 +00001927 // sanity checks:
1928 if (VT == MVT::i8 && EltNo >= 16)
1929 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
1930 else if (VT == MVT::i16 && EltNo >= 8)
1931 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
1932 else if (VT == MVT::i32 && EltNo >= 4)
1933 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
1934 else if (VT == MVT::i64 && EltNo >= 2)
1935 assert(0 && "SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel266bc8f2007-12-04 22:23:35 +00001936
Scott Michel7a1c9e92008-11-22 23:50:42 +00001937 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
1938 // i32 and i64: Element 0 is the preferred slot
Scott Michel104de432008-11-24 17:11:17 +00001939 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT, N);
Scott Michel7a1c9e92008-11-22 23:50:42 +00001940 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001941
Scott Michel7a1c9e92008-11-22 23:50:42 +00001942 // Need to generate shuffle mask and extract:
1943 int prefslot_begin = -1, prefslot_end = -1;
1944 int elt_byte = EltNo * VT.getSizeInBits() / 8;
1945
1946 switch (VT.getSimpleVT()) {
1947 default:
1948 assert(false && "Invalid value type!");
1949 case MVT::i8: {
1950 prefslot_begin = prefslot_end = 3;
1951 break;
1952 }
1953 case MVT::i16: {
1954 prefslot_begin = 2; prefslot_end = 3;
1955 break;
1956 }
1957 case MVT::i32:
1958 case MVT::f32: {
1959 prefslot_begin = 0; prefslot_end = 3;
1960 break;
1961 }
1962 case MVT::i64:
1963 case MVT::f64: {
1964 prefslot_begin = 0; prefslot_end = 7;
1965 break;
1966 }
1967 }
1968
1969 assert(prefslot_begin != -1 && prefslot_end != -1 &&
1970 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
1971
1972 unsigned int ShufBytes[16];
1973 for (int i = 0; i < 16; ++i) {
1974 // zero fill uppper part of preferred slot, don't care about the
1975 // other slots:
1976 unsigned int mask_val;
1977 if (i <= prefslot_end) {
1978 mask_val =
1979 ((i < prefslot_begin)
1980 ? 0x80
1981 : elt_byte + (i - prefslot_begin));
1982
1983 ShufBytes[i] = mask_val;
1984 } else
1985 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
1986 }
1987
1988 SDValue ShufMask[4];
1989 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
Scott Michelcc188272008-12-04 21:01:44 +00001990 unsigned bidx = i * 4;
Scott Michel7a1c9e92008-11-22 23:50:42 +00001991 unsigned int bits = ((ShufBytes[bidx] << 24) |
1992 (ShufBytes[bidx+1] << 16) |
1993 (ShufBytes[bidx+2] << 8) |
1994 ShufBytes[bidx+3]);
1995 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
1996 }
1997
1998 SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
1999 &ShufMask[0],
2000 sizeof(ShufMask) / sizeof(ShufMask[0]));
2001
Scott Michel104de432008-11-24 17:11:17 +00002002 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel7a1c9e92008-11-22 23:50:42 +00002003 DAG.getNode(SPUISD::SHUFB, N.getValueType(),
2004 N, N, ShufMaskVec));
2005 } else {
2006 // Variable index: Rotate the requested element into slot 0, then replicate
2007 // slot 0 across the vector
2008 MVT VecVT = N.getValueType();
2009 if (!VecVT.isSimple() || !VecVT.isVector() || !VecVT.is128BitVector()) {
2010 cerr << "LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit vector type!\n";
2011 abort();
2012 }
2013
2014 // Make life easier by making sure the index is zero-extended to i32
2015 if (Elt.getValueType() != MVT::i32)
2016 Elt = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Elt);
2017
2018 // Scale the index to a bit/byte shift quantity
2019 APInt scaleFactor =
Scott Michel104de432008-11-24 17:11:17 +00002020 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2021 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel7a1c9e92008-11-22 23:50:42 +00002022 SDValue vecShift;
Scott Michel7a1c9e92008-11-22 23:50:42 +00002023
Scott Michel104de432008-11-24 17:11:17 +00002024 if (scaleShift > 0) {
2025 // Scale the shift factor:
Scott Michel7a1c9e92008-11-22 23:50:42 +00002026 Elt = DAG.getNode(ISD::SHL, MVT::i32, Elt,
Scott Michel1a6cdb62008-12-01 17:56:02 +00002027 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel7a1c9e92008-11-22 23:50:42 +00002028 }
2029
Scott Michel104de432008-11-24 17:11:17 +00002030 vecShift = DAG.getNode(SPUISD::SHLQUAD_L_BYTES, VecVT, N, Elt);
2031
2032 // Replicate the bytes starting at byte 0 across the entire vector (for
2033 // consistency with the notion of a unified register set)
Scott Michel7a1c9e92008-11-22 23:50:42 +00002034 SDValue replicate;
2035
2036 switch (VT.getSimpleVT()) {
2037 default:
2038 cerr << "LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector type\n";
2039 abort();
2040 /*NOTREACHED*/
2041 case MVT::i8: {
Scott Michel104de432008-11-24 17:11:17 +00002042 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002043 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2044 factor, factor);
2045 break;
2046 }
2047 case MVT::i16: {
Scott Michel104de432008-11-24 17:11:17 +00002048 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002049 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2050 factor, factor);
2051 break;
2052 }
2053 case MVT::i32:
2054 case MVT::f32: {
2055 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2056 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, factor, factor,
2057 factor, factor);
2058 break;
2059 }
2060 case MVT::i64:
2061 case MVT::f64: {
2062 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2063 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2064 replicate = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, loFactor, hiFactor,
2065 loFactor, hiFactor);
2066 break;
2067 }
2068 }
2069
Scott Michel104de432008-11-24 17:11:17 +00002070 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
Scott Michel1a6cdb62008-12-01 17:56:02 +00002071 DAG.getNode(SPUISD::SHUFB, VecVT,
2072 vecShift, vecShift, replicate));
Scott Michel266bc8f2007-12-04 22:23:35 +00002073 }
2074
Scott Michel7a1c9e92008-11-22 23:50:42 +00002075 return retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00002076}
2077
Dan Gohman475871a2008-07-27 21:46:04 +00002078static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2079 SDValue VecOp = Op.getOperand(0);
2080 SDValue ValOp = Op.getOperand(1);
2081 SDValue IdxOp = Op.getOperand(2);
Duncan Sands83ec4b62008-06-06 12:08:01 +00002082 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002083
2084 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2085 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
2086
Duncan Sands83ec4b62008-06-06 12:08:01 +00002087 MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel1a6cdb62008-12-01 17:56:02 +00002088 // Use $sp ($1) because it's always 16-byte aligned and it's available:
2089 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, PtrVT,
2090 DAG.getRegister(SPU::R1, PtrVT),
2091 DAG.getConstant(CN->getSExtValue(), PtrVT));
2092 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, VT, Pointer);
Scott Michel266bc8f2007-12-04 22:23:35 +00002093
Dan Gohman475871a2008-07-27 21:46:04 +00002094 SDValue result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002095 DAG.getNode(SPUISD::SHUFB, VT,
2096 DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, ValOp),
Scott Michel1df30c42008-12-29 03:23:36 +00002097 VecOp,
Scott Michel19c10e62009-01-26 03:37:41 +00002098 DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, ShufMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002099
2100 return result;
2101}
2102
Scott Michelf0569be2008-12-27 04:51:36 +00002103static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc,
2104 const TargetLowering &TLI)
Scott Michela59d4692008-02-23 18:41:37 +00002105{
Dan Gohman475871a2008-07-27 21:46:04 +00002106 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Scott Michelf0569be2008-12-27 04:51:36 +00002107 MVT ShiftVT = TLI.getShiftAmountTy();
Scott Michel266bc8f2007-12-04 22:23:35 +00002108
2109 assert(Op.getValueType() == MVT::i8);
2110 switch (Opc) {
2111 default:
2112 assert(0 && "Unhandled i8 math operator");
2113 /*NOTREACHED*/
2114 break;
Scott Michel02d711b2008-12-30 23:28:25 +00002115 case ISD::ADD: {
2116 // 8-bit addition: Promote the arguments up to 16-bits and truncate
2117 // the result:
2118 SDValue N1 = Op.getOperand(1);
2119 N0 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0);
2120 N1 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1);
2121 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
2122 DAG.getNode(Opc, MVT::i16, N0, N1));
2123
2124 }
2125
Scott Michel266bc8f2007-12-04 22:23:35 +00002126 case ISD::SUB: {
2127 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2128 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002129 SDValue N1 = Op.getOperand(1);
Scott Michel02d711b2008-12-30 23:28:25 +00002130 N0 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0);
2131 N1 = DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N1);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002132 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002133 DAG.getNode(Opc, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002134 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002135 case ISD::ROTR:
2136 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002137 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002138 unsigned N1Opc;
2139 N0 = (N0.getOpcode() != ISD::Constant
2140 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002141 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2142 MVT::i16));
Scott Michelf0569be2008-12-27 04:51:36 +00002143 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greif93c53e52008-08-31 15:37:04 +00002144 ? ISD::ZERO_EXTEND
2145 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002146 N1 = (N1.getOpcode() != ISD::Constant
Scott Michelf0569be2008-12-27 04:51:36 +00002147 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002148 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michelf0569be2008-12-27 04:51:36 +00002149 TLI.getShiftAmountTy()));
Dan Gohman475871a2008-07-27 21:46:04 +00002150 SDValue ExpandArg =
Scott Michel266bc8f2007-12-04 22:23:35 +00002151 DAG.getNode(ISD::OR, MVT::i16, N0,
2152 DAG.getNode(ISD::SHL, MVT::i16,
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002153 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002154 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002155 DAG.getNode(Opc, MVT::i16, ExpandArg, N1));
2156 }
2157 case ISD::SRL:
2158 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002159 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002160 unsigned N1Opc;
2161 N0 = (N0.getOpcode() != ISD::Constant
2162 ? DAG.getNode(ISD::ZERO_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002163 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
Scott Michelf0569be2008-12-27 04:51:36 +00002164 MVT::i32));
2165 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greif93c53e52008-08-31 15:37:04 +00002166 ? ISD::ZERO_EXTEND
2167 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002168 N1 = (N1.getOpcode() != ISD::Constant
Scott Michelf0569be2008-12-27 04:51:36 +00002169 ? DAG.getNode(N1Opc, ShiftVT, N1)
2170 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(), ShiftVT));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002171 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002172 DAG.getNode(Opc, MVT::i16, N0, N1));
2173 }
2174 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002175 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002176 unsigned N1Opc;
2177 N0 = (N0.getOpcode() != ISD::Constant
2178 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Scott Michelf0569be2008-12-27 04:51:36 +00002179 : DAG.getConstant(cast<ConstantSDNode>(N0)->getSExtValue(),
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002180 MVT::i16));
Scott Michelf0569be2008-12-27 04:51:36 +00002181 N1Opc = N1.getValueType().bitsLT(ShiftVT)
Gabor Greif93c53e52008-08-31 15:37:04 +00002182 ? ISD::SIGN_EXTEND
2183 : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002184 N1 = (N1.getOpcode() != ISD::Constant
Scott Michelf0569be2008-12-27 04:51:36 +00002185 ? DAG.getNode(N1Opc, ShiftVT, N1)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002186 : DAG.getConstant(cast<ConstantSDNode>(N1)->getZExtValue(),
Scott Michelf0569be2008-12-27 04:51:36 +00002187 ShiftVT));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002188 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002189 DAG.getNode(Opc, MVT::i16, N0, N1));
2190 }
2191 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002192 SDValue N1 = Op.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002193 unsigned N1Opc;
2194 N0 = (N0.getOpcode() != ISD::Constant
2195 ? DAG.getNode(ISD::SIGN_EXTEND, MVT::i16, N0)
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002196 : DAG.getConstant(cast<ConstantSDNode>(N0)->getZExtValue(),
2197 MVT::i16));
Duncan Sands8e4eb092008-06-08 20:54:56 +00002198 N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
Scott Michel266bc8f2007-12-04 22:23:35 +00002199 N1 = (N1.getOpcode() != ISD::Constant
2200 ? DAG.getNode(N1Opc, MVT::i16, N1)
Scott Michelf0569be2008-12-27 04:51:36 +00002201 : DAG.getConstant(cast<ConstantSDNode>(N1)->getSExtValue(),
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00002202 MVT::i16));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002203 return DAG.getNode(ISD::TRUNCATE, MVT::i8,
Scott Michel266bc8f2007-12-04 22:23:35 +00002204 DAG.getNode(Opc, MVT::i16, N0, N1));
2205 break;
2206 }
2207 }
2208
Dan Gohman475871a2008-07-27 21:46:04 +00002209 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002210}
2211
Scott Michel94bd57e2009-01-15 04:41:47 +00002212//! Generate the carry-generate shuffle mask.
2213SDValue SPU::getCarryGenerateShufMask(SelectionDAG &DAG) {
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002214 SmallVector<SDValue, 16 > ShufBytes;
Scott Michela59d4692008-02-23 18:41:37 +00002215
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002216 // Create the shuffle mask for "rotating" the borrow up one register slot
2217 // once the borrow is generated.
2218 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2219 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2220 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2221 ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
Scott Michela59d4692008-02-23 18:41:37 +00002222
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002223 return DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2224 &ShufBytes[0], ShufBytes.size());
Scott Michel94bd57e2009-01-15 04:41:47 +00002225}
Scott Michela59d4692008-02-23 18:41:37 +00002226
Scott Michel94bd57e2009-01-15 04:41:47 +00002227//! Generate the borrow-generate shuffle mask
2228SDValue SPU::getBorrowGenerateShufMask(SelectionDAG &DAG) {
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002229 SmallVector<SDValue, 16 > ShufBytes;
Scott Michela59d4692008-02-23 18:41:37 +00002230
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002231 // Create the shuffle mask for "rotating" the borrow up one register slot
2232 // once the borrow is generated.
2233 ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2234 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2235 ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2236 ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
Scott Michel045a1452008-11-24 18:20:46 +00002237
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002238 return DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2239 &ShufBytes[0], ShufBytes.size());
Scott Michela59d4692008-02-23 18:41:37 +00002240}
2241
Scott Michel266bc8f2007-12-04 22:23:35 +00002242//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002243static SDValue
2244LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2245 SDValue ConstVec;
2246 SDValue Arg;
Duncan Sands83ec4b62008-06-06 12:08:01 +00002247 MVT VT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002248
2249 ConstVec = Op.getOperand(0);
2250 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002251 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
2252 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002253 ConstVec = ConstVec.getOperand(0);
2254 } else {
2255 ConstVec = Op.getOperand(1);
2256 Arg = Op.getOperand(0);
Gabor Greifba36cb52008-08-28 21:40:38 +00002257 if (ConstVec.getNode()->getOpcode() == ISD::BIT_CONVERT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002258 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002259 }
2260 }
2261 }
2262
Gabor Greifba36cb52008-08-28 21:40:38 +00002263 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002264 uint64_t VectorBits[2];
2265 uint64_t UndefBits[2];
2266 uint64_t SplatBits, SplatUndef;
2267 int SplatSize;
2268
Gabor Greifba36cb52008-08-28 21:40:38 +00002269 if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002270 && isConstantSplat(VectorBits, UndefBits,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002271 VT.getVectorElementType().getSizeInBits(),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002272 SplatBits, SplatUndef, SplatSize)) {
Dan Gohman475871a2008-07-27 21:46:04 +00002273 SDValue tcVec[16];
2274 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002275 const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
2276
2277 // Turn the BUILD_VECTOR into a set of target constants:
2278 for (size_t i = 0; i < tcVecSize; ++i)
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002279 tcVec[i] = tc;
Scott Michel266bc8f2007-12-04 22:23:35 +00002280
Gabor Greifba36cb52008-08-28 21:40:38 +00002281 return DAG.getNode(Op.getNode()->getOpcode(), VT, Arg,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002282 DAG.getNode(ISD::BUILD_VECTOR, VT, tcVec, tcVecSize));
Scott Michel266bc8f2007-12-04 22:23:35 +00002283 }
2284 }
Scott Michel9de57a92009-01-26 22:33:37 +00002285
Nate Begeman24dc3462008-07-29 19:07:27 +00002286 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2287 // lowered. Return the operation, rather than a null SDValue.
2288 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002289}
2290
Scott Michel266bc8f2007-12-04 22:23:35 +00002291//! Custom lowering for CTPOP (count population)
2292/*!
2293 Custom lowering code that counts the number ones in the input
2294 operand. SPU has such an instruction, but it counts the number of
2295 ones per byte, which then have to be accumulated.
2296*/
Dan Gohman475871a2008-07-27 21:46:04 +00002297static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002298 MVT VT = Op.getValueType();
2299 MVT vecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002300
Duncan Sands83ec4b62008-06-06 12:08:01 +00002301 switch (VT.getSimpleVT()) {
2302 default:
2303 assert(false && "Invalid value type!");
Scott Michel266bc8f2007-12-04 22:23:35 +00002304 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002305 SDValue N = Op.getOperand(0);
2306 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002307
Scott Michelf0569be2008-12-27 04:51:36 +00002308 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman475871a2008-07-27 21:46:04 +00002309 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002310
2311 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i8, CNTB, Elt0);
2312 }
2313
2314 case MVT::i16: {
2315 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002316 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002317
Chris Lattner84bc5422007-12-31 04:13:23 +00002318 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002319
Dan Gohman475871a2008-07-27 21:46:04 +00002320 SDValue N = Op.getOperand(0);
2321 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2322 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
Duncan Sandsfa7935f2008-10-30 19:24:28 +00002323 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002324
Scott Michelf0569be2008-12-27 04:51:36 +00002325 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman475871a2008-07-27 21:46:04 +00002326 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002327
2328 // CNTB_result becomes the chain to which all of the virtual registers
2329 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002330 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002331 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002332
Dan Gohman475871a2008-07-27 21:46:04 +00002333 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002334 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2335
Dan Gohman475871a2008-07-27 21:46:04 +00002336 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002337
2338 return DAG.getNode(ISD::AND, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002339 DAG.getNode(ISD::ADD, MVT::i16,
2340 DAG.getNode(ISD::SRL, MVT::i16,
2341 Tmp1, Shift1),
2342 Tmp1),
2343 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002344 }
2345
2346 case MVT::i32: {
2347 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002348 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002349
Chris Lattner84bc5422007-12-31 04:13:23 +00002350 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2351 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002352
Dan Gohman475871a2008-07-27 21:46:04 +00002353 SDValue N = Op.getOperand(0);
2354 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2355 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2356 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2357 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002358
Scott Michelf0569be2008-12-27 04:51:36 +00002359 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, vecVT, N, N);
Dan Gohman475871a2008-07-27 21:46:04 +00002360 SDValue CNTB = DAG.getNode(SPUISD::CNTB, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002361
2362 // CNTB_result becomes the chain to which all of the virtual registers
2363 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002364 SDValue CNTB_result =
Scott Michel266bc8f2007-12-04 22:23:35 +00002365 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002366
Dan Gohman475871a2008-07-27 21:46:04 +00002367 SDValue CNTB_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002368 DAG.getCopyToReg(CNTB_result, CNTB_reg, CNTB_result);
2369
Dan Gohman475871a2008-07-27 21:46:04 +00002370 SDValue Comp1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002371 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002372 DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32), Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002373
Dan Gohman475871a2008-07-27 21:46:04 +00002374 SDValue Sum1 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002375 DAG.getNode(ISD::ADD, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002376 Comp1, DAG.getCopyFromReg(CNTB_rescopy, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002377
Dan Gohman475871a2008-07-27 21:46:04 +00002378 SDValue Sum1_rescopy =
Scott Michel266bc8f2007-12-04 22:23:35 +00002379 DAG.getCopyToReg(CNTB_result, SUM1_reg, Sum1);
2380
Dan Gohman475871a2008-07-27 21:46:04 +00002381 SDValue Comp2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002382 DAG.getNode(ISD::SRL, MVT::i32,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002383 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32),
2384 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002385 SDValue Sum2 =
Scott Michel266bc8f2007-12-04 22:23:35 +00002386 DAG.getNode(ISD::ADD, MVT::i32, Comp2,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002387 DAG.getCopyFromReg(Sum1_rescopy, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002388
2389 return DAG.getNode(ISD::AND, MVT::i32, Sum2, Mask0);
2390 }
2391
2392 case MVT::i64:
2393 break;
2394 }
2395
Dan Gohman475871a2008-07-27 21:46:04 +00002396 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002397}
2398
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002399//! Lower ISD::FP_TO_SINT, ISD::FP_TO_UINT for i32
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002400/*!
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002401 f32->i32 passes through unchanged, whereas f64->i32 expands to a libcall.
2402 All conversions to i64 are expanded to a libcall.
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002403 */
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002404static SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG,
2405 SPUTargetLowering &TLI) {
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002406 MVT OpVT = Op.getValueType();
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002407 SDValue Op0 = Op.getOperand(0);
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002408 MVT Op0VT = Op0.getValueType();
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002409
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002410 if ((OpVT == MVT::i32 && Op0VT == MVT::f64)
2411 || OpVT == MVT::i64) {
2412 // Convert f32 / f64 to i32 / i64 via libcall.
2413 RTLIB::Libcall LC =
2414 (Op.getOpcode() == ISD::FP_TO_SINT)
2415 ? RTLIB::getFPTOSINT(Op0VT, OpVT)
2416 : RTLIB::getFPTOUINT(Op0VT, OpVT);
2417 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpectd fp-to-int conversion!");
2418 SDValue Dummy;
2419 return ExpandLibCall(LC, Op, DAG, false, Dummy, TLI);
2420 }
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002421
Scott Michel9de57a92009-01-26 22:33:37 +00002422 return Op; // return unmolested, legalized op
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002423}
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002424
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002425//! Lower ISD::SINT_TO_FP, ISD::UINT_TO_FP for i32
2426/*!
2427 i32->f32 passes through unchanged, whereas i32->f64 is expanded to a libcall.
2428 All conversions from i64 are expanded to a libcall.
2429 */
2430static SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG,
2431 SPUTargetLowering &TLI) {
2432 MVT OpVT = Op.getValueType();
2433 SDValue Op0 = Op.getOperand(0);
2434 MVT Op0VT = Op0.getValueType();
2435
2436 if ((OpVT == MVT::f64 && Op0VT == MVT::i32)
2437 || Op0VT == MVT::i64) {
2438 // Convert i32, i64 to f64 via libcall:
2439 RTLIB::Libcall LC =
2440 (Op.getOpcode() == ISD::SINT_TO_FP)
2441 ? RTLIB::getSINTTOFP(Op0VT, OpVT)
2442 : RTLIB::getUINTTOFP(Op0VT, OpVT);
2443 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpectd int-to-fp conversion!");
2444 SDValue Dummy;
2445 return ExpandLibCall(LC, Op, DAG, false, Dummy, TLI);
2446 }
2447
Scott Michel9de57a92009-01-26 22:33:37 +00002448 return Op; // return unmolested, legalized
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002449}
2450
2451//! Lower ISD::SETCC
2452/*!
2453 This handles MVT::f64 (double floating point) condition lowering
2454 */
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002455static SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG,
2456 const TargetLowering &TLI) {
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002457 CondCodeSDNode *CC = dyn_cast<CondCodeSDNode>(Op.getOperand(2));
2458 assert(CC != 0 && "LowerSETCC: CondCodeSDNode should not be null here!\n");
2459
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002460 SDValue lhs = Op.getOperand(0);
2461 SDValue rhs = Op.getOperand(1);
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002462 MVT lhsVT = lhs.getValueType();
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002463 assert(lhsVT == MVT::f64 && "LowerSETCC: type other than MVT::64\n");
2464
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002465 MVT ccResultVT = TLI.getSetCCResultType(lhs.getValueType());
2466 APInt ccResultOnes = APInt::getAllOnesValue(ccResultVT.getSizeInBits());
2467 MVT IntVT(MVT::i64);
2468
2469 // Take advantage of the fact that (truncate (sra arg, 32)) is efficiently
2470 // selected to a NOP:
2471 SDValue i64lhs = DAG.getNode(ISD::BIT_CONVERT, IntVT, lhs);
2472 SDValue lhsHi32 =
2473 DAG.getNode(ISD::TRUNCATE, MVT::i32,
2474 DAG.getNode(ISD::SRL, IntVT,
2475 i64lhs, DAG.getConstant(32, MVT::i32)));
2476 SDValue lhsHi32abs =
2477 DAG.getNode(ISD::AND, MVT::i32,
2478 lhsHi32, DAG.getConstant(0x7fffffff, MVT::i32));
2479 SDValue lhsLo32 =
2480 DAG.getNode(ISD::TRUNCATE, MVT::i32, i64lhs);
2481
2482 // SETO and SETUO only use the lhs operand:
2483 if (CC->get() == ISD::SETO) {
2484 // Evaluates to true if Op0 is not [SQ]NaN - lowers to the inverse of
2485 // SETUO
2486 APInt ccResultAllOnes = APInt::getAllOnesValue(ccResultVT.getSizeInBits());
2487 return DAG.getNode(ISD::XOR, ccResultVT,
2488 DAG.getSetCC(ccResultVT,
2489 lhs, DAG.getConstantFP(0.0, lhsVT),
2490 ISD::SETUO),
2491 DAG.getConstant(ccResultAllOnes, ccResultVT));
2492 } else if (CC->get() == ISD::SETUO) {
2493 // Evaluates to true if Op0 is [SQ]NaN
2494 return DAG.getNode(ISD::AND, ccResultVT,
2495 DAG.getSetCC(ccResultVT,
2496 lhsHi32abs,
2497 DAG.getConstant(0x7ff00000, MVT::i32),
2498 ISD::SETGE),
2499 DAG.getSetCC(ccResultVT,
2500 lhsLo32,
2501 DAG.getConstant(0, MVT::i32),
2502 ISD::SETGT));
2503 }
2504
2505 SDValue i64rhs = DAG.getNode(ISD::BIT_CONVERT, IntVT, rhs);
2506 SDValue rhsHi32 =
2507 DAG.getNode(ISD::TRUNCATE, MVT::i32,
2508 DAG.getNode(ISD::SRL, IntVT,
2509 i64rhs, DAG.getConstant(32, MVT::i32)));
2510
2511 // If a value is negative, subtract from the sign magnitude constant:
2512 SDValue signMag2TC = DAG.getConstant(0x8000000000000000ULL, IntVT);
2513
2514 // Convert the sign-magnitude representation into 2's complement:
2515 SDValue lhsSelectMask = DAG.getNode(ISD::SRA, ccResultVT,
2516 lhsHi32, DAG.getConstant(31, MVT::i32));
2517 SDValue lhsSignMag2TC = DAG.getNode(ISD::SUB, IntVT, signMag2TC, i64lhs);
2518 SDValue lhsSelect =
2519 DAG.getNode(ISD::SELECT, IntVT,
2520 lhsSelectMask, lhsSignMag2TC, i64lhs);
2521
2522 SDValue rhsSelectMask = DAG.getNode(ISD::SRA, ccResultVT,
2523 rhsHi32, DAG.getConstant(31, MVT::i32));
2524 SDValue rhsSignMag2TC = DAG.getNode(ISD::SUB, IntVT, signMag2TC, i64rhs);
2525 SDValue rhsSelect =
2526 DAG.getNode(ISD::SELECT, IntVT,
2527 rhsSelectMask, rhsSignMag2TC, i64rhs);
2528
2529 unsigned compareOp;
2530
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002531 switch (CC->get()) {
2532 case ISD::SETOEQ:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002533 case ISD::SETUEQ:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002534 compareOp = ISD::SETEQ; break;
2535 case ISD::SETOGT:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002536 case ISD::SETUGT:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002537 compareOp = ISD::SETGT; break;
2538 case ISD::SETOGE:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002539 case ISD::SETUGE:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002540 compareOp = ISD::SETGE; break;
2541 case ISD::SETOLT:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002542 case ISD::SETULT:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002543 compareOp = ISD::SETLT; break;
2544 case ISD::SETOLE:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002545 case ISD::SETULE:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002546 compareOp = ISD::SETLE; break;
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002547 case ISD::SETUNE:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002548 case ISD::SETONE:
2549 compareOp = ISD::SETNE; break;
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002550 default:
2551 cerr << "CellSPU ISel Select: unimplemented f64 condition\n";
2552 abort();
2553 break;
2554 }
2555
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002556 SDValue result =
2557 DAG.getSetCC(ccResultVT, lhsSelect, rhsSelect, (ISD::CondCode) compareOp);
2558
2559 if ((CC->get() & 0x8) == 0) {
2560 // Ordered comparison:
2561 SDValue lhsNaN = DAG.getSetCC(ccResultVT,
2562 lhs, DAG.getConstantFP(0.0, MVT::f64),
2563 ISD::SETO);
2564 SDValue rhsNaN = DAG.getSetCC(ccResultVT,
2565 rhs, DAG.getConstantFP(0.0, MVT::f64),
2566 ISD::SETO);
2567 SDValue ordered = DAG.getNode(ISD::AND, ccResultVT, lhsNaN, rhsNaN);
2568
2569 result = DAG.getNode(ISD::AND, ccResultVT, ordered, result);
2570 }
2571
2572 return result;
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002573}
2574
Scott Michel7a1c9e92008-11-22 23:50:42 +00002575//! Lower ISD::SELECT_CC
2576/*!
2577 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2578 SELB instruction.
2579
2580 \note Need to revisit this in the future: if the code path through the true
2581 and false value computations is longer than the latency of a branch (6
2582 cycles), then it would be more advantageous to branch and insert a new basic
2583 block and branch on the condition. However, this code does not make that
2584 assumption, given the simplisitc uses so far.
2585 */
2586
Scott Michelf0569be2008-12-27 04:51:36 +00002587static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
2588 const TargetLowering &TLI) {
Scott Michel7a1c9e92008-11-22 23:50:42 +00002589 MVT VT = Op.getValueType();
2590 SDValue lhs = Op.getOperand(0);
2591 SDValue rhs = Op.getOperand(1);
2592 SDValue trueval = Op.getOperand(2);
2593 SDValue falseval = Op.getOperand(3);
2594 SDValue condition = Op.getOperand(4);
2595
Scott Michelf0569be2008-12-27 04:51:36 +00002596 // NOTE: SELB's arguments: $rA, $rB, $mask
2597 //
2598 // SELB selects bits from $rA where bits in $mask are 0, bits from $rB
2599 // where bits in $mask are 1. CCond will be inverted, having 1s where the
2600 // condition was true and 0s where the condition was false. Hence, the
2601 // arguments to SELB get reversed.
2602
Scott Michel7a1c9e92008-11-22 23:50:42 +00002603 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2604 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2605 // with another "cannot select select_cc" assert:
2606
Duncan Sands5480c042009-01-01 15:52:00 +00002607 SDValue compare = DAG.getNode(ISD::SETCC,
2608 TLI.getSetCCResultType(Op.getValueType()),
Scott Michelf0569be2008-12-27 04:51:36 +00002609 lhs, rhs, condition);
2610 return DAG.getNode(SPUISD::SELB, VT, falseval, trueval, compare);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002611}
2612
Scott Michelb30e8f62008-12-02 19:53:53 +00002613//! Custom lower ISD::TRUNCATE
2614static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
2615{
2616 MVT VT = Op.getValueType();
2617 MVT::SimpleValueType simpleVT = VT.getSimpleVT();
2618 MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
2619
2620 SDValue Op0 = Op.getOperand(0);
2621 MVT Op0VT = Op0.getValueType();
2622 MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
2623
Scott Michelf0569be2008-12-27 04:51:36 +00002624 if (Op0VT.getSimpleVT() == MVT::i128 && simpleVT == MVT::i64) {
Scott Michel52d00012009-01-03 00:27:53 +00002625 // Create shuffle mask, least significant doubleword of quadword
Scott Michelf0569be2008-12-27 04:51:36 +00002626 unsigned maskHigh = 0x08090a0b;
2627 unsigned maskLow = 0x0c0d0e0f;
2628 // Use a shuffle to perform the truncation
2629 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
2630 DAG.getConstant(maskHigh, MVT::i32),
2631 DAG.getConstant(maskLow, MVT::i32),
2632 DAG.getConstant(maskHigh, MVT::i32),
2633 DAG.getConstant(maskLow, MVT::i32));
2634
2635
2636 SDValue PromoteScalar = DAG.getNode(SPUISD::PREFSLOT2VEC, Op0VecVT, Op0);
2637
2638 SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, Op0VecVT,
2639 PromoteScalar, PromoteScalar, shufMask);
2640
2641 return DAG.getNode(SPUISD::VEC2PREFSLOT, VT,
2642 DAG.getNode(ISD::BIT_CONVERT, VecVT, truncShuffle));
Scott Michelb30e8f62008-12-02 19:53:53 +00002643 }
2644
Scott Michelf0569be2008-12-27 04:51:36 +00002645 return SDValue(); // Leave the truncate unmolested
Scott Michelb30e8f62008-12-02 19:53:53 +00002646}
2647
Scott Michel7a1c9e92008-11-22 23:50:42 +00002648//! Custom (target-specific) lowering entry point
2649/*!
2650 This is where LLVM's DAG selection process calls to do target-specific
2651 lowering of nodes.
2652 */
Dan Gohman475871a2008-07-27 21:46:04 +00002653SDValue
2654SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
Scott Michel266bc8f2007-12-04 22:23:35 +00002655{
Scott Michela59d4692008-02-23 18:41:37 +00002656 unsigned Opc = (unsigned) Op.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +00002657 MVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002658
2659 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002660 default: {
2661 cerr << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
Scott Michela59d4692008-02-23 18:41:37 +00002662 cerr << "Op.getOpcode() = " << Opc << "\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002663 cerr << "*Op.getNode():\n";
2664 Op.getNode()->dump();
Scott Michel266bc8f2007-12-04 22:23:35 +00002665 abort();
2666 }
2667 case ISD::LOAD:
Scott Michelb30e8f62008-12-02 19:53:53 +00002668 case ISD::EXTLOAD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002669 case ISD::SEXTLOAD:
2670 case ISD::ZEXTLOAD:
2671 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2672 case ISD::STORE:
2673 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2674 case ISD::ConstantPool:
2675 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2676 case ISD::GlobalAddress:
2677 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2678 case ISD::JumpTable:
2679 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002680 case ISD::ConstantFP:
2681 return LowerConstantFP(Op, DAG);
2682 case ISD::FORMAL_ARGUMENTS:
Scott Michel58c58182008-01-17 20:38:41 +00002683 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Scott Michel266bc8f2007-12-04 22:23:35 +00002684 case ISD::CALL:
Scott Michel9de5d0d2008-01-11 02:53:15 +00002685 return LowerCALL(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002686 case ISD::RET:
2687 return LowerRET(Op, DAG, getTargetMachine());
2688
Scott Michel02d711b2008-12-30 23:28:25 +00002689 // i8, i64 math ops:
Scott Michel8bf61e82008-06-02 22:18:03 +00002690 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002691 case ISD::SUB:
2692 case ISD::ROTR:
2693 case ISD::ROTL:
2694 case ISD::SRL:
2695 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002696 case ISD::SRA: {
Scott Michela59d4692008-02-23 18:41:37 +00002697 if (VT == MVT::i8)
Scott Michelf0569be2008-12-27 04:51:36 +00002698 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michela59d4692008-02-23 18:41:37 +00002699 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002700 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002701
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002702 case ISD::FP_TO_SINT:
2703 case ISD::FP_TO_UINT:
2704 return LowerFP_TO_INT(Op, DAG, *this);
2705
2706 case ISD::SINT_TO_FP:
2707 case ISD::UINT_TO_FP:
2708 return LowerINT_TO_FP(Op, DAG, *this);
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002709
Scott Michel266bc8f2007-12-04 22:23:35 +00002710 // Vector-related lowering.
2711 case ISD::BUILD_VECTOR:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002712 return LowerBUILD_VECTOR(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002713 case ISD::SCALAR_TO_VECTOR:
2714 return LowerSCALAR_TO_VECTOR(Op, DAG);
2715 case ISD::VECTOR_SHUFFLE:
2716 return LowerVECTOR_SHUFFLE(Op, DAG);
2717 case ISD::EXTRACT_VECTOR_ELT:
2718 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2719 case ISD::INSERT_VECTOR_ELT:
2720 return LowerINSERT_VECTOR_ELT(Op, DAG);
2721
2722 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2723 case ISD::AND:
2724 case ISD::OR:
2725 case ISD::XOR:
2726 return LowerByteImmed(Op, DAG);
2727
2728 // Vector and i8 multiply:
2729 case ISD::MUL:
Scott Michel02d711b2008-12-30 23:28:25 +00002730 if (VT == MVT::i8)
Scott Michelf0569be2008-12-27 04:51:36 +00002731 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michel266bc8f2007-12-04 22:23:35 +00002732
Scott Michel266bc8f2007-12-04 22:23:35 +00002733 case ISD::CTPOP:
2734 return LowerCTPOP(Op, DAG);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002735
2736 case ISD::SELECT_CC:
Scott Michelf0569be2008-12-27 04:51:36 +00002737 return LowerSELECT_CC(Op, DAG, *this);
Scott Michelb30e8f62008-12-02 19:53:53 +00002738
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002739 case ISD::SETCC:
2740 return LowerSETCC(Op, DAG, *this);
2741
Scott Michelb30e8f62008-12-02 19:53:53 +00002742 case ISD::TRUNCATE:
2743 return LowerTRUNCATE(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002744 }
2745
Dan Gohman475871a2008-07-27 21:46:04 +00002746 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002747}
2748
Duncan Sands1607f052008-12-01 11:39:25 +00002749void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
2750 SmallVectorImpl<SDValue>&Results,
2751 SelectionDAG &DAG)
Scott Michel73ce1c52008-11-10 23:43:06 +00002752{
2753#if 0
2754 unsigned Opc = (unsigned) N->getOpcode();
2755 MVT OpVT = N->getValueType(0);
2756
2757 switch (Opc) {
2758 default: {
2759 cerr << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2760 cerr << "Op.getOpcode() = " << Opc << "\n";
2761 cerr << "*Op.getNode():\n";
2762 N->dump();
2763 abort();
2764 /*NOTREACHED*/
2765 }
2766 }
2767#endif
2768
2769 /* Otherwise, return unchanged */
Scott Michel73ce1c52008-11-10 23:43:06 +00002770}
2771
Scott Michel266bc8f2007-12-04 22:23:35 +00002772//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002773// Target Optimization Hooks
2774//===----------------------------------------------------------------------===//
2775
Dan Gohman475871a2008-07-27 21:46:04 +00002776SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002777SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2778{
2779#if 0
2780 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002781#endif
2782 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002783 SelectionDAG &DAG = DCI.DAG;
Scott Michel1a6cdb62008-12-01 17:56:02 +00002784 SDValue Op0 = N->getOperand(0); // everything has at least one operand
2785 MVT NodeVT = N->getValueType(0); // The node's value type
Scott Michelf0569be2008-12-27 04:51:36 +00002786 MVT Op0VT = Op0.getValueType(); // The first operand's result
Scott Michel1a6cdb62008-12-01 17:56:02 +00002787 SDValue Result; // Initially, empty result
Scott Michel266bc8f2007-12-04 22:23:35 +00002788
2789 switch (N->getOpcode()) {
2790 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002791 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002792 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002793
Scott Michelf0569be2008-12-27 04:51:36 +00002794 if (Op0.getOpcode() == SPUISD::IndirectAddr
2795 || Op1.getOpcode() == SPUISD::IndirectAddr) {
2796 // Normalize the operands to reduce repeated code
2797 SDValue IndirectArg = Op0, AddArg = Op1;
Scott Michel1df30c42008-12-29 03:23:36 +00002798
Scott Michelf0569be2008-12-27 04:51:36 +00002799 if (Op1.getOpcode() == SPUISD::IndirectAddr) {
2800 IndirectArg = Op1;
2801 AddArg = Op0;
2802 }
2803
2804 if (isa<ConstantSDNode>(AddArg)) {
2805 ConstantSDNode *CN0 = cast<ConstantSDNode > (AddArg);
2806 SDValue IndOp1 = IndirectArg.getOperand(1);
2807
2808 if (CN0->isNullValue()) {
2809 // (add (SPUindirect <arg>, <arg>), 0) ->
2810 // (SPUindirect <arg>, <arg>)
Scott Michel053c1da2008-01-29 02:16:57 +00002811
Scott Michel23f2ff72008-12-04 17:16:59 +00002812#if !defined(NDEBUG)
Scott Michelf0569be2008-12-27 04:51:36 +00002813 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel30ee7df2008-12-04 03:02:42 +00002814 cerr << "\n"
Scott Michelf0569be2008-12-27 04:51:36 +00002815 << "Replace: (add (SPUindirect <arg>, <arg>), 0)\n"
2816 << "With: (SPUindirect <arg>, <arg>)\n";
2817 }
Scott Michel30ee7df2008-12-04 03:02:42 +00002818#endif
2819
Scott Michelf0569be2008-12-27 04:51:36 +00002820 return IndirectArg;
2821 } else if (isa<ConstantSDNode>(IndOp1)) {
2822 // (add (SPUindirect <arg>, <const>), <const>) ->
2823 // (SPUindirect <arg>, <const + const>)
2824 ConstantSDNode *CN1 = cast<ConstantSDNode > (IndOp1);
2825 int64_t combinedConst = CN0->getSExtValue() + CN1->getSExtValue();
2826 SDValue combinedValue = DAG.getConstant(combinedConst, Op0VT);
Scott Michel053c1da2008-01-29 02:16:57 +00002827
Scott Michelf0569be2008-12-27 04:51:36 +00002828#if !defined(NDEBUG)
2829 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
2830 cerr << "\n"
2831 << "Replace: (add (SPUindirect <arg>, " << CN1->getSExtValue()
2832 << "), " << CN0->getSExtValue() << ")\n"
2833 << "With: (SPUindirect <arg>, "
2834 << combinedConst << ")\n";
2835 }
2836#endif
Scott Michel053c1da2008-01-29 02:16:57 +00002837
Scott Michelf0569be2008-12-27 04:51:36 +00002838 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
2839 IndirectArg, combinedValue);
2840 }
Scott Michel053c1da2008-01-29 02:16:57 +00002841 }
2842 }
Scott Michela59d4692008-02-23 18:41:37 +00002843 break;
2844 }
2845 case ISD::SIGN_EXTEND:
2846 case ISD::ZERO_EXTEND:
2847 case ISD::ANY_EXTEND: {
Scott Michel1a6cdb62008-12-01 17:56:02 +00002848 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
Scott Michela59d4692008-02-23 18:41:37 +00002849 // (any_extend (SPUextract_elt0 <arg>)) ->
2850 // (SPUextract_elt0 <arg>)
2851 // Types must match, however...
Scott Michel23f2ff72008-12-04 17:16:59 +00002852#if !defined(NDEBUG)
2853 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Scott Michel30ee7df2008-12-04 03:02:42 +00002854 cerr << "\nReplace: ";
2855 N->dump(&DAG);
2856 cerr << "\nWith: ";
2857 Op0.getNode()->dump(&DAG);
2858 cerr << "\n";
Scott Michel23f2ff72008-12-04 17:16:59 +00002859 }
Scott Michel30ee7df2008-12-04 03:02:42 +00002860#endif
Scott Michela59d4692008-02-23 18:41:37 +00002861
2862 return Op0;
2863 }
2864 break;
2865 }
2866 case SPUISD::IndirectAddr: {
2867 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002868 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1));
2869 if (CN != 0 && CN->getZExtValue() == 0) {
Scott Michela59d4692008-02-23 18:41:37 +00002870 // (SPUindirect (SPUaform <addr>, 0), 0) ->
2871 // (SPUaform <addr>, 0)
2872
2873 DEBUG(cerr << "Replace: ");
2874 DEBUG(N->dump(&DAG));
2875 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002876 DEBUG(Op0.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002877 DEBUG(cerr << "\n");
2878
2879 return Op0;
2880 }
Scott Michelf0569be2008-12-27 04:51:36 +00002881 } else if (Op0.getOpcode() == ISD::ADD) {
2882 SDValue Op1 = N->getOperand(1);
2883 if (ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(Op1)) {
2884 // (SPUindirect (add <arg>, <arg>), 0) ->
2885 // (SPUindirect <arg>, <arg>)
2886 if (CN1->isNullValue()) {
2887
2888#if !defined(NDEBUG)
2889 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
2890 cerr << "\n"
2891 << "Replace: (SPUindirect (add <arg>, <arg>), 0)\n"
2892 << "With: (SPUindirect <arg>, <arg>)\n";
2893 }
2894#endif
2895
2896 return DAG.getNode(SPUISD::IndirectAddr, Op0VT,
2897 Op0.getOperand(0), Op0.getOperand(1));
2898 }
2899 }
Scott Michela59d4692008-02-23 18:41:37 +00002900 }
2901 break;
2902 }
2903 case SPUISD::SHLQUAD_L_BITS:
2904 case SPUISD::SHLQUAD_L_BYTES:
2905 case SPUISD::VEC_SHL:
2906 case SPUISD::VEC_SRL:
2907 case SPUISD::VEC_SRA:
Scott Michelf0569be2008-12-27 04:51:36 +00002908 case SPUISD::ROTBYTES_LEFT: {
Dan Gohman475871a2008-07-27 21:46:04 +00002909 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00002910
Scott Michelf0569be2008-12-27 04:51:36 +00002911 // Kill degenerate vector shifts:
2912 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1)) {
2913 if (CN->isNullValue()) {
Scott Michela59d4692008-02-23 18:41:37 +00002914 Result = Op0;
2915 }
2916 }
2917 break;
2918 }
Scott Michelf0569be2008-12-27 04:51:36 +00002919 case SPUISD::PREFSLOT2VEC: {
Scott Michela59d4692008-02-23 18:41:37 +00002920 switch (Op0.getOpcode()) {
2921 default:
2922 break;
2923 case ISD::ANY_EXTEND:
2924 case ISD::ZERO_EXTEND:
2925 case ISD::SIGN_EXTEND: {
Scott Michel1df30c42008-12-29 03:23:36 +00002926 // (SPUprefslot2vec (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
Scott Michela59d4692008-02-23 18:41:37 +00002927 // <arg>
Scott Michel1df30c42008-12-29 03:23:36 +00002928 // but only if the SPUprefslot2vec and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00002929 SDValue Op00 = Op0.getOperand(0);
Scott Michel104de432008-11-24 17:11:17 +00002930 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman475871a2008-07-27 21:46:04 +00002931 SDValue Op000 = Op00.getOperand(0);
Scott Michel1a6cdb62008-12-01 17:56:02 +00002932 if (Op000.getValueType() == NodeVT) {
Scott Michela59d4692008-02-23 18:41:37 +00002933 Result = Op000;
2934 }
2935 }
2936 break;
2937 }
Scott Michel104de432008-11-24 17:11:17 +00002938 case SPUISD::VEC2PREFSLOT: {
Scott Michel1df30c42008-12-29 03:23:36 +00002939 // (SPUprefslot2vec (SPUvec2prefslot <arg>)) ->
Scott Michela59d4692008-02-23 18:41:37 +00002940 // <arg>
2941 Result = Op0.getOperand(0);
2942 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002943 }
Scott Michela59d4692008-02-23 18:41:37 +00002944 }
2945 break;
Scott Michel053c1da2008-01-29 02:16:57 +00002946 }
2947 }
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002948
Scott Michel58c58182008-01-17 20:38:41 +00002949 // Otherwise, return unchanged.
Scott Michel1a6cdb62008-12-01 17:56:02 +00002950#ifndef NDEBUG
Gabor Greifba36cb52008-08-28 21:40:38 +00002951 if (Result.getNode()) {
Scott Michela59d4692008-02-23 18:41:37 +00002952 DEBUG(cerr << "\nReplace.SPU: ");
2953 DEBUG(N->dump(&DAG));
2954 DEBUG(cerr << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00002955 DEBUG(Result.getNode()->dump(&DAG));
Scott Michela59d4692008-02-23 18:41:37 +00002956 DEBUG(cerr << "\n");
2957 }
2958#endif
2959
2960 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00002961}
2962
2963//===----------------------------------------------------------------------===//
2964// Inline Assembly Support
2965//===----------------------------------------------------------------------===//
2966
2967/// getConstraintType - Given a constraint letter, return the type of
2968/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00002969SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00002970SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
2971 if (ConstraintLetter.size() == 1) {
2972 switch (ConstraintLetter[0]) {
2973 default: break;
2974 case 'b':
2975 case 'r':
2976 case 'f':
2977 case 'v':
2978 case 'y':
2979 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00002980 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002981 }
2982 return TargetLowering::getConstraintType(ConstraintLetter);
2983}
2984
Scott Michel5af8f0e2008-07-16 17:17:29 +00002985std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00002986SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Duncan Sands83ec4b62008-06-06 12:08:01 +00002987 MVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002988{
2989 if (Constraint.size() == 1) {
2990 // GCC RS6000 Constraint Letters
2991 switch (Constraint[0]) {
2992 case 'b': // R1-R31
2993 case 'r': // R0-R31
2994 if (VT == MVT::i64)
2995 return std::make_pair(0U, SPU::R64CRegisterClass);
2996 return std::make_pair(0U, SPU::R32CRegisterClass);
2997 case 'f':
2998 if (VT == MVT::f32)
2999 return std::make_pair(0U, SPU::R32FPRegisterClass);
3000 else if (VT == MVT::f64)
3001 return std::make_pair(0U, SPU::R64FPRegisterClass);
3002 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003003 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00003004 return std::make_pair(0U, SPU::GPRCRegisterClass);
3005 }
3006 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003007
Scott Michel266bc8f2007-12-04 22:23:35 +00003008 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3009}
3010
Scott Michela59d4692008-02-23 18:41:37 +00003011//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00003012void
Dan Gohman475871a2008-07-27 21:46:04 +00003013SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00003014 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00003015 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00003016 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00003017 const SelectionDAG &DAG,
3018 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00003019#if 0
Scott Michela59d4692008-02-23 18:41:37 +00003020 const uint64_t uint64_sizebits = sizeof(uint64_t) * 8;
3021
3022 switch (Op.getOpcode()) {
3023 default:
3024 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3025 break;
Scott Michela59d4692008-02-23 18:41:37 +00003026 case CALL:
3027 case SHUFB:
Scott Michel7a1c9e92008-11-22 23:50:42 +00003028 case SHUFFLE_MASK:
Scott Michela59d4692008-02-23 18:41:37 +00003029 case CNTB:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00003030 case SPUISD::PREFSLOT2VEC:
Scott Michela59d4692008-02-23 18:41:37 +00003031 case SPUISD::LDRESULT:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00003032 case SPUISD::VEC2PREFSLOT:
Scott Michel203b2d62008-04-30 00:30:08 +00003033 case SPUISD::SHLQUAD_L_BITS:
3034 case SPUISD::SHLQUAD_L_BYTES:
3035 case SPUISD::VEC_SHL:
3036 case SPUISD::VEC_SRL:
3037 case SPUISD::VEC_SRA:
3038 case SPUISD::VEC_ROTL:
3039 case SPUISD::VEC_ROTR:
Scott Michel203b2d62008-04-30 00:30:08 +00003040 case SPUISD::ROTBYTES_LEFT:
Scott Michel8bf61e82008-06-02 22:18:03 +00003041 case SPUISD::SELECT_MASK:
3042 case SPUISD::SELB:
Scott Michela59d4692008-02-23 18:41:37 +00003043 }
Scott Micheld1e8d9c2009-01-21 04:58:48 +00003044#endif
Scott Michel266bc8f2007-12-04 22:23:35 +00003045}
Scott Michel02d711b2008-12-30 23:28:25 +00003046
Scott Michelf0569be2008-12-27 04:51:36 +00003047unsigned
3048SPUTargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op,
3049 unsigned Depth) const {
3050 switch (Op.getOpcode()) {
3051 default:
3052 return 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00003053
Scott Michelf0569be2008-12-27 04:51:36 +00003054 case ISD::SETCC: {
3055 MVT VT = Op.getValueType();
3056
3057 if (VT != MVT::i8 && VT != MVT::i16 && VT != MVT::i32) {
3058 VT = MVT::i32;
3059 }
3060 return VT.getSizeInBits();
3061 }
3062 }
3063}
Scott Michel1df30c42008-12-29 03:23:36 +00003064
Scott Michel203b2d62008-04-30 00:30:08 +00003065// LowerAsmOperandForConstraint
3066void
Dan Gohman475871a2008-07-27 21:46:04 +00003067SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Scott Michel203b2d62008-04-30 00:30:08 +00003068 char ConstraintLetter,
Evan Chengda43bcf2008-09-24 00:05:32 +00003069 bool hasMemory,
Dan Gohman475871a2008-07-27 21:46:04 +00003070 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003071 SelectionDAG &DAG) const {
3072 // Default, for the time being, to the base class handler
Evan Chengda43bcf2008-09-24 00:05:32 +00003073 TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
3074 Ops, DAG);
Scott Michel203b2d62008-04-30 00:30:08 +00003075}
3076
Scott Michel266bc8f2007-12-04 22:23:35 +00003077/// isLegalAddressImmediate - Return true if the integer value can be used
3078/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003079bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
3080 const Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003081 // SPU's addresses are 256K:
3082 return (V > -(1 << 18) && V < (1 << 18) - 1);
3083}
3084
3085bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003086 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003087}
Dan Gohman6520e202008-10-18 02:06:02 +00003088
3089bool
3090SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3091 // The SPU target isn't yet aware of offsets.
3092 return false;
3093}