blob: dc0d5a6025434ca5daec9a86054acb109ceef606 [file] [log] [blame]
Scott Michel7ea02ff2009-03-17 01:15:45 +00001//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002// The LLVM Compiler Infrastructure
3//
Chris Lattner4ee451d2007-12-29 20:36:04 +00004// This file is distributed under the University of Illinois Open Source
5// License. See LICENSE.TXT for details.
Scott Michel266bc8f2007-12-04 22:23:35 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the SPUTargetLowering class.
10//
11//===----------------------------------------------------------------------===//
12
Scott Michel266bc8f2007-12-04 22:23:35 +000013#include "SPUISelLowering.h"
14#include "SPUTargetMachine.h"
Anton Korobeynikov16c29b52011-01-10 12:39:04 +000015#include "SPUFrameLowering.h"
Dan Gohman1e93df62010-04-17 14:41:14 +000016#include "SPUMachineFunction.h"
Chris Lattnerf0144122009-07-28 03:13:23 +000017#include "llvm/Constants.h"
18#include "llvm/Function.h"
19#include "llvm/Intrinsics.h"
Scott Michelc9c8b2a2009-01-26 03:31:40 +000020#include "llvm/CallingConv.h"
John Thompson44ab89e2010-10-29 17:29:13 +000021#include "llvm/Type.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000022#include "llvm/CodeGen/CallingConvLower.h"
23#include "llvm/CodeGen/MachineFrameInfo.h"
24#include "llvm/CodeGen/MachineFunction.h"
25#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner84bc5422007-12-31 04:13:23 +000026#include "llvm/CodeGen/MachineRegisterInfo.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000027#include "llvm/CodeGen/SelectionDAG.h"
Anton Korobeynikov362dd0b2010-02-15 22:37:53 +000028#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
Chris Lattnerf0144122009-07-28 03:13:23 +000029#include "llvm/Target/TargetOptions.h"
30#include "llvm/ADT/VectorExtras.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000031#include "llvm/Support/Debug.h"
Torok Edwindac237e2009-07-08 20:53:28 +000032#include "llvm/Support/ErrorHandling.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000033#include "llvm/Support/MathExtras.h"
Torok Edwindac237e2009-07-08 20:53:28 +000034#include "llvm/Support/raw_ostream.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000035#include <map>
36
37using namespace llvm;
38
39// Used in getTargetNodeName() below
40namespace {
41 std::map<unsigned, const char *> node_names;
42
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +000043 // Byte offset of the preferred slot (counted from the MSB)
44 int prefslotOffset(EVT VT) {
45 int retval=0;
Wesley Peckbf17cfa2010-11-23 03:31:01 +000046 if (VT==MVT::i1) retval=3;
47 if (VT==MVT::i8) retval=3;
48 if (VT==MVT::i16) retval=2;
Scott Michel266bc8f2007-12-04 22:23:35 +000049
50 return retval;
51 }
Scott Michel94bd57e2009-01-15 04:41:47 +000052
Scott Michelc9c8b2a2009-01-26 03:31:40 +000053 //! Expand a library call into an actual call DAG node
54 /*!
55 \note
56 This code is taken from SelectionDAGLegalize, since it is not exposed as
57 part of the LLVM SelectionDAG API.
58 */
59
60 SDValue
61 ExpandLibCall(RTLIB::Libcall LC, SDValue Op, SelectionDAG &DAG,
Dan Gohmand858e902010-04-17 15:26:15 +000062 bool isSigned, SDValue &Hi, const SPUTargetLowering &TLI) {
Scott Michelc9c8b2a2009-01-26 03:31:40 +000063 // The input chain to this libcall is the entry node of the function.
64 // Legalizing the call will automatically add the previous call to the
65 // dependence.
66 SDValue InChain = DAG.getEntryNode();
67
68 TargetLowering::ArgListTy Args;
69 TargetLowering::ArgListEntry Entry;
70 for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
Owen Andersone50ed302009-08-10 22:56:29 +000071 EVT ArgVT = Op.getOperand(i).getValueType();
Chris Lattnerdb125cf2011-07-18 04:54:35 +000072 Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext());
Scott Michelc9c8b2a2009-01-26 03:31:40 +000073 Entry.Node = Op.getOperand(i);
74 Entry.Ty = ArgTy;
75 Entry.isSExt = isSigned;
76 Entry.isZExt = !isSigned;
77 Args.push_back(Entry);
78 }
79 SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC),
80 TLI.getPointerTy());
81
82 // Splice the libcall in wherever FindInputOutputChains tells us to.
Chris Lattnerdb125cf2011-07-18 04:54:35 +000083 Type *RetTy =
Owen Anderson23b9b192009-08-12 00:36:31 +000084 Op.getNode()->getValueType(0).getTypeForEVT(*DAG.getContext());
Scott Michelc9c8b2a2009-01-26 03:31:40 +000085 std::pair<SDValue, SDValue> CallInfo =
86 TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false,
Anton Korobeynikov72977a42009-08-14 20:10:52 +000087 0, TLI.getLibcallCallingConv(LC), false,
Dan Gohman98ca4f22009-08-05 01:29:28 +000088 /*isReturnValueUsed=*/true,
Bill Wendling46ada192010-03-02 01:55:18 +000089 Callee, Args, DAG, Op.getDebugLoc());
Scott Michelc9c8b2a2009-01-26 03:31:40 +000090
91 return CallInfo.first;
92 }
Scott Michel266bc8f2007-12-04 22:23:35 +000093}
94
95SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
Chris Lattnerf0144122009-07-28 03:13:23 +000096 : TargetLowering(TM, new TargetLoweringObjectFileELF()),
97 SPUTM(TM) {
Scott Michel266bc8f2007-12-04 22:23:35 +000098
99 // Use _setjmp/_longjmp instead of setjmp/longjmp.
100 setUseUnderscoreSetJmp(true);
101 setUseUnderscoreLongJmp(true);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000102
Scott Micheld1e8d9c2009-01-21 04:58:48 +0000103 // Set RTLIB libcall names as used by SPU:
104 setLibcallName(RTLIB::DIV_F64, "__fast_divdf3");
105
Scott Michel266bc8f2007-12-04 22:23:35 +0000106 // Set up the SPU's register classes:
Owen Anderson825b72b2009-08-11 20:47:22 +0000107 addRegisterClass(MVT::i8, SPU::R8CRegisterClass);
108 addRegisterClass(MVT::i16, SPU::R16CRegisterClass);
109 addRegisterClass(MVT::i32, SPU::R32CRegisterClass);
110 addRegisterClass(MVT::i64, SPU::R64CRegisterClass);
111 addRegisterClass(MVT::f32, SPU::R32FPRegisterClass);
112 addRegisterClass(MVT::f64, SPU::R64FPRegisterClass);
113 addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000114
Scott Michel266bc8f2007-12-04 22:23:35 +0000115 // SPU has no sign or zero extended loads for i1, i8, i16:
Owen Anderson825b72b2009-08-11 20:47:22 +0000116 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
117 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
118 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +0000119
Owen Anderson825b72b2009-08-11 20:47:22 +0000120 setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
121 setLoadExtAction(ISD::EXTLOAD, MVT::f64, Expand);
Scott Michelb30e8f62008-12-02 19:53:53 +0000122
Owen Anderson825b72b2009-08-11 20:47:22 +0000123 setTruncStoreAction(MVT::i128, MVT::i64, Expand);
124 setTruncStoreAction(MVT::i128, MVT::i32, Expand);
125 setTruncStoreAction(MVT::i128, MVT::i16, Expand);
126 setTruncStoreAction(MVT::i128, MVT::i8, Expand);
Eli Friedman5427d712009-07-17 06:36:24 +0000127
Owen Anderson825b72b2009-08-11 20:47:22 +0000128 setTruncStoreAction(MVT::f64, MVT::f32, Expand);
Eli Friedman5427d712009-07-17 06:36:24 +0000129
Scott Michel266bc8f2007-12-04 22:23:35 +0000130 // SPU constant load actions are custom lowered:
Owen Anderson825b72b2009-08-11 20:47:22 +0000131 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
132 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000133
134 // SPU's loads and stores have to be custom lowered:
Owen Anderson825b72b2009-08-11 20:47:22 +0000135 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::i128;
Scott Michel266bc8f2007-12-04 22:23:35 +0000136 ++sctype) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000137 MVT::SimpleValueType VT = (MVT::SimpleValueType)sctype;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000138
Scott Michelf0569be2008-12-27 04:51:36 +0000139 setOperationAction(ISD::LOAD, VT, Custom);
140 setOperationAction(ISD::STORE, VT, Custom);
141 setLoadExtAction(ISD::EXTLOAD, VT, Custom);
142 setLoadExtAction(ISD::ZEXTLOAD, VT, Custom);
143 setLoadExtAction(ISD::SEXTLOAD, VT, Custom);
144
Owen Anderson825b72b2009-08-11 20:47:22 +0000145 for (unsigned stype = sctype - 1; stype >= (unsigned) MVT::i8; --stype) {
146 MVT::SimpleValueType StoreVT = (MVT::SimpleValueType) stype;
Scott Michelf0569be2008-12-27 04:51:36 +0000147 setTruncStoreAction(VT, StoreVT, Expand);
148 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000149 }
150
Owen Anderson825b72b2009-08-11 20:47:22 +0000151 for (unsigned sctype = (unsigned) MVT::f32; sctype < (unsigned) MVT::f64;
Scott Michelf0569be2008-12-27 04:51:36 +0000152 ++sctype) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000153 MVT::SimpleValueType VT = (MVT::SimpleValueType) sctype;
Scott Michelf0569be2008-12-27 04:51:36 +0000154
155 setOperationAction(ISD::LOAD, VT, Custom);
156 setOperationAction(ISD::STORE, VT, Custom);
157
Owen Anderson825b72b2009-08-11 20:47:22 +0000158 for (unsigned stype = sctype - 1; stype >= (unsigned) MVT::f32; --stype) {
159 MVT::SimpleValueType StoreVT = (MVT::SimpleValueType) stype;
Scott Michelf0569be2008-12-27 04:51:36 +0000160 setTruncStoreAction(VT, StoreVT, Expand);
161 }
162 }
163
Scott Michel266bc8f2007-12-04 22:23:35 +0000164 // Expand the jumptable branches
Owen Anderson825b72b2009-08-11 20:47:22 +0000165 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
166 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
Scott Michel7a1c9e92008-11-22 23:50:42 +0000167
168 // Custom lower SELECT_CC for most cases, but expand by default
Owen Anderson825b72b2009-08-11 20:47:22 +0000169 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
170 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
171 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
172 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
173 setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000174
175 // SPU has no intrinsics for these particular operations:
Owen Anderson825b72b2009-08-11 20:47:22 +0000176 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
Eli Friedman14648462011-07-27 22:21:52 +0000177 setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
Andrew Lenharthd497d9f2008-02-16 14:46:26 +0000178
Eli Friedman5427d712009-07-17 06:36:24 +0000179 // SPU has no division/remainder instructions
Owen Anderson825b72b2009-08-11 20:47:22 +0000180 setOperationAction(ISD::SREM, MVT::i8, Expand);
181 setOperationAction(ISD::UREM, MVT::i8, Expand);
182 setOperationAction(ISD::SDIV, MVT::i8, Expand);
183 setOperationAction(ISD::UDIV, MVT::i8, Expand);
184 setOperationAction(ISD::SDIVREM, MVT::i8, Expand);
185 setOperationAction(ISD::UDIVREM, MVT::i8, Expand);
186 setOperationAction(ISD::SREM, MVT::i16, Expand);
187 setOperationAction(ISD::UREM, MVT::i16, Expand);
188 setOperationAction(ISD::SDIV, MVT::i16, Expand);
189 setOperationAction(ISD::UDIV, MVT::i16, Expand);
190 setOperationAction(ISD::SDIVREM, MVT::i16, Expand);
191 setOperationAction(ISD::UDIVREM, MVT::i16, Expand);
192 setOperationAction(ISD::SREM, MVT::i32, Expand);
193 setOperationAction(ISD::UREM, MVT::i32, Expand);
194 setOperationAction(ISD::SDIV, MVT::i32, Expand);
195 setOperationAction(ISD::UDIV, MVT::i32, Expand);
196 setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
197 setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
198 setOperationAction(ISD::SREM, MVT::i64, Expand);
199 setOperationAction(ISD::UREM, MVT::i64, Expand);
200 setOperationAction(ISD::SDIV, MVT::i64, Expand);
201 setOperationAction(ISD::UDIV, MVT::i64, Expand);
202 setOperationAction(ISD::SDIVREM, MVT::i64, Expand);
203 setOperationAction(ISD::UDIVREM, MVT::i64, Expand);
204 setOperationAction(ISD::SREM, MVT::i128, Expand);
205 setOperationAction(ISD::UREM, MVT::i128, Expand);
206 setOperationAction(ISD::SDIV, MVT::i128, Expand);
207 setOperationAction(ISD::UDIV, MVT::i128, Expand);
208 setOperationAction(ISD::SDIVREM, MVT::i128, Expand);
209 setOperationAction(ISD::UDIVREM, MVT::i128, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000210
Scott Michel266bc8f2007-12-04 22:23:35 +0000211 // We don't support sin/cos/sqrt/fmod
Owen Anderson825b72b2009-08-11 20:47:22 +0000212 setOperationAction(ISD::FSIN , MVT::f64, Expand);
213 setOperationAction(ISD::FCOS , MVT::f64, Expand);
214 setOperationAction(ISD::FREM , MVT::f64, Expand);
215 setOperationAction(ISD::FSIN , MVT::f32, Expand);
216 setOperationAction(ISD::FCOS , MVT::f32, Expand);
217 setOperationAction(ISD::FREM , MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000218
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000219 // Expand fsqrt to the appropriate libcall (NOTE: should use h/w fsqrt
220 // for f32!)
Owen Anderson825b72b2009-08-11 20:47:22 +0000221 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
222 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000223
Cameron Zwarich33390842011-07-08 21:39:21 +0000224 setOperationAction(ISD::FMA, MVT::f64, Expand);
225 setOperationAction(ISD::FMA, MVT::f32, Expand);
226
Owen Anderson825b72b2009-08-11 20:47:22 +0000227 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
228 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000229
230 // SPU can do rotate right and left, so legalize it... but customize for i8
231 // because instructions don't exist.
Bill Wendling9440e352008-08-31 02:59:23 +0000232
233 // FIXME: Change from "expand" to appropriate type once ROTR is supported in
234 // .td files.
Owen Anderson825b72b2009-08-11 20:47:22 +0000235 setOperationAction(ISD::ROTR, MVT::i32, Expand /*Legal*/);
236 setOperationAction(ISD::ROTR, MVT::i16, Expand /*Legal*/);
237 setOperationAction(ISD::ROTR, MVT::i8, Expand /*Custom*/);
Bill Wendling9440e352008-08-31 02:59:23 +0000238
Owen Anderson825b72b2009-08-11 20:47:22 +0000239 setOperationAction(ISD::ROTL, MVT::i32, Legal);
240 setOperationAction(ISD::ROTL, MVT::i16, Legal);
241 setOperationAction(ISD::ROTL, MVT::i8, Custom);
Scott Micheldc91bea2008-11-20 16:36:33 +0000242
Scott Michel266bc8f2007-12-04 22:23:35 +0000243 // SPU has no native version of shift left/right for i8
Owen Anderson825b72b2009-08-11 20:47:22 +0000244 setOperationAction(ISD::SHL, MVT::i8, Custom);
245 setOperationAction(ISD::SRL, MVT::i8, Custom);
246 setOperationAction(ISD::SRA, MVT::i8, Custom);
Scott Michel9c0c6b22008-11-21 02:56:16 +0000247
Scott Michel02d711b2008-12-30 23:28:25 +0000248 // Make these operations legal and handle them during instruction selection:
Owen Anderson825b72b2009-08-11 20:47:22 +0000249 setOperationAction(ISD::SHL, MVT::i64, Legal);
250 setOperationAction(ISD::SRL, MVT::i64, Legal);
251 setOperationAction(ISD::SRA, MVT::i64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000252
Scott Michel5af8f0e2008-07-16 17:17:29 +0000253 // Custom lower i8, i32 and i64 multiplications
Owen Anderson825b72b2009-08-11 20:47:22 +0000254 setOperationAction(ISD::MUL, MVT::i8, Custom);
255 setOperationAction(ISD::MUL, MVT::i32, Legal);
256 setOperationAction(ISD::MUL, MVT::i64, Legal);
Scott Michel9c0c6b22008-11-21 02:56:16 +0000257
Eli Friedman6314ac22009-06-16 06:40:59 +0000258 // Expand double-width multiplication
259 // FIXME: It would probably be reasonable to support some of these operations
Owen Anderson825b72b2009-08-11 20:47:22 +0000260 setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand);
261 setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand);
262 setOperationAction(ISD::MULHU, MVT::i8, Expand);
263 setOperationAction(ISD::MULHS, MVT::i8, Expand);
264 setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand);
265 setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand);
266 setOperationAction(ISD::MULHU, MVT::i16, Expand);
267 setOperationAction(ISD::MULHS, MVT::i16, Expand);
268 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
269 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
270 setOperationAction(ISD::MULHU, MVT::i32, Expand);
271 setOperationAction(ISD::MULHS, MVT::i32, Expand);
272 setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
273 setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
274 setOperationAction(ISD::MULHU, MVT::i64, Expand);
275 setOperationAction(ISD::MULHS, MVT::i64, Expand);
Eli Friedman6314ac22009-06-16 06:40:59 +0000276
Scott Michel8bf61e82008-06-02 22:18:03 +0000277 // Need to custom handle (some) common i8, i64 math ops
Owen Anderson825b72b2009-08-11 20:47:22 +0000278 setOperationAction(ISD::ADD, MVT::i8, Custom);
279 setOperationAction(ISD::ADD, MVT::i64, Legal);
280 setOperationAction(ISD::SUB, MVT::i8, Custom);
281 setOperationAction(ISD::SUB, MVT::i64, Legal);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000282
Scott Michel266bc8f2007-12-04 22:23:35 +0000283 // SPU does not have BSWAP. It does have i32 support CTLZ.
284 // CTPOP has to be custom lowered.
Owen Anderson825b72b2009-08-11 20:47:22 +0000285 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
286 setOperationAction(ISD::BSWAP, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000287
Owen Anderson825b72b2009-08-11 20:47:22 +0000288 setOperationAction(ISD::CTPOP, MVT::i8, Custom);
289 setOperationAction(ISD::CTPOP, MVT::i16, Custom);
290 setOperationAction(ISD::CTPOP, MVT::i32, Custom);
291 setOperationAction(ISD::CTPOP, MVT::i64, Custom);
292 setOperationAction(ISD::CTPOP, MVT::i128, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000293
Owen Anderson825b72b2009-08-11 20:47:22 +0000294 setOperationAction(ISD::CTTZ , MVT::i8, Expand);
295 setOperationAction(ISD::CTTZ , MVT::i16, Expand);
296 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
297 setOperationAction(ISD::CTTZ , MVT::i64, Expand);
298 setOperationAction(ISD::CTTZ , MVT::i128, Expand);
Chandler Carruth63974b22011-12-13 01:56:10 +0000299 setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i8, Expand);
300 setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i16, Expand);
301 setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand);
302 setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand);
303 setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i128, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000304
Owen Anderson825b72b2009-08-11 20:47:22 +0000305 setOperationAction(ISD::CTLZ , MVT::i8, Promote);
306 setOperationAction(ISD::CTLZ , MVT::i16, Promote);
307 setOperationAction(ISD::CTLZ , MVT::i32, Legal);
308 setOperationAction(ISD::CTLZ , MVT::i64, Expand);
309 setOperationAction(ISD::CTLZ , MVT::i128, Expand);
Chandler Carruth63974b22011-12-13 01:56:10 +0000310 setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i8, Expand);
311 setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i16, Expand);
312 setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand);
313 setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand);
314 setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i128, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000315
Scott Michel8bf61e82008-06-02 22:18:03 +0000316 // SPU has a version of select that implements (a&~c)|(b&c), just like
Scott Michel405fba12008-03-10 23:49:09 +0000317 // select ought to work:
Owen Anderson825b72b2009-08-11 20:47:22 +0000318 setOperationAction(ISD::SELECT, MVT::i8, Legal);
319 setOperationAction(ISD::SELECT, MVT::i16, Legal);
320 setOperationAction(ISD::SELECT, MVT::i32, Legal);
321 setOperationAction(ISD::SELECT, MVT::i64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000322
Owen Anderson825b72b2009-08-11 20:47:22 +0000323 setOperationAction(ISD::SETCC, MVT::i8, Legal);
324 setOperationAction(ISD::SETCC, MVT::i16, Legal);
325 setOperationAction(ISD::SETCC, MVT::i32, Legal);
326 setOperationAction(ISD::SETCC, MVT::i64, Legal);
327 setOperationAction(ISD::SETCC, MVT::f64, Custom);
Scott Michelad2715e2008-03-05 23:02:02 +0000328
Scott Michelf0569be2008-12-27 04:51:36 +0000329 // Custom lower i128 -> i64 truncates
Owen Anderson825b72b2009-08-11 20:47:22 +0000330 setOperationAction(ISD::TRUNCATE, MVT::i64, Custom);
Scott Michelb30e8f62008-12-02 19:53:53 +0000331
Scott Michel77f452d2009-08-25 22:37:34 +0000332 // Custom lower i32/i64 -> i128 sign extend
Scott Michelf1fa4fd2009-08-24 22:28:53 +0000333 setOperationAction(ISD::SIGN_EXTEND, MVT::i128, Custom);
334
Owen Anderson825b72b2009-08-11 20:47:22 +0000335 setOperationAction(ISD::FP_TO_SINT, MVT::i8, Promote);
336 setOperationAction(ISD::FP_TO_UINT, MVT::i8, Promote);
337 setOperationAction(ISD::FP_TO_SINT, MVT::i16, Promote);
338 setOperationAction(ISD::FP_TO_UINT, MVT::i16, Promote);
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000339 // SPU has a legal FP -> signed INT instruction for f32, but for f64, need
340 // to expand to a libcall, hence the custom lowering:
Owen Anderson825b72b2009-08-11 20:47:22 +0000341 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
342 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
343 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Expand);
344 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
345 setOperationAction(ISD::FP_TO_SINT, MVT::i128, Expand);
346 setOperationAction(ISD::FP_TO_UINT, MVT::i128, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000347
348 // FDIV on SPU requires custom lowering
Owen Anderson825b72b2009-08-11 20:47:22 +0000349 setOperationAction(ISD::FDIV, MVT::f64, Expand); // to libcall
Scott Michel266bc8f2007-12-04 22:23:35 +0000350
Scott Michel9de57a92009-01-26 22:33:37 +0000351 // SPU has [U|S]INT_TO_FP for f32->i32, but not for f64->i32, f64->i64:
Owen Anderson825b72b2009-08-11 20:47:22 +0000352 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
353 setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
354 setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
355 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
356 setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
357 setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
358 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
359 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000360
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000361 setOperationAction(ISD::BITCAST, MVT::i32, Legal);
362 setOperationAction(ISD::BITCAST, MVT::f32, Legal);
363 setOperationAction(ISD::BITCAST, MVT::i64, Legal);
364 setOperationAction(ISD::BITCAST, MVT::f64, Legal);
Scott Michel266bc8f2007-12-04 22:23:35 +0000365
366 // We cannot sextinreg(i1). Expand to shifts.
Owen Anderson825b72b2009-08-11 20:47:22 +0000367 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000368
Scott Michel5af8f0e2008-07-16 17:17:29 +0000369 // We want to legalize GlobalAddress and ConstantPool nodes into the
Scott Michel266bc8f2007-12-04 22:23:35 +0000370 // appropriate instructions to materialize the address.
Owen Anderson825b72b2009-08-11 20:47:22 +0000371 for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
Scott Michel053c1da2008-01-29 02:16:57 +0000372 ++sctype) {
Owen Anderson825b72b2009-08-11 20:47:22 +0000373 MVT::SimpleValueType VT = (MVT::SimpleValueType)sctype;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000374
Scott Michel1df30c42008-12-29 03:23:36 +0000375 setOperationAction(ISD::GlobalAddress, VT, Custom);
376 setOperationAction(ISD::ConstantPool, VT, Custom);
377 setOperationAction(ISD::JumpTable, VT, Custom);
Scott Michel053c1da2008-01-29 02:16:57 +0000378 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000379
Scott Michel266bc8f2007-12-04 22:23:35 +0000380 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
Owen Anderson825b72b2009-08-11 20:47:22 +0000381 setOperationAction(ISD::VASTART , MVT::Other, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000382
Scott Michel266bc8f2007-12-04 22:23:35 +0000383 // Use the default implementation.
Owen Anderson825b72b2009-08-11 20:47:22 +0000384 setOperationAction(ISD::VAARG , MVT::Other, Expand);
385 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
386 setOperationAction(ISD::VAEND , MVT::Other, Expand);
387 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
388 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
389 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
390 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000391
392 // Cell SPU has instructions for converting between i64 and fp.
Owen Anderson825b72b2009-08-11 20:47:22 +0000393 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
394 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000395
Scott Michel266bc8f2007-12-04 22:23:35 +0000396 // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
Owen Anderson825b72b2009-08-11 20:47:22 +0000397 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +0000398
399 // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
Owen Anderson825b72b2009-08-11 20:47:22 +0000400 setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000401
402 // First set operation action for all vector types to expand. Then we
403 // will selectively turn on ones that can be effectively codegen'd.
Owen Anderson825b72b2009-08-11 20:47:22 +0000404 addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
405 addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
406 addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
407 addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
408 addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
409 addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
Scott Michel266bc8f2007-12-04 22:23:35 +0000410
Owen Anderson825b72b2009-08-11 20:47:22 +0000411 for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
412 i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
413 MVT::SimpleValueType VT = (MVT::SimpleValueType)i;
Scott Michel266bc8f2007-12-04 22:23:35 +0000414
Nadav Rotem34804c42011-10-04 12:05:35 +0000415 // Set operation actions to legal types only.
416 if (!isTypeLegal(VT)) continue;
417
Duncan Sands83ec4b62008-06-06 12:08:01 +0000418 // add/sub are legal for all supported vector VT's.
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000419 setOperationAction(ISD::ADD, VT, Legal);
420 setOperationAction(ISD::SUB, VT, Legal);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000421 // mul has to be custom lowered.
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000422 setOperationAction(ISD::MUL, VT, Legal);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000423
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000424 setOperationAction(ISD::AND, VT, Legal);
425 setOperationAction(ISD::OR, VT, Legal);
426 setOperationAction(ISD::XOR, VT, Legal);
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000427 setOperationAction(ISD::LOAD, VT, Custom);
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000428 setOperationAction(ISD::SELECT, VT, Legal);
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000429 setOperationAction(ISD::STORE, VT, Custom);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000430
Scott Michel266bc8f2007-12-04 22:23:35 +0000431 // These operations need to be expanded:
Scott Michelc9c8b2a2009-01-26 03:31:40 +0000432 setOperationAction(ISD::SDIV, VT, Expand);
433 setOperationAction(ISD::SREM, VT, Expand);
434 setOperationAction(ISD::UDIV, VT, Expand);
435 setOperationAction(ISD::UREM, VT, Expand);
Scott Michel266bc8f2007-12-04 22:23:35 +0000436
Nadav Rotem4d83b792011-10-15 20:05:17 +0000437 // Expand all trunc stores
438 for (unsigned j = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
439 j <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++j) {
440 MVT::SimpleValueType TargetVT = (MVT::SimpleValueType)j;
441 setTruncStoreAction(VT, TargetVT, Expand);
442 }
443
Scott Michel266bc8f2007-12-04 22:23:35 +0000444 // Custom lower build_vector, constant pool spills, insert and
445 // extract vector elements:
Nadav Rotem34804c42011-10-04 12:05:35 +0000446 setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
447 setOperationAction(ISD::ConstantPool, VT, Custom);
448 setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
449 setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
450 setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
451 setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
Scott Michel266bc8f2007-12-04 22:23:35 +0000452 }
453
Nadav Rotem4d83b792011-10-15 20:05:17 +0000454 setOperationAction(ISD::SHL, MVT::v2i64, Expand);
455
Owen Anderson825b72b2009-08-11 20:47:22 +0000456 setOperationAction(ISD::AND, MVT::v16i8, Custom);
457 setOperationAction(ISD::OR, MVT::v16i8, Custom);
458 setOperationAction(ISD::XOR, MVT::v16i8, Custom);
459 setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000460
Owen Anderson825b72b2009-08-11 20:47:22 +0000461 setOperationAction(ISD::FDIV, MVT::v4f32, Legal);
Scott Michel1df30c42008-12-29 03:23:36 +0000462
Scott Michelf0569be2008-12-27 04:51:36 +0000463 setBooleanContents(ZeroOrNegativeOneBooleanContent);
Duncan Sands28b77e92011-09-06 19:07:46 +0000464 setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); // FIXME: Is this correct?
Scott Michel5af8f0e2008-07-16 17:17:29 +0000465
Scott Michel266bc8f2007-12-04 22:23:35 +0000466 setStackPointerRegisterToSaveRestore(SPU::R1);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000467
Scott Michel266bc8f2007-12-04 22:23:35 +0000468 // We have target-specific dag combine patterns for the following nodes:
Scott Michel053c1da2008-01-29 02:16:57 +0000469 setTargetDAGCombine(ISD::ADD);
Scott Michela59d4692008-02-23 18:41:37 +0000470 setTargetDAGCombine(ISD::ZERO_EXTEND);
471 setTargetDAGCombine(ISD::SIGN_EXTEND);
472 setTargetDAGCombine(ISD::ANY_EXTEND);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000473
Eli Friedmanfc5d3052011-05-06 20:34:06 +0000474 setMinFunctionAlignment(3);
475
Scott Michel266bc8f2007-12-04 22:23:35 +0000476 computeRegisterProperties();
Scott Michel7a1c9e92008-11-22 23:50:42 +0000477
Scott Michele07d3de2008-12-09 03:37:19 +0000478 // Set pre-RA register scheduler default to BURR, which produces slightly
479 // better code than the default (could also be TDRR, but TargetLowering.h
480 // needs a mod to support that model):
Evan Cheng211ffa12010-05-19 20:19:50 +0000481 setSchedulingPreference(Sched::RegPressure);
Scott Michel266bc8f2007-12-04 22:23:35 +0000482}
483
484const char *
485SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
486{
487 if (node_names.empty()) {
488 node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
489 node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
490 node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
491 node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
Scott Michel9de5d0d2008-01-11 02:53:15 +0000492 node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
Scott Michel053c1da2008-01-29 02:16:57 +0000493 node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
Scott Michel266bc8f2007-12-04 22:23:35 +0000494 node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
495 node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
496 node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
Scott Michel7a1c9e92008-11-22 23:50:42 +0000497 node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000498 node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
Scott Michel1df30c42008-12-29 03:23:36 +0000499 node_names[(unsigned) SPUISD::PREFSLOT2VEC] = "SPUISD::PREFSLOT2VEC";
Scott Michel104de432008-11-24 17:11:17 +0000500 node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000501 node_names[(unsigned) SPUISD::SHL_BITS] = "SPUISD::SHL_BITS";
502 node_names[(unsigned) SPUISD::SHL_BYTES] = "SPUISD::SHL_BYTES";
Scott Michel266bc8f2007-12-04 22:23:35 +0000503 node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
504 node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
Scott Micheld1e8d9c2009-01-21 04:58:48 +0000505 node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
506 node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
507 "SPUISD::ROTBYTES_LEFT_BITS";
Scott Michel8bf61e82008-06-02 22:18:03 +0000508 node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
Scott Michel266bc8f2007-12-04 22:23:35 +0000509 node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
Scott Michel94bd57e2009-01-15 04:41:47 +0000510 node_names[(unsigned) SPUISD::ADD64_MARKER] = "SPUISD::ADD64_MARKER";
511 node_names[(unsigned) SPUISD::SUB64_MARKER] = "SPUISD::SUB64_MARKER";
512 node_names[(unsigned) SPUISD::MUL64_MARKER] = "SPUISD::MUL64_MARKER";
Scott Michel266bc8f2007-12-04 22:23:35 +0000513 }
514
515 std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
516
517 return ((i != node_names.end()) ? i->second : 0);
518}
519
Scott Michelf0569be2008-12-27 04:51:36 +0000520//===----------------------------------------------------------------------===//
521// Return the Cell SPU's SETCC result type
522//===----------------------------------------------------------------------===//
523
Duncan Sands28b77e92011-09-06 19:07:46 +0000524EVT SPUTargetLowering::getSetCCResultType(EVT VT) const {
Kalle Raiskila7de81012010-11-24 12:59:16 +0000525 // i8, i16 and i32 are valid SETCC result types
526 MVT::SimpleValueType retval;
527
528 switch(VT.getSimpleVT().SimpleTy){
529 case MVT::i1:
530 case MVT::i8:
531 retval = MVT::i8; break;
532 case MVT::i16:
533 retval = MVT::i16; break;
534 case MVT::i32:
535 default:
536 retval = MVT::i32;
537 }
538 return retval;
Scott Michel78c47fa2008-03-10 16:58:52 +0000539}
540
Scott Michel266bc8f2007-12-04 22:23:35 +0000541//===----------------------------------------------------------------------===//
542// Calling convention code:
543//===----------------------------------------------------------------------===//
544
545#include "SPUGenCallingConv.inc"
546
547//===----------------------------------------------------------------------===//
548// LowerOperation implementation
549//===----------------------------------------------------------------------===//
550
551/// Custom lower loads for CellSPU
552/*!
553 All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
554 within a 16-byte block, we have to rotate to extract the requested element.
Scott Michel30ee7df2008-12-04 03:02:42 +0000555
556 For extending loads, we also want to ensure that the following sequence is
Owen Anderson825b72b2009-08-11 20:47:22 +0000557 emitted, e.g. for MVT::f32 extending load to MVT::f64:
Scott Michel30ee7df2008-12-04 03:02:42 +0000558
559\verbatim
Scott Michel1df30c42008-12-29 03:23:36 +0000560%1 v16i8,ch = load
Scott Michel30ee7df2008-12-04 03:02:42 +0000561%2 v16i8,ch = rotate %1
Scott Michel1df30c42008-12-29 03:23:36 +0000562%3 v4f8, ch = bitconvert %2
Scott Michel30ee7df2008-12-04 03:02:42 +0000563%4 f32 = vec2perfslot %3
564%5 f64 = fp_extend %4
565\endverbatim
566*/
Dan Gohman475871a2008-07-27 21:46:04 +0000567static SDValue
568LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000569 LoadSDNode *LN = cast<LoadSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000570 SDValue the_chain = LN->getChain();
Owen Andersone50ed302009-08-10 22:56:29 +0000571 EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
572 EVT InVT = LN->getMemoryVT();
573 EVT OutVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +0000574 ISD::LoadExtType ExtType = LN->getExtensionType();
575 unsigned alignment = LN->getAlignment();
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000576 int pso = prefslotOffset(InVT);
Dale Johannesen33c960f2009-02-04 20:06:27 +0000577 DebugLoc dl = Op.getDebugLoc();
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000578 EVT vecVT = InVT.isVector()? InVT: EVT::getVectorVT(*DAG.getContext(), InVT,
579 (128 / InVT.getSizeInBits()));
Scott Michel266bc8f2007-12-04 22:23:35 +0000580
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000581 // two sanity checks
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000582 assert( LN->getAddressingMode() == ISD::UNINDEXED
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000583 && "we should get only UNINDEXED adresses");
584 // clean aligned loads can be selected as-is
Kalle Raiskila8702e8b2011-01-17 11:59:20 +0000585 if (InVT.getSizeInBits() == 128 && (alignment%16) == 0)
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000586 return SDValue();
587
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000588 // Get pointerinfos to the memory chunk(s) that contain the data to load
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000589 uint64_t mpi_offset = LN->getPointerInfo().Offset;
590 mpi_offset -= mpi_offset%16;
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000591 MachinePointerInfo lowMemPtr(LN->getPointerInfo().V, mpi_offset);
592 MachinePointerInfo highMemPtr(LN->getPointerInfo().V, mpi_offset+16);
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000593
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000594 SDValue result;
595 SDValue basePtr = LN->getBasePtr();
596 SDValue rotate;
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000597
Kalle Raiskila8702e8b2011-01-17 11:59:20 +0000598 if ((alignment%16) == 0) {
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000599 ConstantSDNode *CN;
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000600
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000601 // Special cases for a known aligned load to simplify the base pointer
602 // and the rotation amount:
603 if (basePtr.getOpcode() == ISD::ADD
604 && (CN = dyn_cast<ConstantSDNode > (basePtr.getOperand(1))) != 0) {
605 // Known offset into basePtr
606 int64_t offset = CN->getSExtValue();
607 int64_t rotamt = int64_t((offset & 0xf) - pso);
Scott Michel266bc8f2007-12-04 22:23:35 +0000608
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000609 if (rotamt < 0)
610 rotamt += 16;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000611
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000612 rotate = DAG.getConstant(rotamt, MVT::i16);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000613
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000614 // Simplify the base pointer for this case:
615 basePtr = basePtr.getOperand(0);
616 if ((offset & ~0xf) > 0) {
Dale Johannesende064702009-02-06 21:50:26 +0000617 basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
Scott Michelf0569be2008-12-27 04:51:36 +0000618 basePtr,
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000619 DAG.getConstant((offset & ~0xf), PtrVT));
Scott Michelf0569be2008-12-27 04:51:36 +0000620 }
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000621 } else if ((basePtr.getOpcode() == SPUISD::AFormAddr)
622 || (basePtr.getOpcode() == SPUISD::IndirectAddr
623 && basePtr.getOperand(0).getOpcode() == SPUISD::Hi
624 && basePtr.getOperand(1).getOpcode() == SPUISD::Lo)) {
625 // Plain aligned a-form address: rotate into preferred slot
626 // Same for (SPUindirect (SPUhi ...), (SPUlo ...))
627 int64_t rotamt = -pso;
628 if (rotamt < 0)
629 rotamt += 16;
630 rotate = DAG.getConstant(rotamt, MVT::i16);
631 } else {
Scott Michelf0569be2008-12-27 04:51:36 +0000632 // Offset the rotate amount by the basePtr and the preferred slot
633 // byte offset
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000634 int64_t rotamt = -pso;
635 if (rotamt < 0)
636 rotamt += 16;
Dale Johannesen33c960f2009-02-04 20:06:27 +0000637 rotate = DAG.getNode(ISD::ADD, dl, PtrVT,
Scott Michelf0569be2008-12-27 04:51:36 +0000638 basePtr,
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000639 DAG.getConstant(rotamt, PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +0000640 }
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000641 } else {
642 // Unaligned load: must be more pessimistic about addressing modes:
643 if (basePtr.getOpcode() == ISD::ADD) {
644 MachineFunction &MF = DAG.getMachineFunction();
645 MachineRegisterInfo &RegInfo = MF.getRegInfo();
646 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
647 SDValue Flag;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000648
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000649 SDValue Op0 = basePtr.getOperand(0);
650 SDValue Op1 = basePtr.getOperand(1);
651
652 if (isa<ConstantSDNode>(Op1)) {
653 // Convert the (add <ptr>, <const>) to an indirect address contained
654 // in a register. Note that this is done because we need to avoid
655 // creating a 0(reg) d-form address due to the SPU's block loads.
656 basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Op0, Op1);
657 the_chain = DAG.getCopyToReg(the_chain, dl, VReg, basePtr, Flag);
658 basePtr = DAG.getCopyFromReg(the_chain, dl, VReg, PtrVT);
659 } else {
660 // Convert the (add <arg1>, <arg2>) to an indirect address, which
661 // will likely be lowered as a reg(reg) x-form address.
662 basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Op0, Op1);
663 }
664 } else {
665 basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
666 basePtr,
667 DAG.getConstant(0, PtrVT));
668 }
669
670 // Offset the rotate amount by the basePtr and the preferred slot
671 // byte offset
672 rotate = DAG.getNode(ISD::ADD, dl, PtrVT,
673 basePtr,
674 DAG.getConstant(-pso, PtrVT));
675 }
676
677 // Do the load as a i128 to allow possible shifting
678 SDValue low = DAG.getLoad(MVT::i128, dl, the_chain, basePtr,
679 lowMemPtr,
Pete Cooperd752e0f2011-11-08 18:42:53 +0000680 LN->isVolatile(), LN->isNonTemporal(), false, 16);
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000681
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000682 // When the size is not greater than alignment we get all data with just
683 // one load
684 if (alignment >= InVT.getSizeInBits()/8) {
Scott Michelf0569be2008-12-27 04:51:36 +0000685 // Update the chain
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000686 the_chain = low.getValue(1);
Scott Michelf0569be2008-12-27 04:51:36 +0000687
688 // Rotate into the preferred slot:
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000689 result = DAG.getNode(SPUISD::ROTBYTES_LEFT, dl, MVT::i128,
690 low.getValue(0), rotate);
Scott Michelf0569be2008-12-27 04:51:36 +0000691
Scott Michel30ee7df2008-12-04 03:02:42 +0000692 // Convert the loaded v16i8 vector to the appropriate vector type
693 // specified by the operand:
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000694 EVT vecVT = EVT::getVectorVT(*DAG.getContext(),
Owen Anderson23b9b192009-08-12 00:36:31 +0000695 InVT, (128 / InVT.getSizeInBits()));
Dale Johannesen33c960f2009-02-04 20:06:27 +0000696 result = DAG.getNode(SPUISD::VEC2PREFSLOT, dl, InVT,
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000697 DAG.getNode(ISD::BITCAST, dl, vecVT, result));
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000698 }
699 // When alignment is less than the size, we might need (known only at
700 // run-time) two loads
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000701 // TODO: if the memory address is composed only from constants, we have
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000702 // extra kowledge, and might avoid the second load
703 else {
704 // storage position offset from lower 16 byte aligned memory chunk
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000705 SDValue offset = DAG.getNode(ISD::AND, dl, MVT::i32,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000706 basePtr, DAG.getConstant( 0xf, MVT::i32 ) );
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000707 // get a registerfull of ones. (this implementation is a workaround: LLVM
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000708 // cannot handle 128 bit signed int constants)
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000709 SDValue ones = DAG.getConstant(-1, MVT::v4i32 );
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000710 ones = DAG.getNode(ISD::BITCAST, dl, MVT::i128, ones);
Scott Michel5af8f0e2008-07-16 17:17:29 +0000711
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000712 SDValue high = DAG.getLoad(MVT::i128, dl, the_chain,
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000713 DAG.getNode(ISD::ADD, dl, PtrVT,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000714 basePtr,
715 DAG.getConstant(16, PtrVT)),
716 highMemPtr,
Pete Cooperd752e0f2011-11-08 18:42:53 +0000717 LN->isVolatile(), LN->isNonTemporal(), false,
718 16);
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000719
720 the_chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, low.getValue(1),
721 high.getValue(1));
722
723 // Shift the (possible) high part right to compensate the misalignemnt.
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000724 // if there is no highpart (i.e. value is i64 and offset is 4), this
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000725 // will zero out the high value.
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000726 high = DAG.getNode(SPUISD::SRL_BYTES, dl, MVT::i128, high,
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000727 DAG.getNode(ISD::SUB, dl, MVT::i32,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000728 DAG.getConstant( 16, MVT::i32),
729 offset
730 ));
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000731
Chris Lattner7a2bdde2011-04-15 05:18:47 +0000732 // Shift the low similarly
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000733 // TODO: add SPUISD::SHL_BYTES
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000734 low = DAG.getNode(SPUISD::SHL_BYTES, dl, MVT::i128, low, offset );
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000735
736 // Merge the two parts
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000737 result = DAG.getNode(ISD::BITCAST, dl, vecVT,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000738 DAG.getNode(ISD::OR, dl, MVT::i128, low, high));
739
740 if (!InVT.isVector()) {
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000741 result = DAG.getNode(SPUISD::VEC2PREFSLOT, dl, InVT, result );
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000742 }
743
744 }
Scott Michel30ee7df2008-12-04 03:02:42 +0000745 // Handle extending loads by extending the scalar result:
746 if (ExtType == ISD::SEXTLOAD) {
Dale Johannesen33c960f2009-02-04 20:06:27 +0000747 result = DAG.getNode(ISD::SIGN_EXTEND, dl, OutVT, result);
Scott Michel30ee7df2008-12-04 03:02:42 +0000748 } else if (ExtType == ISD::ZEXTLOAD) {
Dale Johannesen33c960f2009-02-04 20:06:27 +0000749 result = DAG.getNode(ISD::ZERO_EXTEND, dl, OutVT, result);
Scott Michel30ee7df2008-12-04 03:02:42 +0000750 } else if (ExtType == ISD::EXTLOAD) {
751 unsigned NewOpc = ISD::ANY_EXTEND;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000752
Scott Michel30ee7df2008-12-04 03:02:42 +0000753 if (OutVT.isFloatingPoint())
Scott Michel19c10e62009-01-26 03:37:41 +0000754 NewOpc = ISD::FP_EXTEND;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000755
Dale Johannesen33c960f2009-02-04 20:06:27 +0000756 result = DAG.getNode(NewOpc, dl, OutVT, result);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000757 }
758
Owen Anderson825b72b2009-08-11 20:47:22 +0000759 SDVTList retvts = DAG.getVTList(OutVT, MVT::Other);
Dan Gohman475871a2008-07-27 21:46:04 +0000760 SDValue retops[2] = {
Scott Michel58c58182008-01-17 20:38:41 +0000761 result,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000762 the_chain
Scott Michel58c58182008-01-17 20:38:41 +0000763 };
Scott Michel9de5d0d2008-01-11 02:53:15 +0000764
Dale Johannesen33c960f2009-02-04 20:06:27 +0000765 result = DAG.getNode(SPUISD::LDRESULT, dl, retvts,
Scott Michel58c58182008-01-17 20:38:41 +0000766 retops, sizeof(retops) / sizeof(retops[0]));
Scott Michel9de5d0d2008-01-11 02:53:15 +0000767 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +0000768}
769
770/// Custom lower stores for CellSPU
771/*!
772 All CellSPU stores are aligned to 16-byte boundaries, so for elements
773 within a 16-byte block, we have to generate a shuffle to insert the
774 requested element into its place, then store the resulting block.
775 */
Dan Gohman475871a2008-07-27 21:46:04 +0000776static SDValue
777LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000778 StoreSDNode *SN = cast<StoreSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +0000779 SDValue Value = SN->getValue();
Owen Andersone50ed302009-08-10 22:56:29 +0000780 EVT VT = Value.getValueType();
781 EVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
782 EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Dale Johannesen33c960f2009-02-04 20:06:27 +0000783 DebugLoc dl = Op.getDebugLoc();
Scott Michel9de5d0d2008-01-11 02:53:15 +0000784 unsigned alignment = SN->getAlignment();
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000785 SDValue result;
786 EVT vecVT = StVT.isVector()? StVT: EVT::getVectorVT(*DAG.getContext(), StVT,
787 (128 / StVT.getSizeInBits()));
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000788 // Get pointerinfos to the memory chunk(s) that contain the data to load
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000789 uint64_t mpi_offset = SN->getPointerInfo().Offset;
790 mpi_offset -= mpi_offset%16;
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000791 MachinePointerInfo lowMemPtr(SN->getPointerInfo().V, mpi_offset);
792 MachinePointerInfo highMemPtr(SN->getPointerInfo().V, mpi_offset+16);
Scott Michel266bc8f2007-12-04 22:23:35 +0000793
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000794
795 // two sanity checks
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000796 assert( SN->getAddressingMode() == ISD::UNINDEXED
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000797 && "we should get only UNINDEXED adresses");
798 // clean aligned loads can be selected as-is
Kalle Raiskila8702e8b2011-01-17 11:59:20 +0000799 if (StVT.getSizeInBits() == 128 && (alignment%16) == 0)
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000800 return SDValue();
801
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000802 SDValue alignLoadVec;
803 SDValue basePtr = SN->getBasePtr();
804 SDValue the_chain = SN->getChain();
805 SDValue insertEltOffs;
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000806
Kalle Raiskila8702e8b2011-01-17 11:59:20 +0000807 if ((alignment%16) == 0) {
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000808 ConstantSDNode *CN;
809 // Special cases for a known aligned load to simplify the base pointer
810 // and insertion byte:
811 if (basePtr.getOpcode() == ISD::ADD
812 && (CN = dyn_cast<ConstantSDNode>(basePtr.getOperand(1))) != 0) {
813 // Known offset into basePtr
814 int64_t offset = CN->getSExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000815
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000816 // Simplify the base pointer for this case:
817 basePtr = basePtr.getOperand(0);
818 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
819 basePtr,
820 DAG.getConstant((offset & 0xf), PtrVT));
Scott Michel266bc8f2007-12-04 22:23:35 +0000821
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000822 if ((offset & ~0xf) > 0) {
Dale Johannesende064702009-02-06 21:50:26 +0000823 basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
Scott Michelf0569be2008-12-27 04:51:36 +0000824 basePtr,
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000825 DAG.getConstant((offset & ~0xf), PtrVT));
Scott Michelf0569be2008-12-27 04:51:36 +0000826 }
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000827 } else {
828 // Otherwise, assume it's at byte 0 of basePtr
829 insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
830 basePtr,
831 DAG.getConstant(0, PtrVT));
832 basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
Scott Michelf0569be2008-12-27 04:51:36 +0000833 basePtr,
834 DAG.getConstant(0, PtrVT));
835 }
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000836 } else {
837 // Unaligned load: must be more pessimistic about addressing modes:
838 if (basePtr.getOpcode() == ISD::ADD) {
839 MachineFunction &MF = DAG.getMachineFunction();
840 MachineRegisterInfo &RegInfo = MF.getRegInfo();
841 unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
842 SDValue Flag;
Scott Michelf0569be2008-12-27 04:51:36 +0000843
Kalle Raiskila38e0c9b2010-11-15 10:12:32 +0000844 SDValue Op0 = basePtr.getOperand(0);
845 SDValue Op1 = basePtr.getOperand(1);
846
847 if (isa<ConstantSDNode>(Op1)) {
848 // Convert the (add <ptr>, <const>) to an indirect address contained
849 // in a register. Note that this is done because we need to avoid
850 // creating a 0(reg) d-form address due to the SPU's block loads.
851 basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Op0, Op1);
852 the_chain = DAG.getCopyToReg(the_chain, dl, VReg, basePtr, Flag);
853 basePtr = DAG.getCopyFromReg(the_chain, dl, VReg, PtrVT);
854 } else {
855 // Convert the (add <arg1>, <arg2>) to an indirect address, which
856 // will likely be lowered as a reg(reg) x-form address.
857 basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Op0, Op1);
858 }
859 } else {
860 basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
861 basePtr,
862 DAG.getConstant(0, PtrVT));
863 }
864
865 // Insertion point is solely determined by basePtr's contents
866 insertEltOffs = DAG.getNode(ISD::ADD, dl, PtrVT,
867 basePtr,
868 DAG.getConstant(0, PtrVT));
869 }
870
871 // Load the lower part of the memory to which to store.
872 SDValue low = DAG.getLoad(vecVT, dl, the_chain, basePtr,
Pete Cooperd752e0f2011-11-08 18:42:53 +0000873 lowMemPtr, SN->isVolatile(), SN->isNonTemporal(),
874 false, 16);
Scott Michelf0569be2008-12-27 04:51:36 +0000875
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000876 // if we don't need to store over the 16 byte boundary, one store suffices
877 if (alignment >= StVT.getSizeInBits()/8) {
Scott Michelf0569be2008-12-27 04:51:36 +0000878 // Update the chain
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000879 the_chain = low.getValue(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000880
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000881 LoadSDNode *LN = cast<LoadSDNode>(low);
Dan Gohman475871a2008-07-27 21:46:04 +0000882 SDValue theValue = SN->getValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000883
884 if (StVT != VT
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000885 && (theValue.getOpcode() == ISD::AssertZext
886 || theValue.getOpcode() == ISD::AssertSext)) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000887 // Drill down and get the value for zero- and sign-extended
888 // quantities
Scott Michel5af8f0e2008-07-16 17:17:29 +0000889 theValue = theValue.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000890 }
891
Scott Michel9de5d0d2008-01-11 02:53:15 +0000892 // If the base pointer is already a D-form address, then just create
893 // a new D-form address with a slot offset and the orignal base pointer.
894 // Otherwise generate a D-form address with the slot offset relative
895 // to the stack pointer, which is always aligned.
Scott Michelf0569be2008-12-27 04:51:36 +0000896#if !defined(NDEBUG)
897 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Chris Lattner4437ae22009-08-23 07:05:07 +0000898 errs() << "CellSPU LowerSTORE: basePtr = ";
Scott Michelf0569be2008-12-27 04:51:36 +0000899 basePtr.getNode()->dump(&DAG);
Chris Lattner4437ae22009-08-23 07:05:07 +0000900 errs() << "\n";
Scott Michelf0569be2008-12-27 04:51:36 +0000901 }
902#endif
Scott Michel9de5d0d2008-01-11 02:53:15 +0000903
Kalle Raiskilaf53fdc22010-08-24 11:05:51 +0000904 SDValue insertEltOp = DAG.getNode(SPUISD::SHUFFLE_MASK, dl, vecVT,
905 insertEltOffs);
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000906 SDValue vectorizeOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, vecVT,
Kalle Raiskilaf53fdc22010-08-24 11:05:51 +0000907 theValue);
908
Dale Johannesen33c960f2009-02-04 20:06:27 +0000909 result = DAG.getNode(SPUISD::SHUFB, dl, vecVT,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000910 vectorizeOp, low,
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000911 DAG.getNode(ISD::BITCAST, dl,
Owen Anderson825b72b2009-08-11 20:47:22 +0000912 MVT::v4i32, insertEltOp));
Scott Michel266bc8f2007-12-04 22:23:35 +0000913
Dale Johannesen33c960f2009-02-04 20:06:27 +0000914 result = DAG.getStore(the_chain, dl, result, basePtr,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000915 lowMemPtr,
David Greene73657df2010-02-15 16:55:58 +0000916 LN->isVolatile(), LN->isNonTemporal(),
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000917 16);
Scott Michel266bc8f2007-12-04 22:23:35 +0000918
Scott Michel266bc8f2007-12-04 22:23:35 +0000919 }
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000920 // do the store when it might cross the 16 byte memory access boundary.
921 else {
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000922 // TODO issue a warning if SN->isVolatile()== true? This is likely not
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000923 // what the user wanted.
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000924
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000925 // address offset from nearest lower 16byte alinged address
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000926 SDValue offset = DAG.getNode(ISD::AND, dl, MVT::i32,
927 SN->getBasePtr(),
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000928 DAG.getConstant(0xf, MVT::i32));
929 // 16 - offset
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000930 SDValue offset_compl = DAG.getNode(ISD::SUB, dl, MVT::i32,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000931 DAG.getConstant( 16, MVT::i32),
932 offset);
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000933 // 16 - sizeof(Value)
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000934 SDValue surplus = DAG.getNode(ISD::SUB, dl, MVT::i32,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000935 DAG.getConstant( 16, MVT::i32),
936 DAG.getConstant( VT.getSizeInBits()/8,
937 MVT::i32));
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000938 // get a registerfull of ones
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000939 SDValue ones = DAG.getConstant(-1, MVT::v4i32);
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000940 ones = DAG.getNode(ISD::BITCAST, dl, MVT::i128, ones);
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000941
942 // Create the 128 bit masks that have ones where the data to store is
943 // located.
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000944 SDValue lowmask, himask;
945 // if the value to store don't fill up the an entire 128 bits, zero
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000946 // out the last bits of the mask so that only the value we want to store
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000947 // is masked.
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000948 // this is e.g. in the case of store i32, align 2
949 if (!VT.isVector()){
950 Value = DAG.getNode(SPUISD::PREFSLOT2VEC, dl, vecVT, Value);
951 lowmask = DAG.getNode(SPUISD::SRL_BYTES, dl, MVT::i128, ones, surplus);
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000952 lowmask = DAG.getNode(SPUISD::SHL_BYTES, dl, MVT::i128, lowmask,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000953 surplus);
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000954 Value = DAG.getNode(ISD::BITCAST, dl, MVT::i128, Value);
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000955 Value = DAG.getNode(ISD::AND, dl, MVT::i128, Value, lowmask);
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000956
Torok Edwindac237e2009-07-08 20:53:28 +0000957 }
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000958 else {
959 lowmask = ones;
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000960 Value = DAG.getNode(ISD::BITCAST, dl, MVT::i128, Value);
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000961 }
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000962 // this will zero, if there are no data that goes to the high quad
963 himask = DAG.getNode(SPUISD::SHL_BYTES, dl, MVT::i128, lowmask,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000964 offset_compl);
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000965 lowmask = DAG.getNode(SPUISD::SRL_BYTES, dl, MVT::i128, lowmask,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000966 offset);
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000967
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000968 // Load in the old data and zero out the parts that will be overwritten with
969 // the new data to store.
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000970 SDValue hi = DAG.getLoad(MVT::i128, dl, the_chain,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000971 DAG.getNode(ISD::ADD, dl, PtrVT, basePtr,
972 DAG.getConstant( 16, PtrVT)),
973 highMemPtr,
Pete Cooperd752e0f2011-11-08 18:42:53 +0000974 SN->isVolatile(), SN->isNonTemporal(),
975 false, 16);
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000976 the_chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, low.getValue(1),
977 hi.getValue(1));
Scott Michel266bc8f2007-12-04 22:23:35 +0000978
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000979 low = DAG.getNode(ISD::AND, dl, MVT::i128,
980 DAG.getNode( ISD::BITCAST, dl, MVT::i128, low),
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000981 DAG.getNode( ISD::XOR, dl, MVT::i128, lowmask, ones));
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000982 hi = DAG.getNode(ISD::AND, dl, MVT::i128,
983 DAG.getNode( ISD::BITCAST, dl, MVT::i128, hi),
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000984 DAG.getNode( ISD::XOR, dl, MVT::i128, himask, ones));
985
986 // Shift the Value to store into place. rlow contains the parts that go to
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000987 // the lower memory chunk, rhi has the parts that go to the upper one.
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000988 SDValue rlow = DAG.getNode(SPUISD::SRL_BYTES, dl, MVT::i128, Value, offset);
989 rlow = DAG.getNode(ISD::AND, dl, MVT::i128, rlow, lowmask);
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000990 SDValue rhi = DAG.getNode(SPUISD::SHL_BYTES, dl, MVT::i128, Value,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +0000991 offset_compl);
992
993 // Merge the old data and the new data and store the results
Wesley Peckbf17cfa2010-11-23 03:31:01 +0000994 // Need to convert vectors here to integer as 'OR'ing floats assert
995 rlow = DAG.getNode(ISD::OR, dl, MVT::i128,
996 DAG.getNode(ISD::BITCAST, dl, MVT::i128, low),
997 DAG.getNode(ISD::BITCAST, dl, MVT::i128, rlow));
998 rhi = DAG.getNode(ISD::OR, dl, MVT::i128,
999 DAG.getNode(ISD::BITCAST, dl, MVT::i128, hi),
1000 DAG.getNode(ISD::BITCAST, dl, MVT::i128, rhi));
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +00001001
1002 low = DAG.getStore(the_chain, dl, rlow, basePtr,
1003 lowMemPtr,
1004 SN->isVolatile(), SN->isNonTemporal(), 16);
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001005 hi = DAG.getStore(the_chain, dl, rhi,
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +00001006 DAG.getNode(ISD::ADD, dl, PtrVT, basePtr,
1007 DAG.getConstant( 16, PtrVT)),
1008 highMemPtr,
1009 SN->isVolatile(), SN->isNonTemporal(), 16);
1010 result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, low.getValue(0),
1011 hi.getValue(0));
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001012 }
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +00001013
1014 return result;
Scott Michel266bc8f2007-12-04 22:23:35 +00001015}
1016
Scott Michel94bd57e2009-01-15 04:41:47 +00001017//! Generate the address of a constant pool entry.
Dan Gohman7db949d2009-08-07 01:32:21 +00001018static SDValue
Dan Gohman475871a2008-07-27 21:46:04 +00001019LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Owen Andersone50ed302009-08-10 22:56:29 +00001020 EVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001021 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
Dan Gohman46510a72010-04-15 01:51:59 +00001022 const Constant *C = CP->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +00001023 SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
1024 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001025 const TargetMachine &TM = DAG.getTarget();
Dale Johannesende064702009-02-06 21:50:26 +00001026 // FIXME there is no actual debug info here
1027 DebugLoc dl = Op.getDebugLoc();
Scott Michel266bc8f2007-12-04 22:23:35 +00001028
1029 if (TM.getRelocationModel() == Reloc::Static) {
1030 if (!ST->usingLargeMem()) {
Dan Gohman475871a2008-07-27 21:46:04 +00001031 // Just return the SDValue with the constant pool address in it.
Dale Johannesende064702009-02-06 21:50:26 +00001032 return DAG.getNode(SPUISD::AFormAddr, dl, PtrVT, CPI, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001033 } else {
Dale Johannesende064702009-02-06 21:50:26 +00001034 SDValue Hi = DAG.getNode(SPUISD::Hi, dl, PtrVT, CPI, Zero);
1035 SDValue Lo = DAG.getNode(SPUISD::Lo, dl, PtrVT, CPI, Zero);
1036 return DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Hi, Lo);
Scott Michel266bc8f2007-12-04 22:23:35 +00001037 }
1038 }
1039
Torok Edwinc23197a2009-07-14 16:55:14 +00001040 llvm_unreachable("LowerConstantPool: Relocation model other than static"
Torok Edwin481d15a2009-07-14 12:22:58 +00001041 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +00001042 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001043}
1044
Scott Michel94bd57e2009-01-15 04:41:47 +00001045//! Alternate entry point for generating the address of a constant pool entry
1046SDValue
1047SPU::LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUTargetMachine &TM) {
1048 return ::LowerConstantPool(Op, DAG, TM.getSubtargetImpl());
1049}
1050
Dan Gohman475871a2008-07-27 21:46:04 +00001051static SDValue
1052LowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Owen Andersone50ed302009-08-10 22:56:29 +00001053 EVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001054 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +00001055 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
1056 SDValue Zero = DAG.getConstant(0, PtrVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001057 const TargetMachine &TM = DAG.getTarget();
Dale Johannesende064702009-02-06 21:50:26 +00001058 // FIXME there is no actual debug info here
1059 DebugLoc dl = Op.getDebugLoc();
Scott Michel266bc8f2007-12-04 22:23:35 +00001060
1061 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michela59d4692008-02-23 18:41:37 +00001062 if (!ST->usingLargeMem()) {
Dale Johannesende064702009-02-06 21:50:26 +00001063 return DAG.getNode(SPUISD::AFormAddr, dl, PtrVT, JTI, Zero);
Scott Michela59d4692008-02-23 18:41:37 +00001064 } else {
Dale Johannesende064702009-02-06 21:50:26 +00001065 SDValue Hi = DAG.getNode(SPUISD::Hi, dl, PtrVT, JTI, Zero);
1066 SDValue Lo = DAG.getNode(SPUISD::Lo, dl, PtrVT, JTI, Zero);
1067 return DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Hi, Lo);
Scott Michela59d4692008-02-23 18:41:37 +00001068 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001069 }
1070
Torok Edwinc23197a2009-07-14 16:55:14 +00001071 llvm_unreachable("LowerJumpTable: Relocation model other than static"
Torok Edwin481d15a2009-07-14 12:22:58 +00001072 " not supported.");
Dan Gohman475871a2008-07-27 21:46:04 +00001073 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001074}
1075
Dan Gohman475871a2008-07-27 21:46:04 +00001076static SDValue
1077LowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
Owen Andersone50ed302009-08-10 22:56:29 +00001078 EVT PtrVT = Op.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001079 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
Dan Gohman46510a72010-04-15 01:51:59 +00001080 const GlobalValue *GV = GSDN->getGlobal();
Devang Patel0d881da2010-07-06 22:08:15 +00001081 SDValue GA = DAG.getTargetGlobalAddress(GV, Op.getDebugLoc(),
1082 PtrVT, GSDN->getOffset());
Scott Michel266bc8f2007-12-04 22:23:35 +00001083 const TargetMachine &TM = DAG.getTarget();
Dan Gohman475871a2008-07-27 21:46:04 +00001084 SDValue Zero = DAG.getConstant(0, PtrVT);
Dale Johannesende064702009-02-06 21:50:26 +00001085 // FIXME there is no actual debug info here
1086 DebugLoc dl = Op.getDebugLoc();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001087
Scott Michel266bc8f2007-12-04 22:23:35 +00001088 if (TM.getRelocationModel() == Reloc::Static) {
Scott Michel053c1da2008-01-29 02:16:57 +00001089 if (!ST->usingLargeMem()) {
Dale Johannesende064702009-02-06 21:50:26 +00001090 return DAG.getNode(SPUISD::AFormAddr, dl, PtrVT, GA, Zero);
Scott Michel053c1da2008-01-29 02:16:57 +00001091 } else {
Dale Johannesende064702009-02-06 21:50:26 +00001092 SDValue Hi = DAG.getNode(SPUISD::Hi, dl, PtrVT, GA, Zero);
1093 SDValue Lo = DAG.getNode(SPUISD::Lo, dl, PtrVT, GA, Zero);
1094 return DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Hi, Lo);
Scott Michel053c1da2008-01-29 02:16:57 +00001095 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001096 } else {
Chris Lattner75361b62010-04-07 22:58:41 +00001097 report_fatal_error("LowerGlobalAddress: Relocation model other than static"
Torok Edwindac237e2009-07-08 20:53:28 +00001098 "not supported.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001099 /*NOTREACHED*/
1100 }
1101
Dan Gohman475871a2008-07-27 21:46:04 +00001102 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001103}
1104
Nate Begemanccef5802008-02-14 18:43:04 +00001105//! Custom lower double precision floating point constants
Dan Gohman475871a2008-07-27 21:46:04 +00001106static SDValue
1107LowerConstantFP(SDValue Op, SelectionDAG &DAG) {
Owen Andersone50ed302009-08-10 22:56:29 +00001108 EVT VT = Op.getValueType();
Dale Johannesende064702009-02-06 21:50:26 +00001109 // FIXME there is no actual debug info here
1110 DebugLoc dl = Op.getDebugLoc();
Scott Michel266bc8f2007-12-04 22:23:35 +00001111
Owen Anderson825b72b2009-08-11 20:47:22 +00001112 if (VT == MVT::f64) {
Scott Michel1a6cdb62008-12-01 17:56:02 +00001113 ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
1114
1115 assert((FP != 0) &&
1116 "LowerConstantFP: Node is not ConstantFPSDNode");
Scott Michel1df30c42008-12-29 03:23:36 +00001117
Scott Michel170783a2007-12-19 20:15:47 +00001118 uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
Owen Anderson825b72b2009-08-11 20:47:22 +00001119 SDValue T = DAG.getConstant(dbits, MVT::i64);
1120 SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64, T, T);
Dale Johannesende064702009-02-06 21:50:26 +00001121 return DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT,
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001122 DAG.getNode(ISD::BITCAST, dl, MVT::v2f64, Tvec));
Scott Michel266bc8f2007-12-04 22:23:35 +00001123 }
1124
Dan Gohman475871a2008-07-27 21:46:04 +00001125 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001126}
1127
Dan Gohman98ca4f22009-08-05 01:29:28 +00001128SDValue
1129SPUTargetLowering::LowerFormalArguments(SDValue Chain,
Sandeep Patel65c3c8f2009-09-02 08:44:58 +00001130 CallingConv::ID CallConv, bool isVarArg,
Dan Gohman98ca4f22009-08-05 01:29:28 +00001131 const SmallVectorImpl<ISD::InputArg>
1132 &Ins,
1133 DebugLoc dl, SelectionDAG &DAG,
Dan Gohmand858e902010-04-17 15:26:15 +00001134 SmallVectorImpl<SDValue> &InVals)
1135 const {
Dan Gohman98ca4f22009-08-05 01:29:28 +00001136
Scott Michel266bc8f2007-12-04 22:23:35 +00001137 MachineFunction &MF = DAG.getMachineFunction();
1138 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner84bc5422007-12-31 04:13:23 +00001139 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Dan Gohman1e93df62010-04-17 14:41:14 +00001140 SPUFunctionInfo *FuncInfo = MF.getInfo<SPUFunctionInfo>();
Scott Michel266bc8f2007-12-04 22:23:35 +00001141
Anton Korobeynikov16c29b52011-01-10 12:39:04 +00001142 unsigned ArgOffset = SPUFrameLowering::minStackSize();
Scott Michel266bc8f2007-12-04 22:23:35 +00001143 unsigned ArgRegIdx = 0;
Anton Korobeynikov16c29b52011-01-10 12:39:04 +00001144 unsigned StackSlotSize = SPUFrameLowering::stackSlotSize();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001145
Owen Andersone50ed302009-08-10 22:56:29 +00001146 EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001147
Kalle Raiskilad258c492010-07-08 21:15:22 +00001148 SmallVector<CCValAssign, 16> ArgLocs;
Eric Christopher471e4222011-06-08 23:55:35 +00001149 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
1150 getTargetMachine(), ArgLocs, *DAG.getContext());
Kalle Raiskilad258c492010-07-08 21:15:22 +00001151 // FIXME: allow for other calling conventions
1152 CCInfo.AnalyzeFormalArguments(Ins, CCC_SPU);
1153
Scott Michel266bc8f2007-12-04 22:23:35 +00001154 // Add DAG nodes to load the arguments or copy them out of registers.
Dan Gohman98ca4f22009-08-05 01:29:28 +00001155 for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) {
Owen Andersone50ed302009-08-10 22:56:29 +00001156 EVT ObjectVT = Ins[ArgNo].VT;
Duncan Sands83ec4b62008-06-06 12:08:01 +00001157 unsigned ObjSize = ObjectVT.getSizeInBits()/8;
Scott Micheld976c212008-10-30 01:51:48 +00001158 SDValue ArgVal;
Kalle Raiskilad258c492010-07-08 21:15:22 +00001159 CCValAssign &VA = ArgLocs[ArgNo];
Scott Michel266bc8f2007-12-04 22:23:35 +00001160
Kalle Raiskilad258c492010-07-08 21:15:22 +00001161 if (VA.isRegLoc()) {
Scott Micheld976c212008-10-30 01:51:48 +00001162 const TargetRegisterClass *ArgRegClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001163
Owen Anderson825b72b2009-08-11 20:47:22 +00001164 switch (ObjectVT.getSimpleVT().SimpleTy) {
Benjamin Kramer1bd73352010-04-08 10:44:28 +00001165 default:
1166 report_fatal_error("LowerFormalArguments Unhandled argument type: " +
1167 Twine(ObjectVT.getEVTString()));
Owen Anderson825b72b2009-08-11 20:47:22 +00001168 case MVT::i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +00001169 ArgRegClass = &SPU::R8CRegClass;
1170 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001171 case MVT::i16:
Scott Michel9c0c6b22008-11-21 02:56:16 +00001172 ArgRegClass = &SPU::R16CRegClass;
1173 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001174 case MVT::i32:
Scott Michel9c0c6b22008-11-21 02:56:16 +00001175 ArgRegClass = &SPU::R32CRegClass;
1176 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001177 case MVT::i64:
Scott Michel9c0c6b22008-11-21 02:56:16 +00001178 ArgRegClass = &SPU::R64CRegClass;
1179 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001180 case MVT::i128:
Scott Micheldd950092009-01-06 03:36:14 +00001181 ArgRegClass = &SPU::GPRCRegClass;
1182 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001183 case MVT::f32:
Scott Michel9c0c6b22008-11-21 02:56:16 +00001184 ArgRegClass = &SPU::R32FPRegClass;
1185 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001186 case MVT::f64:
Scott Michel9c0c6b22008-11-21 02:56:16 +00001187 ArgRegClass = &SPU::R64FPRegClass;
1188 break;
Owen Anderson825b72b2009-08-11 20:47:22 +00001189 case MVT::v2f64:
1190 case MVT::v4f32:
1191 case MVT::v2i64:
1192 case MVT::v4i32:
1193 case MVT::v8i16:
1194 case MVT::v16i8:
Scott Michel9c0c6b22008-11-21 02:56:16 +00001195 ArgRegClass = &SPU::VECREGRegClass;
1196 break;
Scott Micheld976c212008-10-30 01:51:48 +00001197 }
1198
1199 unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
Kalle Raiskilad258c492010-07-08 21:15:22 +00001200 RegInfo.addLiveIn(VA.getLocReg(), VReg);
Dan Gohman98ca4f22009-08-05 01:29:28 +00001201 ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT);
Scott Micheld976c212008-10-30 01:51:48 +00001202 ++ArgRegIdx;
1203 } else {
1204 // We need to load the argument to a virtual register if we determined
1205 // above that we ran out of physical registers of the appropriate type
1206 // or we're forced to do vararg
Evan Chenged2ae132010-07-03 00:40:23 +00001207 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset, true);
Dan Gohman475871a2008-07-27 21:46:04 +00001208 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
Chris Lattnere8639032010-09-21 06:22:23 +00001209 ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, MachinePointerInfo(),
Pete Cooperd752e0f2011-11-08 18:42:53 +00001210 false, false, false, 0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001211 ArgOffset += StackSlotSize;
1212 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001213
Dan Gohman98ca4f22009-08-05 01:29:28 +00001214 InVals.push_back(ArgVal);
Scott Micheld976c212008-10-30 01:51:48 +00001215 // Update the chain
Dan Gohman98ca4f22009-08-05 01:29:28 +00001216 Chain = ArgVal.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001217 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001218
Scott Micheld976c212008-10-30 01:51:48 +00001219 // vararg handling:
Scott Michel266bc8f2007-12-04 22:23:35 +00001220 if (isVarArg) {
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001221 // FIXME: we should be able to query the argument registers from
1222 // tablegen generated code.
Kalle Raiskilad258c492010-07-08 21:15:22 +00001223 static const unsigned ArgRegs[] = {
1224 SPU::R3, SPU::R4, SPU::R5, SPU::R6, SPU::R7, SPU::R8, SPU::R9,
1225 SPU::R10, SPU::R11, SPU::R12, SPU::R13, SPU::R14, SPU::R15, SPU::R16,
1226 SPU::R17, SPU::R18, SPU::R19, SPU::R20, SPU::R21, SPU::R22, SPU::R23,
1227 SPU::R24, SPU::R25, SPU::R26, SPU::R27, SPU::R28, SPU::R29, SPU::R30,
1228 SPU::R31, SPU::R32, SPU::R33, SPU::R34, SPU::R35, SPU::R36, SPU::R37,
1229 SPU::R38, SPU::R39, SPU::R40, SPU::R41, SPU::R42, SPU::R43, SPU::R44,
1230 SPU::R45, SPU::R46, SPU::R47, SPU::R48, SPU::R49, SPU::R50, SPU::R51,
1231 SPU::R52, SPU::R53, SPU::R54, SPU::R55, SPU::R56, SPU::R57, SPU::R58,
1232 SPU::R59, SPU::R60, SPU::R61, SPU::R62, SPU::R63, SPU::R64, SPU::R65,
1233 SPU::R66, SPU::R67, SPU::R68, SPU::R69, SPU::R70, SPU::R71, SPU::R72,
1234 SPU::R73, SPU::R74, SPU::R75, SPU::R76, SPU::R77, SPU::R78, SPU::R79
1235 };
1236 // size of ArgRegs array
1237 unsigned NumArgRegs = 77;
1238
Scott Micheld976c212008-10-30 01:51:48 +00001239 // We will spill (79-3)+1 registers to the stack
1240 SmallVector<SDValue, 79-3+1> MemOps;
1241
1242 // Create the frame slot
Scott Michel266bc8f2007-12-04 22:23:35 +00001243 for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
Dan Gohman1e93df62010-04-17 14:41:14 +00001244 FuncInfo->setVarArgsFrameIndex(
Evan Chenged2ae132010-07-03 00:40:23 +00001245 MFI->CreateFixedObject(StackSlotSize, ArgOffset, true));
Dan Gohman1e93df62010-04-17 14:41:14 +00001246 SDValue FIN = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
Cameron Zwarich055cdfc2011-05-19 04:44:19 +00001247 unsigned VReg = MF.addLiveIn(ArgRegs[ArgRegIdx], &SPU::VECREGRegClass);
Chris Lattnere27e02b2010-03-29 17:38:47 +00001248 SDValue ArgVal = DAG.getRegister(VReg, MVT::v16i8);
Chris Lattner6229d0a2010-09-21 18:41:36 +00001249 SDValue Store = DAG.getStore(Chain, dl, ArgVal, FIN, MachinePointerInfo(),
David Greene73657df2010-02-15 16:55:58 +00001250 false, false, 0);
Dan Gohman98ca4f22009-08-05 01:29:28 +00001251 Chain = Store.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00001252 MemOps.push_back(Store);
Scott Micheld976c212008-10-30 01:51:48 +00001253
1254 // Increment address by stack slot size for the next stored argument
1255 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001256 }
1257 if (!MemOps.empty())
Owen Anderson825b72b2009-08-11 20:47:22 +00001258 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Dan Gohman98ca4f22009-08-05 01:29:28 +00001259 &MemOps[0], MemOps.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001260 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001261
Dan Gohman98ca4f22009-08-05 01:29:28 +00001262 return Chain;
Scott Michel266bc8f2007-12-04 22:23:35 +00001263}
1264
1265/// isLSAAddress - Return the immediate to use if the specified
1266/// value is representable as a LSA address.
Dan Gohman475871a2008-07-27 21:46:04 +00001267static SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001268 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +00001269 if (!C) return 0;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001270
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001271 int Addr = C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001272 if ((Addr & 3) != 0 || // Low 2 bits are implicitly zero.
1273 (Addr << 14 >> 14) != Addr)
1274 return 0; // Top 14 bits have to be sext of immediate.
Scott Michel5af8f0e2008-07-16 17:17:29 +00001275
Owen Anderson825b72b2009-08-11 20:47:22 +00001276 return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +00001277}
1278
Dan Gohman98ca4f22009-08-05 01:29:28 +00001279SDValue
Evan Cheng022d9e12010-02-02 23:55:14 +00001280SPUTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
Sandeep Patel65c3c8f2009-09-02 08:44:58 +00001281 CallingConv::ID CallConv, bool isVarArg,
Evan Cheng0c439eb2010-01-27 00:07:07 +00001282 bool &isTailCall,
Dan Gohman98ca4f22009-08-05 01:29:28 +00001283 const SmallVectorImpl<ISD::OutputArg> &Outs,
Dan Gohmanc9403652010-07-07 15:54:55 +00001284 const SmallVectorImpl<SDValue> &OutVals,
Dan Gohman98ca4f22009-08-05 01:29:28 +00001285 const SmallVectorImpl<ISD::InputArg> &Ins,
1286 DebugLoc dl, SelectionDAG &DAG,
Dan Gohmand858e902010-04-17 15:26:15 +00001287 SmallVectorImpl<SDValue> &InVals) const {
Evan Cheng0c439eb2010-01-27 00:07:07 +00001288 // CellSPU target does not yet support tail call optimization.
1289 isTailCall = false;
Dan Gohman98ca4f22009-08-05 01:29:28 +00001290
1291 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
1292 unsigned NumOps = Outs.size();
Anton Korobeynikov16c29b52011-01-10 12:39:04 +00001293 unsigned StackSlotSize = SPUFrameLowering::stackSlotSize();
Kalle Raiskilad258c492010-07-08 21:15:22 +00001294
1295 SmallVector<CCValAssign, 16> ArgLocs;
Eric Christopher471e4222011-06-08 23:55:35 +00001296 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
1297 getTargetMachine(), ArgLocs, *DAG.getContext());
Kalle Raiskilad258c492010-07-08 21:15:22 +00001298 // FIXME: allow for other calling conventions
1299 CCInfo.AnalyzeCallOperands(Outs, CCC_SPU);
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001300
Kalle Raiskilad258c492010-07-08 21:15:22 +00001301 const unsigned NumArgRegs = ArgLocs.size();
1302
Scott Michel266bc8f2007-12-04 22:23:35 +00001303
1304 // Handy pointer type
Owen Andersone50ed302009-08-10 22:56:29 +00001305 EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001306
Scott Michel266bc8f2007-12-04 22:23:35 +00001307 // Set up a copy of the stack pointer for use loading and storing any
1308 // arguments that may not fit in the registers available for argument
1309 // passing.
Owen Anderson825b72b2009-08-11 20:47:22 +00001310 SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001311
Scott Michel266bc8f2007-12-04 22:23:35 +00001312 // Figure out which arguments are going to go in registers, and which in
1313 // memory.
Anton Korobeynikov16c29b52011-01-10 12:39:04 +00001314 unsigned ArgOffset = SPUFrameLowering::minStackSize(); // Just below [LR]
Scott Michel266bc8f2007-12-04 22:23:35 +00001315 unsigned ArgRegIdx = 0;
1316
1317 // Keep track of registers passing arguments
Dan Gohman475871a2008-07-27 21:46:04 +00001318 std::vector<std::pair<unsigned, SDValue> > RegsToPass;
Scott Michel266bc8f2007-12-04 22:23:35 +00001319 // And the arguments passed on the stack
Dan Gohman475871a2008-07-27 21:46:04 +00001320 SmallVector<SDValue, 8> MemOpChains;
Scott Michel266bc8f2007-12-04 22:23:35 +00001321
Kalle Raiskilad258c492010-07-08 21:15:22 +00001322 for (; ArgRegIdx != NumOps; ++ArgRegIdx) {
1323 SDValue Arg = OutVals[ArgRegIdx];
1324 CCValAssign &VA = ArgLocs[ArgRegIdx];
Scott Michel5af8f0e2008-07-16 17:17:29 +00001325
Scott Michel266bc8f2007-12-04 22:23:35 +00001326 // PtrOff will be used to store the current argument to the stack if a
1327 // register cannot be found for it.
Dan Gohman475871a2008-07-27 21:46:04 +00001328 SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
Dale Johannesen33c960f2009-02-04 20:06:27 +00001329 PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, PtrOff);
Scott Michel266bc8f2007-12-04 22:23:35 +00001330
Owen Anderson825b72b2009-08-11 20:47:22 +00001331 switch (Arg.getValueType().getSimpleVT().SimpleTy) {
Torok Edwinc23197a2009-07-14 16:55:14 +00001332 default: llvm_unreachable("Unexpected ValueType for argument!");
Owen Anderson825b72b2009-08-11 20:47:22 +00001333 case MVT::i8:
1334 case MVT::i16:
1335 case MVT::i32:
1336 case MVT::i64:
1337 case MVT::i128:
Owen Anderson825b72b2009-08-11 20:47:22 +00001338 case MVT::f32:
1339 case MVT::f64:
Owen Anderson825b72b2009-08-11 20:47:22 +00001340 case MVT::v2i64:
1341 case MVT::v2f64:
1342 case MVT::v4f32:
1343 case MVT::v4i32:
1344 case MVT::v8i16:
1345 case MVT::v16i8:
Scott Michel266bc8f2007-12-04 22:23:35 +00001346 if (ArgRegIdx != NumArgRegs) {
Kalle Raiskilad258c492010-07-08 21:15:22 +00001347 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
Scott Michel266bc8f2007-12-04 22:23:35 +00001348 } else {
Chris Lattner6229d0a2010-09-21 18:41:36 +00001349 MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
1350 MachinePointerInfo(),
David Greene73657df2010-02-15 16:55:58 +00001351 false, false, 0));
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001352 ArgOffset += StackSlotSize;
Scott Michel266bc8f2007-12-04 22:23:35 +00001353 }
1354 break;
1355 }
1356 }
1357
Bill Wendlingce90c242009-12-28 01:31:11 +00001358 // Accumulate how many bytes are to be pushed on the stack, including the
1359 // linkage area, and parameter passing area. According to the SPU ABI,
1360 // we minimally need space for [LR] and [SP].
Anton Korobeynikov16c29b52011-01-10 12:39:04 +00001361 unsigned NumStackBytes = ArgOffset - SPUFrameLowering::minStackSize();
Bill Wendlingce90c242009-12-28 01:31:11 +00001362
1363 // Insert a call sequence start
Chris Lattnere563bbc2008-10-11 22:08:30 +00001364 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1365 true));
Scott Michel266bc8f2007-12-04 22:23:35 +00001366
1367 if (!MemOpChains.empty()) {
1368 // Adjust the stack pointer for the stack arguments.
Owen Anderson825b72b2009-08-11 20:47:22 +00001369 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Scott Michel266bc8f2007-12-04 22:23:35 +00001370 &MemOpChains[0], MemOpChains.size());
1371 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001372
Scott Michel266bc8f2007-12-04 22:23:35 +00001373 // Build a sequence of copy-to-reg nodes chained together with token chain
1374 // and flag operands which copy the outgoing args into the appropriate regs.
Dan Gohman475871a2008-07-27 21:46:04 +00001375 SDValue InFlag;
Scott Michel266bc8f2007-12-04 22:23:35 +00001376 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
Scott Michel6e1d1472009-03-16 18:47:25 +00001377 Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
Dale Johannesen33c960f2009-02-04 20:06:27 +00001378 RegsToPass[i].second, InFlag);
Scott Michel266bc8f2007-12-04 22:23:35 +00001379 InFlag = Chain.getValue(1);
1380 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001381
Dan Gohman475871a2008-07-27 21:46:04 +00001382 SmallVector<SDValue, 8> Ops;
Scott Michel266bc8f2007-12-04 22:23:35 +00001383 unsigned CallOpc = SPUISD::CALL;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001384
Bill Wendling056292f2008-09-16 21:48:12 +00001385 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1386 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1387 // node so that legalize doesn't hack it.
Scott Michel19fd42a2008-11-11 03:06:06 +00001388 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Dan Gohman46510a72010-04-15 01:51:59 +00001389 const GlobalValue *GV = G->getGlobal();
Owen Andersone50ed302009-08-10 22:56:29 +00001390 EVT CalleeVT = Callee.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00001391 SDValue Zero = DAG.getConstant(0, PtrVT);
Devang Patel0d881da2010-07-06 22:08:15 +00001392 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, CalleeVT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001393
Scott Michel9de5d0d2008-01-11 02:53:15 +00001394 if (!ST->usingLargeMem()) {
1395 // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1396 // style calls, otherwise, external symbols are BRASL calls. This assumes
1397 // that declared/defined symbols are in the same compilation unit and can
1398 // be reached through PC-relative jumps.
1399 //
1400 // NOTE:
1401 // This may be an unsafe assumption for JIT and really large compilation
1402 // units.
1403 if (GV->isDeclaration()) {
Dale Johannesende064702009-02-06 21:50:26 +00001404 Callee = DAG.getNode(SPUISD::AFormAddr, dl, CalleeVT, GA, Zero);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001405 } else {
Dale Johannesende064702009-02-06 21:50:26 +00001406 Callee = DAG.getNode(SPUISD::PCRelAddr, dl, CalleeVT, GA, Zero);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001407 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001408 } else {
Scott Michel9de5d0d2008-01-11 02:53:15 +00001409 // "Large memory" mode: Turn all calls into indirect calls with a X-form
1410 // address pairs:
Dale Johannesende064702009-02-06 21:50:26 +00001411 Callee = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, GA, Zero);
Scott Michel266bc8f2007-12-04 22:23:35 +00001412 }
Scott Michel1df30c42008-12-29 03:23:36 +00001413 } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
Owen Andersone50ed302009-08-10 22:56:29 +00001414 EVT CalleeVT = Callee.getValueType();
Scott Michel1df30c42008-12-29 03:23:36 +00001415 SDValue Zero = DAG.getConstant(0, PtrVT);
1416 SDValue ExtSym = DAG.getTargetExternalSymbol(S->getSymbol(),
1417 Callee.getValueType());
1418
1419 if (!ST->usingLargeMem()) {
Dale Johannesende064702009-02-06 21:50:26 +00001420 Callee = DAG.getNode(SPUISD::AFormAddr, dl, CalleeVT, ExtSym, Zero);
Scott Michel1df30c42008-12-29 03:23:36 +00001421 } else {
Dale Johannesende064702009-02-06 21:50:26 +00001422 Callee = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, ExtSym, Zero);
Scott Michel1df30c42008-12-29 03:23:36 +00001423 }
1424 } else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001425 // If this is an absolute destination address that appears to be a legal
1426 // local store address, use the munged value.
Dan Gohman475871a2008-07-27 21:46:04 +00001427 Callee = SDValue(Dest, 0);
Scott Michel9de5d0d2008-01-11 02:53:15 +00001428 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001429
1430 Ops.push_back(Chain);
1431 Ops.push_back(Callee);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001432
Scott Michel266bc8f2007-12-04 22:23:35 +00001433 // Add argument registers to the end of the list so that they are known live
1434 // into the call.
1435 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
Scott Michel5af8f0e2008-07-16 17:17:29 +00001436 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
Scott Michel266bc8f2007-12-04 22:23:35 +00001437 RegsToPass[i].second.getValueType()));
Scott Michel5af8f0e2008-07-16 17:17:29 +00001438
Gabor Greifba36cb52008-08-28 21:40:38 +00001439 if (InFlag.getNode())
Scott Michel266bc8f2007-12-04 22:23:35 +00001440 Ops.push_back(InFlag);
Duncan Sands4bdcb612008-07-02 17:40:58 +00001441 // Returns a chain and a flag for retval copy to use.
Chris Lattnerf1b4eaf2010-12-21 02:38:05 +00001442 Chain = DAG.getNode(CallOpc, dl, DAG.getVTList(MVT::Other, MVT::Glue),
Duncan Sands4bdcb612008-07-02 17:40:58 +00001443 &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001444 InFlag = Chain.getValue(1);
1445
Chris Lattnere563bbc2008-10-11 22:08:30 +00001446 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1447 DAG.getIntPtrConstant(0, true), InFlag);
Dan Gohman98ca4f22009-08-05 01:29:28 +00001448 if (!Ins.empty())
Evan Chengebaaa912008-02-05 22:44:06 +00001449 InFlag = Chain.getValue(1);
1450
Dan Gohman98ca4f22009-08-05 01:29:28 +00001451 // If the function returns void, just return the chain.
1452 if (Ins.empty())
1453 return Chain;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001454
Kalle Raiskila55aebef2010-08-24 11:50:48 +00001455 // Now handle the return value(s)
1456 SmallVector<CCValAssign, 16> RVLocs;
Eric Christopher471e4222011-06-08 23:55:35 +00001457 CCState CCRetInfo(CallConv, isVarArg, DAG.getMachineFunction(),
1458 getTargetMachine(), RVLocs, *DAG.getContext());
Kalle Raiskila55aebef2010-08-24 11:50:48 +00001459 CCRetInfo.AnalyzeCallResult(Ins, CCC_SPU);
1460
1461
Scott Michel266bc8f2007-12-04 22:23:35 +00001462 // If the call has results, copy the values out of the ret val registers.
Kalle Raiskila55aebef2010-08-24 11:50:48 +00001463 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1464 CCValAssign VA = RVLocs[i];
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001465
Kalle Raiskila55aebef2010-08-24 11:50:48 +00001466 SDValue Val = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(),
1467 InFlag);
1468 Chain = Val.getValue(1);
1469 InFlag = Val.getValue(2);
1470 InVals.push_back(Val);
1471 }
Duncan Sands4bdcb612008-07-02 17:40:58 +00001472
Dan Gohman98ca4f22009-08-05 01:29:28 +00001473 return Chain;
Scott Michel266bc8f2007-12-04 22:23:35 +00001474}
1475
Dan Gohman98ca4f22009-08-05 01:29:28 +00001476SDValue
1477SPUTargetLowering::LowerReturn(SDValue Chain,
Sandeep Patel65c3c8f2009-09-02 08:44:58 +00001478 CallingConv::ID CallConv, bool isVarArg,
Dan Gohman98ca4f22009-08-05 01:29:28 +00001479 const SmallVectorImpl<ISD::OutputArg> &Outs,
Dan Gohmanc9403652010-07-07 15:54:55 +00001480 const SmallVectorImpl<SDValue> &OutVals,
Dan Gohmand858e902010-04-17 15:26:15 +00001481 DebugLoc dl, SelectionDAG &DAG) const {
Dan Gohman98ca4f22009-08-05 01:29:28 +00001482
Scott Michel266bc8f2007-12-04 22:23:35 +00001483 SmallVector<CCValAssign, 16> RVLocs;
Eric Christopher471e4222011-06-08 23:55:35 +00001484 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
1485 getTargetMachine(), RVLocs, *DAG.getContext());
Dan Gohman98ca4f22009-08-05 01:29:28 +00001486 CCInfo.AnalyzeReturn(Outs, RetCC_SPU);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001487
Scott Michel266bc8f2007-12-04 22:23:35 +00001488 // If this is the first return lowered for this function, add the regs to the
1489 // liveout set for the function.
Chris Lattner84bc5422007-12-31 04:13:23 +00001490 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001491 for (unsigned i = 0; i != RVLocs.size(); ++i)
Chris Lattner84bc5422007-12-31 04:13:23 +00001492 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
Scott Michel266bc8f2007-12-04 22:23:35 +00001493 }
1494
Dan Gohman475871a2008-07-27 21:46:04 +00001495 SDValue Flag;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001496
Scott Michel266bc8f2007-12-04 22:23:35 +00001497 // Copy the result values into the output registers.
1498 for (unsigned i = 0; i != RVLocs.size(); ++i) {
1499 CCValAssign &VA = RVLocs[i];
1500 assert(VA.isRegLoc() && "Can only return in registers!");
Dale Johannesena05dca42009-02-04 23:02:30 +00001501 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
Dan Gohmanc9403652010-07-07 15:54:55 +00001502 OutVals[i], Flag);
Scott Michel266bc8f2007-12-04 22:23:35 +00001503 Flag = Chain.getValue(1);
1504 }
1505
Gabor Greifba36cb52008-08-28 21:40:38 +00001506 if (Flag.getNode())
Owen Anderson825b72b2009-08-11 20:47:22 +00001507 return DAG.getNode(SPUISD::RET_FLAG, dl, MVT::Other, Chain, Flag);
Scott Michel266bc8f2007-12-04 22:23:35 +00001508 else
Owen Anderson825b72b2009-08-11 20:47:22 +00001509 return DAG.getNode(SPUISD::RET_FLAG, dl, MVT::Other, Chain);
Scott Michel266bc8f2007-12-04 22:23:35 +00001510}
1511
1512
1513//===----------------------------------------------------------------------===//
1514// Vector related lowering:
1515//===----------------------------------------------------------------------===//
1516
1517static ConstantSDNode *
1518getVecImm(SDNode *N) {
Dan Gohman475871a2008-07-27 21:46:04 +00001519 SDValue OpVal(0, 0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001520
Scott Michel266bc8f2007-12-04 22:23:35 +00001521 // Check to see if this buildvec has a single non-undef value in its elements.
1522 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1523 if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
Gabor Greifba36cb52008-08-28 21:40:38 +00001524 if (OpVal.getNode() == 0)
Scott Michel266bc8f2007-12-04 22:23:35 +00001525 OpVal = N->getOperand(i);
1526 else if (OpVal != N->getOperand(i))
1527 return 0;
1528 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001529
Gabor Greifba36cb52008-08-28 21:40:38 +00001530 if (OpVal.getNode() != 0) {
Scott Michel19fd42a2008-11-11 03:06:06 +00001531 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001532 return CN;
1533 }
1534 }
1535
Scott Michel7ea02ff2009-03-17 01:15:45 +00001536 return 0;
Scott Michel266bc8f2007-12-04 22:23:35 +00001537}
1538
1539/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1540/// and the value fits into an unsigned 18-bit constant, and if so, return the
1541/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001542SDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
Owen Andersone50ed302009-08-10 22:56:29 +00001543 EVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001544 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001545 uint64_t Value = CN->getZExtValue();
Owen Anderson825b72b2009-08-11 20:47:22 +00001546 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001547 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001548 uint32_t upper = uint32_t(UValue >> 32);
1549 uint32_t lower = uint32_t(UValue);
1550 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001551 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001552 Value = Value >> 32;
1553 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001554 if (Value <= 0x3ffff)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001555 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001556 }
1557
Dan Gohman475871a2008-07-27 21:46:04 +00001558 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001559}
1560
1561/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1562/// and the value fits into a signed 16-bit constant, and if so, return the
1563/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001564SDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
Owen Andersone50ed302009-08-10 22:56:29 +00001565 EVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001566 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001567 int64_t Value = CN->getSExtValue();
Owen Anderson825b72b2009-08-11 20:47:22 +00001568 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001569 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001570 uint32_t upper = uint32_t(UValue >> 32);
1571 uint32_t lower = uint32_t(UValue);
1572 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001573 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001574 Value = Value >> 32;
1575 }
Scott Michelad2715e2008-03-05 23:02:02 +00001576 if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
Dan Gohmanfa210d82008-11-05 02:06:09 +00001577 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001578 }
1579 }
1580
Dan Gohman475871a2008-07-27 21:46:04 +00001581 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001582}
1583
1584/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1585/// and the value fits into a signed 10-bit constant, and if so, return the
1586/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001587SDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
Owen Andersone50ed302009-08-10 22:56:29 +00001588 EVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001589 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohman7810bfe2008-09-26 21:54:37 +00001590 int64_t Value = CN->getSExtValue();
Owen Anderson825b72b2009-08-11 20:47:22 +00001591 if (ValueType == MVT::i64) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001592 uint64_t UValue = CN->getZExtValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001593 uint32_t upper = uint32_t(UValue >> 32);
1594 uint32_t lower = uint32_t(UValue);
1595 if (upper != lower)
Dan Gohman475871a2008-07-27 21:46:04 +00001596 return SDValue();
Scott Michel4cb8bd82008-03-06 04:02:54 +00001597 Value = Value >> 32;
1598 }
Benjamin Kramer7e09deb2010-03-29 19:07:58 +00001599 if (isInt<10>(Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001600 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001601 }
1602
Dan Gohman475871a2008-07-27 21:46:04 +00001603 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001604}
1605
1606/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1607/// and the value fits into a signed 8-bit constant, and if so, return the
1608/// constant.
1609///
1610/// @note: The incoming vector is v16i8 because that's the only way we can load
1611/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1612/// same value.
Dan Gohman475871a2008-07-27 21:46:04 +00001613SDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
Owen Andersone50ed302009-08-10 22:56:29 +00001614 EVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001615 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001616 int Value = (int) CN->getZExtValue();
Owen Anderson825b72b2009-08-11 20:47:22 +00001617 if (ValueType == MVT::i16
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001618 && Value <= 0xffff /* truncated from uint64_t */
1619 && ((short) Value >> 8) == ((short) Value & 0xff))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001620 return DAG.getTargetConstant(Value & 0xff, ValueType);
Owen Anderson825b72b2009-08-11 20:47:22 +00001621 else if (ValueType == MVT::i8
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001622 && (Value & 0xff) == Value)
Dan Gohmanfa210d82008-11-05 02:06:09 +00001623 return DAG.getTargetConstant(Value, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001624 }
1625
Dan Gohman475871a2008-07-27 21:46:04 +00001626 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001627}
1628
1629/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1630/// and the value fits into a signed 16-bit constant, and if so, return the
1631/// constant
Dan Gohman475871a2008-07-27 21:46:04 +00001632SDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
Owen Andersone50ed302009-08-10 22:56:29 +00001633 EVT ValueType) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001634 if (ConstantSDNode *CN = getVecImm(N)) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001635 uint64_t Value = CN->getZExtValue();
Owen Anderson825b72b2009-08-11 20:47:22 +00001636 if ((ValueType == MVT::i32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001637 && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
Owen Anderson825b72b2009-08-11 20:47:22 +00001638 || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
Dan Gohmanfa210d82008-11-05 02:06:09 +00001639 return DAG.getTargetConstant(Value >> 16, ValueType);
Scott Michel266bc8f2007-12-04 22:23:35 +00001640 }
1641
Dan Gohman475871a2008-07-27 21:46:04 +00001642 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001643}
1644
1645/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001646SDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001647 if (ConstantSDNode *CN = getVecImm(N)) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001648 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00001649 }
1650
Dan Gohman475871a2008-07-27 21:46:04 +00001651 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001652}
1653
1654/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
Dan Gohman475871a2008-07-27 21:46:04 +00001655SDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001656 if (ConstantSDNode *CN = getVecImm(N)) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001657 return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
Scott Michel266bc8f2007-12-04 22:23:35 +00001658 }
1659
Dan Gohman475871a2008-07-27 21:46:04 +00001660 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001661}
1662
Scott Micheld1e8d9c2009-01-21 04:58:48 +00001663//! Lower a BUILD_VECTOR instruction creatively:
Dan Gohman7db949d2009-08-07 01:32:21 +00001664static SDValue
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001665LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
Owen Andersone50ed302009-08-10 22:56:29 +00001666 EVT VT = Op.getValueType();
1667 EVT EltVT = VT.getVectorElementType();
Dale Johannesened2eee62009-02-06 01:31:28 +00001668 DebugLoc dl = Op.getDebugLoc();
Scott Michel7ea02ff2009-03-17 01:15:45 +00001669 BuildVectorSDNode *BCN = dyn_cast<BuildVectorSDNode>(Op.getNode());
1670 assert(BCN != 0 && "Expected BuildVectorSDNode in SPU LowerBUILD_VECTOR");
1671 unsigned minSplatBits = EltVT.getSizeInBits();
1672
1673 if (minSplatBits < 16)
1674 minSplatBits = 16;
1675
1676 APInt APSplatBits, APSplatUndef;
1677 unsigned SplatBitSize;
1678 bool HasAnyUndefs;
1679
1680 if (!BCN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize,
1681 HasAnyUndefs, minSplatBits)
1682 || minSplatBits < SplatBitSize)
1683 return SDValue(); // Wasn't a constant vector or splat exceeded min
1684
1685 uint64_t SplatBits = APSplatBits.getZExtValue();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001686
Owen Anderson825b72b2009-08-11 20:47:22 +00001687 switch (VT.getSimpleVT().SimpleTy) {
Benjamin Kramer1bd73352010-04-08 10:44:28 +00001688 default:
1689 report_fatal_error("CellSPU: Unhandled VT in LowerBUILD_VECTOR, VT = " +
1690 Twine(VT.getEVTString()));
Scott Micheld1e8d9c2009-01-21 04:58:48 +00001691 /*NOTREACHED*/
Owen Anderson825b72b2009-08-11 20:47:22 +00001692 case MVT::v4f32: {
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001693 uint32_t Value32 = uint32_t(SplatBits);
Chris Lattnere7fa1f22009-03-26 05:29:34 +00001694 assert(SplatBitSize == 32
Scott Michel7f9ba9b2008-01-30 02:55:46 +00001695 && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001696 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Owen Anderson825b72b2009-08-11 20:47:22 +00001697 SDValue T = DAG.getConstant(Value32, MVT::i32);
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001698 return DAG.getNode(ISD::BITCAST, dl, MVT::v4f32,
Owen Anderson825b72b2009-08-11 20:47:22 +00001699 DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, T,T,T,T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001700 break;
1701 }
Owen Anderson825b72b2009-08-11 20:47:22 +00001702 case MVT::v2f64: {
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001703 uint64_t f64val = uint64_t(SplatBits);
Chris Lattnere7fa1f22009-03-26 05:29:34 +00001704 assert(SplatBitSize == 64
Scott Michel104de432008-11-24 17:11:17 +00001705 && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
Scott Michel266bc8f2007-12-04 22:23:35 +00001706 // NOTE: pretend the constant is an integer. LLVM won't load FP constants
Owen Anderson825b72b2009-08-11 20:47:22 +00001707 SDValue T = DAG.getConstant(f64val, MVT::i64);
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001708 return DAG.getNode(ISD::BITCAST, dl, MVT::v2f64,
Owen Anderson825b72b2009-08-11 20:47:22 +00001709 DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64, T, T));
Scott Michel266bc8f2007-12-04 22:23:35 +00001710 break;
1711 }
Owen Anderson825b72b2009-08-11 20:47:22 +00001712 case MVT::v16i8: {
Scott Michel266bc8f2007-12-04 22:23:35 +00001713 // 8-bit constants have to be expanded to 16-bits
Scott Michel7ea02ff2009-03-17 01:15:45 +00001714 unsigned short Value16 = SplatBits /* | (SplatBits << 8) */;
1715 SmallVector<SDValue, 8> Ops;
1716
Owen Anderson825b72b2009-08-11 20:47:22 +00001717 Ops.assign(8, DAG.getConstant(Value16, MVT::i16));
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001718 return DAG.getNode(ISD::BITCAST, dl, VT,
Owen Anderson825b72b2009-08-11 20:47:22 +00001719 DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v8i16, &Ops[0], Ops.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00001720 }
Owen Anderson825b72b2009-08-11 20:47:22 +00001721 case MVT::v8i16: {
Scott Michel7ea02ff2009-03-17 01:15:45 +00001722 unsigned short Value16 = SplatBits;
1723 SDValue T = DAG.getConstant(Value16, EltVT);
1724 SmallVector<SDValue, 8> Ops;
1725
1726 Ops.assign(8, T);
1727 return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], Ops.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001728 }
Owen Anderson825b72b2009-08-11 20:47:22 +00001729 case MVT::v4i32: {
Scott Michel7ea02ff2009-03-17 01:15:45 +00001730 SDValue T = DAG.getConstant(unsigned(SplatBits), VT.getVectorElementType());
Evan Chenga87008d2009-02-25 22:49:59 +00001731 return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, T, T, T, T);
Scott Michel266bc8f2007-12-04 22:23:35 +00001732 }
Owen Anderson825b72b2009-08-11 20:47:22 +00001733 case MVT::v2i64: {
Scott Michel7ea02ff2009-03-17 01:15:45 +00001734 return SPU::LowerV2I64Splat(VT, DAG, SplatBits, dl);
Scott Michel266bc8f2007-12-04 22:23:35 +00001735 }
1736 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00001737
Dan Gohman475871a2008-07-27 21:46:04 +00001738 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00001739}
1740
Scott Michel7ea02ff2009-03-17 01:15:45 +00001741/*!
1742 */
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001743SDValue
Owen Andersone50ed302009-08-10 22:56:29 +00001744SPU::LowerV2I64Splat(EVT OpVT, SelectionDAG& DAG, uint64_t SplatVal,
Scott Michel7ea02ff2009-03-17 01:15:45 +00001745 DebugLoc dl) {
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001746 uint32_t upper = uint32_t(SplatVal >> 32);
1747 uint32_t lower = uint32_t(SplatVal);
1748
1749 if (upper == lower) {
1750 // Magic constant that can be matched by IL, ILA, et. al.
Owen Anderson825b72b2009-08-11 20:47:22 +00001751 SDValue Val = DAG.getTargetConstant(upper, MVT::i32);
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001752 return DAG.getNode(ISD::BITCAST, dl, OpVT,
Owen Anderson825b72b2009-08-11 20:47:22 +00001753 DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
Evan Chenga87008d2009-02-25 22:49:59 +00001754 Val, Val, Val, Val));
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001755 } else {
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001756 bool upper_special, lower_special;
1757
1758 // NOTE: This code creates common-case shuffle masks that can be easily
1759 // detected as common expressions. It is not attempting to create highly
1760 // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1761
1762 // Detect if the upper or lower half is a special shuffle mask pattern:
1763 upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1764 lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1765
Scott Michel7ea02ff2009-03-17 01:15:45 +00001766 // Both upper and lower are special, lower to a constant pool load:
1767 if (lower_special && upper_special) {
Nadav Rotemc32a8c92011-10-16 10:02:06 +00001768 SDValue UpperVal = DAG.getConstant(upper, MVT::i32);
1769 SDValue LowerVal = DAG.getConstant(lower, MVT::i32);
1770 SDValue BV = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
1771 UpperVal, LowerVal, UpperVal, LowerVal);
1772 return DAG.getNode(ISD::BITCAST, dl, OpVT, BV);
Scott Michel7ea02ff2009-03-17 01:15:45 +00001773 }
1774
1775 SDValue LO32;
1776 SDValue HI32;
1777 SmallVector<SDValue, 16> ShufBytes;
1778 SDValue Result;
1779
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001780 // Create lower vector if not a special pattern
1781 if (!lower_special) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001782 SDValue LO32C = DAG.getConstant(lower, MVT::i32);
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001783 LO32 = DAG.getNode(ISD::BITCAST, dl, OpVT,
Owen Anderson825b72b2009-08-11 20:47:22 +00001784 DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
Evan Chenga87008d2009-02-25 22:49:59 +00001785 LO32C, LO32C, LO32C, LO32C));
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001786 }
1787
1788 // Create upper vector if not a special pattern
1789 if (!upper_special) {
Owen Anderson825b72b2009-08-11 20:47:22 +00001790 SDValue HI32C = DAG.getConstant(upper, MVT::i32);
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001791 HI32 = DAG.getNode(ISD::BITCAST, dl, OpVT,
Owen Anderson825b72b2009-08-11 20:47:22 +00001792 DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
Evan Chenga87008d2009-02-25 22:49:59 +00001793 HI32C, HI32C, HI32C, HI32C));
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001794 }
1795
1796 // If either upper or lower are special, then the two input operands are
1797 // the same (basically, one of them is a "don't care")
1798 if (lower_special)
1799 LO32 = HI32;
1800 if (upper_special)
1801 HI32 = LO32;
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001802
1803 for (int i = 0; i < 4; ++i) {
1804 uint64_t val = 0;
1805 for (int j = 0; j < 4; ++j) {
1806 SDValue V;
1807 bool process_upper, process_lower;
1808 val <<= 8;
1809 process_upper = (upper_special && (i & 1) == 0);
1810 process_lower = (lower_special && (i & 1) == 1);
1811
1812 if (process_upper || process_lower) {
1813 if ((process_upper && upper == 0)
1814 || (process_lower && lower == 0))
1815 val |= 0x80;
1816 else if ((process_upper && upper == 0xffffffff)
1817 || (process_lower && lower == 0xffffffff))
1818 val |= 0xc0;
1819 else if ((process_upper && upper == 0x80000000)
1820 || (process_lower && lower == 0x80000000))
1821 val |= (j == 0 ? 0xe0 : 0x80);
1822 } else
1823 val |= i * 4 + j + ((i & 1) * 16);
1824 }
1825
Owen Anderson825b72b2009-08-11 20:47:22 +00001826 ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001827 }
1828
Dale Johannesened2eee62009-02-06 01:31:28 +00001829 return DAG.getNode(SPUISD::SHUFB, dl, OpVT, HI32, LO32,
Owen Anderson825b72b2009-08-11 20:47:22 +00001830 DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
Evan Chenga87008d2009-02-25 22:49:59 +00001831 &ShufBytes[0], ShufBytes.size()));
Scott Michelc9c8b2a2009-01-26 03:31:40 +00001832 }
1833}
1834
Scott Michel266bc8f2007-12-04 22:23:35 +00001835/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1836/// which the Cell can operate. The code inspects V3 to ascertain whether the
1837/// permutation vector, V3, is monotonically increasing with one "exception"
1838/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
Scott Michel7a1c9e92008-11-22 23:50:42 +00001839/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
Scott Michel266bc8f2007-12-04 22:23:35 +00001840/// In either case, the net result is going to eventually invoke SHUFB to
1841/// permute/shuffle the bytes from V1 and V2.
1842/// \note
Scott Michel7a1c9e92008-11-22 23:50:42 +00001843/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
Scott Michel266bc8f2007-12-04 22:23:35 +00001844/// control word for byte/halfword/word insertion. This takes care of a single
1845/// element move from V2 into V1.
1846/// \note
1847/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
Dan Gohman475871a2008-07-27 21:46:04 +00001848static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
Nate Begeman9008ca62009-04-27 18:41:29 +00001849 const ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
Dan Gohman475871a2008-07-27 21:46:04 +00001850 SDValue V1 = Op.getOperand(0);
1851 SDValue V2 = Op.getOperand(1);
Dale Johannesena05dca42009-02-04 23:02:30 +00001852 DebugLoc dl = Op.getDebugLoc();
Scott Michel5af8f0e2008-07-16 17:17:29 +00001853
Scott Michel266bc8f2007-12-04 22:23:35 +00001854 if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001855
Scott Michel266bc8f2007-12-04 22:23:35 +00001856 // If we have a single element being moved from V1 to V2, this can be handled
1857 // using the C*[DX] compute mask instructions, but the vector elements have
Kalle Raiskilaca9460f2010-08-18 10:20:29 +00001858 // to be monotonically increasing with one exception element, and the source
1859 // slot of the element to move must be the same as the destination.
Owen Andersone50ed302009-08-10 22:56:29 +00001860 EVT VecVT = V1.getValueType();
1861 EVT EltVT = VecVT.getVectorElementType();
Scott Michel266bc8f2007-12-04 22:23:35 +00001862 unsigned EltsFromV2 = 0;
Kalle Raiskilaca9460f2010-08-18 10:20:29 +00001863 unsigned V2EltOffset = 0;
Scott Michel266bc8f2007-12-04 22:23:35 +00001864 unsigned V2EltIdx0 = 0;
1865 unsigned CurrElt = 0;
Scott Michelcc188272008-12-04 21:01:44 +00001866 unsigned MaxElts = VecVT.getVectorNumElements();
1867 unsigned PrevElt = 0;
Scott Michel266bc8f2007-12-04 22:23:35 +00001868 bool monotonic = true;
Scott Michelcc188272008-12-04 21:01:44 +00001869 bool rotate = true;
Kalle Raiskilabb7d33a2010-09-09 07:30:15 +00001870 int rotamt=0;
Kalle Raiskila47948072010-06-21 10:17:36 +00001871 EVT maskVT; // which of the c?d instructions to use
Scott Michelcc188272008-12-04 21:01:44 +00001872
Owen Anderson825b72b2009-08-11 20:47:22 +00001873 if (EltVT == MVT::i8) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001874 V2EltIdx0 = 16;
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001875 maskVT = MVT::v16i8;
Owen Anderson825b72b2009-08-11 20:47:22 +00001876 } else if (EltVT == MVT::i16) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001877 V2EltIdx0 = 8;
Kalle Raiskila47948072010-06-21 10:17:36 +00001878 maskVT = MVT::v8i16;
Owen Anderson825b72b2009-08-11 20:47:22 +00001879 } else if (EltVT == MVT::i32 || EltVT == MVT::f32) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001880 V2EltIdx0 = 4;
Kalle Raiskila47948072010-06-21 10:17:36 +00001881 maskVT = MVT::v4i32;
Owen Anderson825b72b2009-08-11 20:47:22 +00001882 } else if (EltVT == MVT::i64 || EltVT == MVT::f64) {
Scott Michelcc188272008-12-04 21:01:44 +00001883 V2EltIdx0 = 2;
Kalle Raiskila47948072010-06-21 10:17:36 +00001884 maskVT = MVT::v2i64;
Scott Michelcc188272008-12-04 21:01:44 +00001885 } else
Torok Edwinc23197a2009-07-14 16:55:14 +00001886 llvm_unreachable("Unhandled vector type in LowerVECTOR_SHUFFLE");
Scott Michel266bc8f2007-12-04 22:23:35 +00001887
Nate Begeman9008ca62009-04-27 18:41:29 +00001888 for (unsigned i = 0; i != MaxElts; ++i) {
1889 if (SVN->getMaskElt(i) < 0)
1890 continue;
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001891
Nate Begeman9008ca62009-04-27 18:41:29 +00001892 unsigned SrcElt = SVN->getMaskElt(i);
Scott Michel266bc8f2007-12-04 22:23:35 +00001893
Nate Begeman9008ca62009-04-27 18:41:29 +00001894 if (monotonic) {
1895 if (SrcElt >= V2EltIdx0) {
Kalle Raiskilaca9460f2010-08-18 10:20:29 +00001896 // TODO: optimize for the monotonic case when several consecutive
1897 // elements are taken form V2. Do we ever get such a case?
1898 if (EltsFromV2 == 0 && CurrElt == (SrcElt - V2EltIdx0))
1899 V2EltOffset = (SrcElt - V2EltIdx0) * (EltVT.getSizeInBits()/8);
1900 else
1901 monotonic = false;
1902 ++EltsFromV2;
Nate Begeman9008ca62009-04-27 18:41:29 +00001903 } else if (CurrElt != SrcElt) {
1904 monotonic = false;
Scott Michelcc188272008-12-04 21:01:44 +00001905 }
1906
Nate Begeman9008ca62009-04-27 18:41:29 +00001907 ++CurrElt;
1908 }
1909
1910 if (rotate) {
1911 if (PrevElt > 0 && SrcElt < MaxElts) {
1912 if ((PrevElt == SrcElt - 1)
1913 || (PrevElt == MaxElts - 1 && SrcElt == 0)) {
Scott Michelcc188272008-12-04 21:01:44 +00001914 PrevElt = SrcElt;
1915 } else {
Scott Michelcc188272008-12-04 21:01:44 +00001916 rotate = false;
1917 }
Kalle Raiskila0b4ab0c2010-09-08 11:53:38 +00001918 } else if (i == 0 || (PrevElt==0 && SrcElt==1)) {
1919 // First time or after a "wrap around"
Kalle Raiskilad87e5712010-11-22 16:28:26 +00001920 rotamt = SrcElt-i;
Nate Begeman9008ca62009-04-27 18:41:29 +00001921 PrevElt = SrcElt;
1922 } else {
1923 // This isn't a rotation, takes elements from vector 2
1924 rotate = false;
Scott Michelcc188272008-12-04 21:01:44 +00001925 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001926 }
Scott Michel266bc8f2007-12-04 22:23:35 +00001927 }
1928
1929 if (EltsFromV2 == 1 && monotonic) {
1930 // Compute mask and shuffle
Owen Andersone50ed302009-08-10 22:56:29 +00001931 EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Kalle Raiskila47948072010-06-21 10:17:36 +00001932
1933 // As SHUFFLE_MASK becomes a c?d instruction, feed it an address
1934 // R1 ($sp) is used here only as it is guaranteed to have last bits zero
1935 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
1936 DAG.getRegister(SPU::R1, PtrVT),
Kalle Raiskilaca9460f2010-08-18 10:20:29 +00001937 DAG.getConstant(V2EltOffset, MVT::i32));
Wesley Peckbf17cfa2010-11-23 03:31:01 +00001938 SDValue ShufMaskOp = DAG.getNode(SPUISD::SHUFFLE_MASK, dl,
Kalle Raiskila47948072010-06-21 10:17:36 +00001939 maskVT, Pointer);
1940
Scott Michel266bc8f2007-12-04 22:23:35 +00001941 // Use shuffle mask in SHUFB synthetic instruction:
Scott Michel6e1d1472009-03-16 18:47:25 +00001942 return DAG.getNode(SPUISD::SHUFB, dl, V1.getValueType(), V2, V1,
Dale Johannesena05dca42009-02-04 23:02:30 +00001943 ShufMaskOp);
Scott Michelcc188272008-12-04 21:01:44 +00001944 } else if (rotate) {
Kalle Raiskila0b4ab0c2010-09-08 11:53:38 +00001945 if (rotamt < 0)
1946 rotamt +=MaxElts;
1947 rotamt *= EltVT.getSizeInBits()/8;
Dale Johannesena05dca42009-02-04 23:02:30 +00001948 return DAG.getNode(SPUISD::ROTBYTES_LEFT, dl, V1.getValueType(),
Owen Anderson825b72b2009-08-11 20:47:22 +00001949 V1, DAG.getConstant(rotamt, MVT::i16));
Scott Michel266bc8f2007-12-04 22:23:35 +00001950 } else {
Gabor Greif93c53e52008-08-31 15:37:04 +00001951 // Convert the SHUFFLE_VECTOR mask's input element units to the
1952 // actual bytes.
Duncan Sands83ec4b62008-06-06 12:08:01 +00001953 unsigned BytesPerElement = EltVT.getSizeInBits()/8;
Scott Michel5af8f0e2008-07-16 17:17:29 +00001954
Dan Gohman475871a2008-07-27 21:46:04 +00001955 SmallVector<SDValue, 16> ResultMask;
Nate Begeman9008ca62009-04-27 18:41:29 +00001956 for (unsigned i = 0, e = MaxElts; i != e; ++i) {
1957 unsigned SrcElt = SVN->getMaskElt(i) < 0 ? 0 : SVN->getMaskElt(i);
Scott Michel5af8f0e2008-07-16 17:17:29 +00001958
Nate Begeman9008ca62009-04-27 18:41:29 +00001959 for (unsigned j = 0; j < BytesPerElement; ++j)
Owen Anderson825b72b2009-08-11 20:47:22 +00001960 ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,MVT::i8));
Scott Michel266bc8f2007-12-04 22:23:35 +00001961 }
Owen Anderson825b72b2009-08-11 20:47:22 +00001962 SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v16i8,
Evan Chenga87008d2009-02-25 22:49:59 +00001963 &ResultMask[0], ResultMask.size());
Dale Johannesena05dca42009-02-04 23:02:30 +00001964 return DAG.getNode(SPUISD::SHUFB, dl, V1.getValueType(), V1, V2, VPermMask);
Scott Michel266bc8f2007-12-04 22:23:35 +00001965 }
1966}
1967
Dan Gohman475871a2008-07-27 21:46:04 +00001968static SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1969 SDValue Op0 = Op.getOperand(0); // Op0 = the scalar
Dale Johannesened2eee62009-02-06 01:31:28 +00001970 DebugLoc dl = Op.getDebugLoc();
Scott Michel266bc8f2007-12-04 22:23:35 +00001971
Gabor Greifba36cb52008-08-28 21:40:38 +00001972 if (Op0.getNode()->getOpcode() == ISD::Constant) {
Scott Michel266bc8f2007-12-04 22:23:35 +00001973 // For a constant, build the appropriate constant vector, which will
1974 // eventually simplify to a vector register load.
1975
Gabor Greifba36cb52008-08-28 21:40:38 +00001976 ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
Dan Gohman475871a2008-07-27 21:46:04 +00001977 SmallVector<SDValue, 16> ConstVecValues;
Owen Andersone50ed302009-08-10 22:56:29 +00001978 EVT VT;
Scott Michel266bc8f2007-12-04 22:23:35 +00001979 size_t n_copies;
1980
1981 // Create a constant vector:
Owen Anderson825b72b2009-08-11 20:47:22 +00001982 switch (Op.getValueType().getSimpleVT().SimpleTy) {
Torok Edwinc23197a2009-07-14 16:55:14 +00001983 default: llvm_unreachable("Unexpected constant value type in "
Torok Edwin481d15a2009-07-14 12:22:58 +00001984 "LowerSCALAR_TO_VECTOR");
Owen Anderson825b72b2009-08-11 20:47:22 +00001985 case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1986 case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1987 case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1988 case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1989 case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1990 case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
Scott Michel266bc8f2007-12-04 22:23:35 +00001991 }
1992
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +00001993 SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
Scott Michel266bc8f2007-12-04 22:23:35 +00001994 for (size_t j = 0; j < n_copies; ++j)
1995 ConstVecValues.push_back(CValue);
1996
Evan Chenga87008d2009-02-25 22:49:59 +00001997 return DAG.getNode(ISD::BUILD_VECTOR, dl, Op.getValueType(),
1998 &ConstVecValues[0], ConstVecValues.size());
Scott Michel266bc8f2007-12-04 22:23:35 +00001999 } else {
2000 // Otherwise, copy the value from one register to another:
Owen Anderson825b72b2009-08-11 20:47:22 +00002001 switch (Op0.getValueType().getSimpleVT().SimpleTy) {
Torok Edwinc23197a2009-07-14 16:55:14 +00002002 default: llvm_unreachable("Unexpected value type in LowerSCALAR_TO_VECTOR");
Owen Anderson825b72b2009-08-11 20:47:22 +00002003 case MVT::i8:
2004 case MVT::i16:
2005 case MVT::i32:
2006 case MVT::i64:
2007 case MVT::f32:
2008 case MVT::f64:
Dale Johannesened2eee62009-02-06 01:31:28 +00002009 return DAG.getNode(SPUISD::PREFSLOT2VEC, dl, Op.getValueType(), Op0, Op0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002010 }
2011 }
2012
Dan Gohman475871a2008-07-27 21:46:04 +00002013 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002014}
2015
Dan Gohman475871a2008-07-27 21:46:04 +00002016static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
Owen Andersone50ed302009-08-10 22:56:29 +00002017 EVT VT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +00002018 SDValue N = Op.getOperand(0);
2019 SDValue Elt = Op.getOperand(1);
Dale Johannesened2eee62009-02-06 01:31:28 +00002020 DebugLoc dl = Op.getDebugLoc();
Scott Michel7a1c9e92008-11-22 23:50:42 +00002021 SDValue retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00002022
Scott Michel7a1c9e92008-11-22 23:50:42 +00002023 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2024 // Constant argument:
2025 int EltNo = (int) C->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002026
Scott Michel7a1c9e92008-11-22 23:50:42 +00002027 // sanity checks:
Owen Anderson825b72b2009-08-11 20:47:22 +00002028 if (VT == MVT::i8 && EltNo >= 16)
Torok Edwinc23197a2009-07-14 16:55:14 +00002029 llvm_unreachable("SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
Owen Anderson825b72b2009-08-11 20:47:22 +00002030 else if (VT == MVT::i16 && EltNo >= 8)
Torok Edwinc23197a2009-07-14 16:55:14 +00002031 llvm_unreachable("SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
Owen Anderson825b72b2009-08-11 20:47:22 +00002032 else if (VT == MVT::i32 && EltNo >= 4)
Torok Edwinc23197a2009-07-14 16:55:14 +00002033 llvm_unreachable("SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
Owen Anderson825b72b2009-08-11 20:47:22 +00002034 else if (VT == MVT::i64 && EltNo >= 2)
Torok Edwinc23197a2009-07-14 16:55:14 +00002035 llvm_unreachable("SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
Scott Michel266bc8f2007-12-04 22:23:35 +00002036
Owen Anderson825b72b2009-08-11 20:47:22 +00002037 if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
Scott Michel7a1c9e92008-11-22 23:50:42 +00002038 // i32 and i64: Element 0 is the preferred slot
Dale Johannesened2eee62009-02-06 01:31:28 +00002039 return DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT, N);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002040 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002041
Scott Michel7a1c9e92008-11-22 23:50:42 +00002042 // Need to generate shuffle mask and extract:
2043 int prefslot_begin = -1, prefslot_end = -1;
2044 int elt_byte = EltNo * VT.getSizeInBits() / 8;
2045
Owen Anderson825b72b2009-08-11 20:47:22 +00002046 switch (VT.getSimpleVT().SimpleTy) {
Scott Michel7a1c9e92008-11-22 23:50:42 +00002047 default:
2048 assert(false && "Invalid value type!");
Owen Anderson825b72b2009-08-11 20:47:22 +00002049 case MVT::i8: {
Scott Michel7a1c9e92008-11-22 23:50:42 +00002050 prefslot_begin = prefslot_end = 3;
2051 break;
2052 }
Owen Anderson825b72b2009-08-11 20:47:22 +00002053 case MVT::i16: {
Scott Michel7a1c9e92008-11-22 23:50:42 +00002054 prefslot_begin = 2; prefslot_end = 3;
2055 break;
2056 }
Owen Anderson825b72b2009-08-11 20:47:22 +00002057 case MVT::i32:
2058 case MVT::f32: {
Scott Michel7a1c9e92008-11-22 23:50:42 +00002059 prefslot_begin = 0; prefslot_end = 3;
2060 break;
2061 }
Owen Anderson825b72b2009-08-11 20:47:22 +00002062 case MVT::i64:
2063 case MVT::f64: {
Scott Michel7a1c9e92008-11-22 23:50:42 +00002064 prefslot_begin = 0; prefslot_end = 7;
2065 break;
2066 }
2067 }
2068
2069 assert(prefslot_begin != -1 && prefslot_end != -1 &&
2070 "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2071
Scott Michel9b2420d2009-08-24 21:53:27 +00002072 unsigned int ShufBytes[16] = {
2073 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
2074 };
Scott Michel7a1c9e92008-11-22 23:50:42 +00002075 for (int i = 0; i < 16; ++i) {
2076 // zero fill uppper part of preferred slot, don't care about the
2077 // other slots:
2078 unsigned int mask_val;
2079 if (i <= prefslot_end) {
2080 mask_val =
2081 ((i < prefslot_begin)
2082 ? 0x80
2083 : elt_byte + (i - prefslot_begin));
2084
2085 ShufBytes[i] = mask_val;
2086 } else
2087 ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2088 }
2089
2090 SDValue ShufMask[4];
2091 for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
Scott Michelcc188272008-12-04 21:01:44 +00002092 unsigned bidx = i * 4;
Scott Michel7a1c9e92008-11-22 23:50:42 +00002093 unsigned int bits = ((ShufBytes[bidx] << 24) |
2094 (ShufBytes[bidx+1] << 16) |
2095 (ShufBytes[bidx+2] << 8) |
2096 ShufBytes[bidx+3]);
Owen Anderson825b72b2009-08-11 20:47:22 +00002097 ShufMask[i] = DAG.getConstant(bits, MVT::i32);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002098 }
2099
Scott Michel7ea02ff2009-03-17 01:15:45 +00002100 SDValue ShufMaskVec =
Owen Anderson825b72b2009-08-11 20:47:22 +00002101 DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
Scott Michel7ea02ff2009-03-17 01:15:45 +00002102 &ShufMask[0], sizeof(ShufMask)/sizeof(ShufMask[0]));
Scott Michel7a1c9e92008-11-22 23:50:42 +00002103
Dale Johannesened2eee62009-02-06 01:31:28 +00002104 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT,
2105 DAG.getNode(SPUISD::SHUFB, dl, N.getValueType(),
Scott Michel7a1c9e92008-11-22 23:50:42 +00002106 N, N, ShufMaskVec));
2107 } else {
2108 // Variable index: Rotate the requested element into slot 0, then replicate
2109 // slot 0 across the vector
Owen Andersone50ed302009-08-10 22:56:29 +00002110 EVT VecVT = N.getValueType();
Kalle Raiskila82fe4672010-08-02 08:54:39 +00002111 if (!VecVT.isSimple() || !VecVT.isVector()) {
Chris Lattner75361b62010-04-07 22:58:41 +00002112 report_fatal_error("LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit"
Torok Edwindac237e2009-07-08 20:53:28 +00002113 "vector type!");
Scott Michel7a1c9e92008-11-22 23:50:42 +00002114 }
2115
2116 // Make life easier by making sure the index is zero-extended to i32
Owen Anderson825b72b2009-08-11 20:47:22 +00002117 if (Elt.getValueType() != MVT::i32)
2118 Elt = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Elt);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002119
2120 // Scale the index to a bit/byte shift quantity
2121 APInt scaleFactor =
Scott Michel104de432008-11-24 17:11:17 +00002122 APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2123 unsigned scaleShift = scaleFactor.logBase2();
Scott Michel7a1c9e92008-11-22 23:50:42 +00002124 SDValue vecShift;
Scott Michel7a1c9e92008-11-22 23:50:42 +00002125
Scott Michel104de432008-11-24 17:11:17 +00002126 if (scaleShift > 0) {
2127 // Scale the shift factor:
Owen Anderson825b72b2009-08-11 20:47:22 +00002128 Elt = DAG.getNode(ISD::SHL, dl, MVT::i32, Elt,
2129 DAG.getConstant(scaleShift, MVT::i32));
Scott Michel7a1c9e92008-11-22 23:50:42 +00002130 }
2131
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +00002132 vecShift = DAG.getNode(SPUISD::SHL_BYTES, dl, VecVT, N, Elt);
Scott Michel104de432008-11-24 17:11:17 +00002133
2134 // Replicate the bytes starting at byte 0 across the entire vector (for
2135 // consistency with the notion of a unified register set)
Scott Michel7a1c9e92008-11-22 23:50:42 +00002136 SDValue replicate;
2137
Owen Anderson825b72b2009-08-11 20:47:22 +00002138 switch (VT.getSimpleVT().SimpleTy) {
Scott Michel7a1c9e92008-11-22 23:50:42 +00002139 default:
Chris Lattner75361b62010-04-07 22:58:41 +00002140 report_fatal_error("LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector"
Torok Edwindac237e2009-07-08 20:53:28 +00002141 "type");
Scott Michel7a1c9e92008-11-22 23:50:42 +00002142 /*NOTREACHED*/
Owen Anderson825b72b2009-08-11 20:47:22 +00002143 case MVT::i8: {
2144 SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
2145 replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
Scott Michel7ea02ff2009-03-17 01:15:45 +00002146 factor, factor, factor, factor);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002147 break;
2148 }
Owen Anderson825b72b2009-08-11 20:47:22 +00002149 case MVT::i16: {
2150 SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
2151 replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
Scott Michel7ea02ff2009-03-17 01:15:45 +00002152 factor, factor, factor, factor);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002153 break;
2154 }
Owen Anderson825b72b2009-08-11 20:47:22 +00002155 case MVT::i32:
2156 case MVT::f32: {
2157 SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2158 replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
Scott Michel7ea02ff2009-03-17 01:15:45 +00002159 factor, factor, factor, factor);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002160 break;
2161 }
Owen Anderson825b72b2009-08-11 20:47:22 +00002162 case MVT::i64:
2163 case MVT::f64: {
2164 SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2165 SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2166 replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
Evan Chenga87008d2009-02-25 22:49:59 +00002167 loFactor, hiFactor, loFactor, hiFactor);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002168 break;
2169 }
2170 }
2171
Dale Johannesened2eee62009-02-06 01:31:28 +00002172 retval = DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT,
2173 DAG.getNode(SPUISD::SHUFB, dl, VecVT,
Scott Michel1a6cdb62008-12-01 17:56:02 +00002174 vecShift, vecShift, replicate));
Scott Michel266bc8f2007-12-04 22:23:35 +00002175 }
2176
Scott Michel7a1c9e92008-11-22 23:50:42 +00002177 return retval;
Scott Michel266bc8f2007-12-04 22:23:35 +00002178}
2179
Dan Gohman475871a2008-07-27 21:46:04 +00002180static SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2181 SDValue VecOp = Op.getOperand(0);
2182 SDValue ValOp = Op.getOperand(1);
2183 SDValue IdxOp = Op.getOperand(2);
Dale Johannesened2eee62009-02-06 01:31:28 +00002184 DebugLoc dl = Op.getDebugLoc();
Owen Andersone50ed302009-08-10 22:56:29 +00002185 EVT VT = Op.getValueType();
Kalle Raiskilabd887df2010-08-29 12:41:50 +00002186 EVT eltVT = ValOp.getValueType();
Scott Michel266bc8f2007-12-04 22:23:35 +00002187
Kalle Raiskila43d225d2010-06-09 09:58:17 +00002188 // use 0 when the lane to insert to is 'undef'
Kalle Raiskilabd887df2010-08-29 12:41:50 +00002189 int64_t Offset=0;
Kalle Raiskila43d225d2010-06-09 09:58:17 +00002190 if (IdxOp.getOpcode() != ISD::UNDEF) {
2191 ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2192 assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
Kalle Raiskilabd887df2010-08-29 12:41:50 +00002193 Offset = (CN->getSExtValue()) * eltVT.getSizeInBits()/8;
Kalle Raiskila43d225d2010-06-09 09:58:17 +00002194 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002195
Owen Andersone50ed302009-08-10 22:56:29 +00002196 EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
Scott Michel1a6cdb62008-12-01 17:56:02 +00002197 // Use $sp ($1) because it's always 16-byte aligned and it's available:
Dale Johannesened2eee62009-02-06 01:31:28 +00002198 SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
Scott Michel1a6cdb62008-12-01 17:56:02 +00002199 DAG.getRegister(SPU::R1, PtrVT),
Kalle Raiskilabd887df2010-08-29 12:41:50 +00002200 DAG.getConstant(Offset, PtrVT));
Kalle Raiskilabc2697c2010-08-04 13:59:48 +00002201 // widen the mask when dealing with half vectors
Wesley Peckbf17cfa2010-11-23 03:31:01 +00002202 EVT maskVT = EVT::getVectorVT(*(DAG.getContext()), VT.getVectorElementType(),
Kalle Raiskilabc2697c2010-08-04 13:59:48 +00002203 128/ VT.getVectorElementType().getSizeInBits());
2204 SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, dl, maskVT, Pointer);
Scott Michel266bc8f2007-12-04 22:23:35 +00002205
Dan Gohman475871a2008-07-27 21:46:04 +00002206 SDValue result =
Dale Johannesened2eee62009-02-06 01:31:28 +00002207 DAG.getNode(SPUISD::SHUFB, dl, VT,
2208 DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, ValOp),
Scott Michel1df30c42008-12-29 03:23:36 +00002209 VecOp,
Wesley Peckbf17cfa2010-11-23 03:31:01 +00002210 DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, ShufMask));
Scott Michel266bc8f2007-12-04 22:23:35 +00002211
2212 return result;
2213}
2214
Scott Michelf0569be2008-12-27 04:51:36 +00002215static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc,
2216 const TargetLowering &TLI)
Scott Michela59d4692008-02-23 18:41:37 +00002217{
Dan Gohman475871a2008-07-27 21:46:04 +00002218 SDValue N0 = Op.getOperand(0); // Everything has at least one operand
Dale Johannesened2eee62009-02-06 01:31:28 +00002219 DebugLoc dl = Op.getDebugLoc();
Owen Anderson95771af2011-02-25 21:41:48 +00002220 EVT ShiftVT = TLI.getShiftAmountTy(N0.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +00002221
Owen Anderson825b72b2009-08-11 20:47:22 +00002222 assert(Op.getValueType() == MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002223 switch (Opc) {
2224 default:
Torok Edwinc23197a2009-07-14 16:55:14 +00002225 llvm_unreachable("Unhandled i8 math operator");
Scott Michel266bc8f2007-12-04 22:23:35 +00002226 /*NOTREACHED*/
2227 break;
Scott Michel02d711b2008-12-30 23:28:25 +00002228 case ISD::ADD: {
2229 // 8-bit addition: Promote the arguments up to 16-bits and truncate
2230 // the result:
2231 SDValue N1 = Op.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +00002232 N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0);
2233 N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N1);
2234 return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2235 DAG.getNode(Opc, dl, MVT::i16, N0, N1));
Scott Michel02d711b2008-12-30 23:28:25 +00002236
2237 }
2238
Scott Michel266bc8f2007-12-04 22:23:35 +00002239 case ISD::SUB: {
2240 // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2241 // the result:
Dan Gohman475871a2008-07-27 21:46:04 +00002242 SDValue N1 = Op.getOperand(1);
Owen Anderson825b72b2009-08-11 20:47:22 +00002243 N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0);
2244 N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N1);
2245 return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2246 DAG.getNode(Opc, dl, MVT::i16, N0, N1));
Scott Michel5af8f0e2008-07-16 17:17:29 +00002247 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002248 case ISD::ROTR:
2249 case ISD::ROTL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002250 SDValue N1 = Op.getOperand(1);
Owen Andersone50ed302009-08-10 22:56:29 +00002251 EVT N1VT = N1.getValueType();
Scott Michel7ea02ff2009-03-17 01:15:45 +00002252
Owen Anderson825b72b2009-08-11 20:47:22 +00002253 N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i16, N0);
Scott Michel7ea02ff2009-03-17 01:15:45 +00002254 if (!N1VT.bitsEq(ShiftVT)) {
2255 unsigned N1Opc = N1.getValueType().bitsLT(ShiftVT)
2256 ? ISD::ZERO_EXTEND
2257 : ISD::TRUNCATE;
2258 N1 = DAG.getNode(N1Opc, dl, ShiftVT, N1);
2259 }
2260
2261 // Replicate lower 8-bits into upper 8:
Dan Gohman475871a2008-07-27 21:46:04 +00002262 SDValue ExpandArg =
Owen Anderson825b72b2009-08-11 20:47:22 +00002263 DAG.getNode(ISD::OR, dl, MVT::i16, N0,
2264 DAG.getNode(ISD::SHL, dl, MVT::i16,
2265 N0, DAG.getConstant(8, MVT::i32)));
Scott Michel7ea02ff2009-03-17 01:15:45 +00002266
2267 // Truncate back down to i8
Owen Anderson825b72b2009-08-11 20:47:22 +00002268 return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2269 DAG.getNode(Opc, dl, MVT::i16, ExpandArg, N1));
Scott Michel266bc8f2007-12-04 22:23:35 +00002270 }
2271 case ISD::SRL:
2272 case ISD::SHL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002273 SDValue N1 = Op.getOperand(1);
Owen Andersone50ed302009-08-10 22:56:29 +00002274 EVT N1VT = N1.getValueType();
Scott Michel7ea02ff2009-03-17 01:15:45 +00002275
Owen Anderson825b72b2009-08-11 20:47:22 +00002276 N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i16, N0);
Scott Michel7ea02ff2009-03-17 01:15:45 +00002277 if (!N1VT.bitsEq(ShiftVT)) {
2278 unsigned N1Opc = ISD::ZERO_EXTEND;
2279
2280 if (N1.getValueType().bitsGT(ShiftVT))
2281 N1Opc = ISD::TRUNCATE;
2282
2283 N1 = DAG.getNode(N1Opc, dl, ShiftVT, N1);
2284 }
2285
Owen Anderson825b72b2009-08-11 20:47:22 +00002286 return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2287 DAG.getNode(Opc, dl, MVT::i16, N0, N1));
Scott Michel266bc8f2007-12-04 22:23:35 +00002288 }
2289 case ISD::SRA: {
Dan Gohman475871a2008-07-27 21:46:04 +00002290 SDValue N1 = Op.getOperand(1);
Owen Andersone50ed302009-08-10 22:56:29 +00002291 EVT N1VT = N1.getValueType();
Scott Michel7ea02ff2009-03-17 01:15:45 +00002292
Owen Anderson825b72b2009-08-11 20:47:22 +00002293 N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0);
Scott Michel7ea02ff2009-03-17 01:15:45 +00002294 if (!N1VT.bitsEq(ShiftVT)) {
2295 unsigned N1Opc = ISD::SIGN_EXTEND;
2296
2297 if (N1VT.bitsGT(ShiftVT))
2298 N1Opc = ISD::TRUNCATE;
2299 N1 = DAG.getNode(N1Opc, dl, ShiftVT, N1);
2300 }
2301
Owen Anderson825b72b2009-08-11 20:47:22 +00002302 return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2303 DAG.getNode(Opc, dl, MVT::i16, N0, N1));
Scott Michel266bc8f2007-12-04 22:23:35 +00002304 }
2305 case ISD::MUL: {
Dan Gohman475871a2008-07-27 21:46:04 +00002306 SDValue N1 = Op.getOperand(1);
Scott Michel7ea02ff2009-03-17 01:15:45 +00002307
Owen Anderson825b72b2009-08-11 20:47:22 +00002308 N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0);
2309 N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N1);
2310 return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2311 DAG.getNode(Opc, dl, MVT::i16, N0, N1));
Scott Michel266bc8f2007-12-04 22:23:35 +00002312 break;
2313 }
2314 }
2315
Dan Gohman475871a2008-07-27 21:46:04 +00002316 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002317}
2318
2319//! Lower byte immediate operations for v16i8 vectors:
Dan Gohman475871a2008-07-27 21:46:04 +00002320static SDValue
2321LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2322 SDValue ConstVec;
2323 SDValue Arg;
Owen Andersone50ed302009-08-10 22:56:29 +00002324 EVT VT = Op.getValueType();
Dale Johannesened2eee62009-02-06 01:31:28 +00002325 DebugLoc dl = Op.getDebugLoc();
Scott Michel266bc8f2007-12-04 22:23:35 +00002326
2327 ConstVec = Op.getOperand(0);
2328 Arg = Op.getOperand(1);
Gabor Greifba36cb52008-08-28 21:40:38 +00002329 if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
Wesley Peckbf17cfa2010-11-23 03:31:01 +00002330 if (ConstVec.getNode()->getOpcode() == ISD::BITCAST) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002331 ConstVec = ConstVec.getOperand(0);
2332 } else {
2333 ConstVec = Op.getOperand(1);
2334 Arg = Op.getOperand(0);
Wesley Peckbf17cfa2010-11-23 03:31:01 +00002335 if (ConstVec.getNode()->getOpcode() == ISD::BITCAST) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002336 ConstVec = ConstVec.getOperand(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002337 }
2338 }
2339 }
2340
Gabor Greifba36cb52008-08-28 21:40:38 +00002341 if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
Scott Michel7ea02ff2009-03-17 01:15:45 +00002342 BuildVectorSDNode *BCN = dyn_cast<BuildVectorSDNode>(ConstVec.getNode());
2343 assert(BCN != 0 && "Expected BuildVectorSDNode in SPU LowerByteImmed");
Scott Michel266bc8f2007-12-04 22:23:35 +00002344
Scott Michel7ea02ff2009-03-17 01:15:45 +00002345 APInt APSplatBits, APSplatUndef;
2346 unsigned SplatBitSize;
2347 bool HasAnyUndefs;
2348 unsigned minSplatBits = VT.getVectorElementType().getSizeInBits();
2349
2350 if (BCN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize,
2351 HasAnyUndefs, minSplatBits)
2352 && minSplatBits <= SplatBitSize) {
2353 uint64_t SplatBits = APSplatBits.getZExtValue();
Owen Anderson825b72b2009-08-11 20:47:22 +00002354 SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
Scott Michel266bc8f2007-12-04 22:23:35 +00002355
Scott Michel7ea02ff2009-03-17 01:15:45 +00002356 SmallVector<SDValue, 16> tcVec;
2357 tcVec.assign(16, tc);
Dale Johannesened2eee62009-02-06 01:31:28 +00002358 return DAG.getNode(Op.getNode()->getOpcode(), dl, VT, Arg,
Scott Michel7ea02ff2009-03-17 01:15:45 +00002359 DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &tcVec[0], tcVec.size()));
Scott Michel266bc8f2007-12-04 22:23:35 +00002360 }
2361 }
Scott Michel9de57a92009-01-26 22:33:37 +00002362
Nate Begeman24dc3462008-07-29 19:07:27 +00002363 // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2364 // lowered. Return the operation, rather than a null SDValue.
2365 return Op;
Scott Michel266bc8f2007-12-04 22:23:35 +00002366}
2367
Scott Michel266bc8f2007-12-04 22:23:35 +00002368//! Custom lowering for CTPOP (count population)
2369/*!
2370 Custom lowering code that counts the number ones in the input
2371 operand. SPU has such an instruction, but it counts the number of
2372 ones per byte, which then have to be accumulated.
2373*/
Dan Gohman475871a2008-07-27 21:46:04 +00002374static SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
Owen Andersone50ed302009-08-10 22:56:29 +00002375 EVT VT = Op.getValueType();
Wesley Peckbf17cfa2010-11-23 03:31:01 +00002376 EVT vecVT = EVT::getVectorVT(*DAG.getContext(),
Owen Anderson23b9b192009-08-12 00:36:31 +00002377 VT, (128 / VT.getSizeInBits()));
Dale Johannesena05dca42009-02-04 23:02:30 +00002378 DebugLoc dl = Op.getDebugLoc();
Scott Michel266bc8f2007-12-04 22:23:35 +00002379
Owen Anderson825b72b2009-08-11 20:47:22 +00002380 switch (VT.getSimpleVT().SimpleTy) {
Duncan Sands83ec4b62008-06-06 12:08:01 +00002381 default:
2382 assert(false && "Invalid value type!");
Owen Anderson825b72b2009-08-11 20:47:22 +00002383 case MVT::i8: {
Dan Gohman475871a2008-07-27 21:46:04 +00002384 SDValue N = Op.getOperand(0);
Owen Anderson825b72b2009-08-11 20:47:22 +00002385 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002386
Dale Johannesena05dca42009-02-04 23:02:30 +00002387 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, dl, vecVT, N, N);
2388 SDValue CNTB = DAG.getNode(SPUISD::CNTB, dl, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002389
Owen Anderson825b72b2009-08-11 20:47:22 +00002390 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i8, CNTB, Elt0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002391 }
2392
Owen Anderson825b72b2009-08-11 20:47:22 +00002393 case MVT::i16: {
Scott Michel266bc8f2007-12-04 22:23:35 +00002394 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002395 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002396
Chris Lattner84bc5422007-12-31 04:13:23 +00002397 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002398
Dan Gohman475871a2008-07-27 21:46:04 +00002399 SDValue N = Op.getOperand(0);
Owen Anderson825b72b2009-08-11 20:47:22 +00002400 SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2401 SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
2402 SDValue Shift1 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002403
Dale Johannesena05dca42009-02-04 23:02:30 +00002404 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, dl, vecVT, N, N);
2405 SDValue CNTB = DAG.getNode(SPUISD::CNTB, dl, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002406
2407 // CNTB_result becomes the chain to which all of the virtual registers
2408 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002409 SDValue CNTB_result =
Owen Anderson825b72b2009-08-11 20:47:22 +00002410 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i16, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002411
Dan Gohman475871a2008-07-27 21:46:04 +00002412 SDValue CNTB_rescopy =
Dale Johannesena05dca42009-02-04 23:02:30 +00002413 DAG.getCopyToReg(CNTB_result, dl, CNTB_reg, CNTB_result);
Scott Michel266bc8f2007-12-04 22:23:35 +00002414
Owen Anderson825b72b2009-08-11 20:47:22 +00002415 SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, dl, CNTB_reg, MVT::i16);
Scott Michel266bc8f2007-12-04 22:23:35 +00002416
Owen Anderson825b72b2009-08-11 20:47:22 +00002417 return DAG.getNode(ISD::AND, dl, MVT::i16,
2418 DAG.getNode(ISD::ADD, dl, MVT::i16,
2419 DAG.getNode(ISD::SRL, dl, MVT::i16,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002420 Tmp1, Shift1),
2421 Tmp1),
2422 Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002423 }
2424
Owen Anderson825b72b2009-08-11 20:47:22 +00002425 case MVT::i32: {
Scott Michel266bc8f2007-12-04 22:23:35 +00002426 MachineFunction &MF = DAG.getMachineFunction();
Chris Lattner84bc5422007-12-31 04:13:23 +00002427 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +00002428
Chris Lattner84bc5422007-12-31 04:13:23 +00002429 unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2430 unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
Scott Michel266bc8f2007-12-04 22:23:35 +00002431
Dan Gohman475871a2008-07-27 21:46:04 +00002432 SDValue N = Op.getOperand(0);
Owen Anderson825b72b2009-08-11 20:47:22 +00002433 SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2434 SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2435 SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2436 SDValue Shift2 = DAG.getConstant(8, MVT::i32);
Scott Michel266bc8f2007-12-04 22:23:35 +00002437
Dale Johannesena05dca42009-02-04 23:02:30 +00002438 SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, dl, vecVT, N, N);
2439 SDValue CNTB = DAG.getNode(SPUISD::CNTB, dl, vecVT, Promote);
Scott Michel266bc8f2007-12-04 22:23:35 +00002440
2441 // CNTB_result becomes the chain to which all of the virtual registers
2442 // CNTB_reg, SUM1_reg become associated:
Dan Gohman475871a2008-07-27 21:46:04 +00002443 SDValue CNTB_result =
Owen Anderson825b72b2009-08-11 20:47:22 +00002444 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32, CNTB, Elt0);
Scott Michel5af8f0e2008-07-16 17:17:29 +00002445
Dan Gohman475871a2008-07-27 21:46:04 +00002446 SDValue CNTB_rescopy =
Dale Johannesena05dca42009-02-04 23:02:30 +00002447 DAG.getCopyToReg(CNTB_result, dl, CNTB_reg, CNTB_result);
Scott Michel266bc8f2007-12-04 22:23:35 +00002448
Dan Gohman475871a2008-07-27 21:46:04 +00002449 SDValue Comp1 =
Owen Anderson825b72b2009-08-11 20:47:22 +00002450 DAG.getNode(ISD::SRL, dl, MVT::i32,
2451 DAG.getCopyFromReg(CNTB_rescopy, dl, CNTB_reg, MVT::i32),
Dale Johannesena05dca42009-02-04 23:02:30 +00002452 Shift1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002453
Dan Gohman475871a2008-07-27 21:46:04 +00002454 SDValue Sum1 =
Owen Anderson825b72b2009-08-11 20:47:22 +00002455 DAG.getNode(ISD::ADD, dl, MVT::i32, Comp1,
2456 DAG.getCopyFromReg(CNTB_rescopy, dl, CNTB_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002457
Dan Gohman475871a2008-07-27 21:46:04 +00002458 SDValue Sum1_rescopy =
Dale Johannesena05dca42009-02-04 23:02:30 +00002459 DAG.getCopyToReg(CNTB_result, dl, SUM1_reg, Sum1);
Scott Michel266bc8f2007-12-04 22:23:35 +00002460
Dan Gohman475871a2008-07-27 21:46:04 +00002461 SDValue Comp2 =
Owen Anderson825b72b2009-08-11 20:47:22 +00002462 DAG.getNode(ISD::SRL, dl, MVT::i32,
2463 DAG.getCopyFromReg(Sum1_rescopy, dl, SUM1_reg, MVT::i32),
Scott Michel7f9ba9b2008-01-30 02:55:46 +00002464 Shift2);
Dan Gohman475871a2008-07-27 21:46:04 +00002465 SDValue Sum2 =
Owen Anderson825b72b2009-08-11 20:47:22 +00002466 DAG.getNode(ISD::ADD, dl, MVT::i32, Comp2,
2467 DAG.getCopyFromReg(Sum1_rescopy, dl, SUM1_reg, MVT::i32));
Scott Michel266bc8f2007-12-04 22:23:35 +00002468
Owen Anderson825b72b2009-08-11 20:47:22 +00002469 return DAG.getNode(ISD::AND, dl, MVT::i32, Sum2, Mask0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002470 }
2471
Owen Anderson825b72b2009-08-11 20:47:22 +00002472 case MVT::i64:
Scott Michel266bc8f2007-12-04 22:23:35 +00002473 break;
2474 }
2475
Dan Gohman475871a2008-07-27 21:46:04 +00002476 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002477}
2478
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002479//! Lower ISD::FP_TO_SINT, ISD::FP_TO_UINT for i32
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002480/*!
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002481 f32->i32 passes through unchanged, whereas f64->i32 expands to a libcall.
2482 All conversions to i64 are expanded to a libcall.
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002483 */
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002484static SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG,
Dan Gohmand858e902010-04-17 15:26:15 +00002485 const SPUTargetLowering &TLI) {
Owen Andersone50ed302009-08-10 22:56:29 +00002486 EVT OpVT = Op.getValueType();
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002487 SDValue Op0 = Op.getOperand(0);
Owen Andersone50ed302009-08-10 22:56:29 +00002488 EVT Op0VT = Op0.getValueType();
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002489
Owen Anderson825b72b2009-08-11 20:47:22 +00002490 if ((OpVT == MVT::i32 && Op0VT == MVT::f64)
2491 || OpVT == MVT::i64) {
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002492 // Convert f32 / f64 to i32 / i64 via libcall.
2493 RTLIB::Libcall LC =
2494 (Op.getOpcode() == ISD::FP_TO_SINT)
2495 ? RTLIB::getFPTOSINT(Op0VT, OpVT)
2496 : RTLIB::getFPTOUINT(Op0VT, OpVT);
2497 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpectd fp-to-int conversion!");
2498 SDValue Dummy;
2499 return ExpandLibCall(LC, Op, DAG, false, Dummy, TLI);
2500 }
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002501
Eli Friedman36df4992009-05-27 00:47:34 +00002502 return Op;
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002503}
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002504
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002505//! Lower ISD::SINT_TO_FP, ISD::UINT_TO_FP for i32
2506/*!
2507 i32->f32 passes through unchanged, whereas i32->f64 is expanded to a libcall.
2508 All conversions from i64 are expanded to a libcall.
2509 */
2510static SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG,
Dan Gohmand858e902010-04-17 15:26:15 +00002511 const SPUTargetLowering &TLI) {
Owen Andersone50ed302009-08-10 22:56:29 +00002512 EVT OpVT = Op.getValueType();
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002513 SDValue Op0 = Op.getOperand(0);
Owen Andersone50ed302009-08-10 22:56:29 +00002514 EVT Op0VT = Op0.getValueType();
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002515
Owen Anderson825b72b2009-08-11 20:47:22 +00002516 if ((OpVT == MVT::f64 && Op0VT == MVT::i32)
2517 || Op0VT == MVT::i64) {
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002518 // Convert i32, i64 to f64 via libcall:
2519 RTLIB::Libcall LC =
2520 (Op.getOpcode() == ISD::SINT_TO_FP)
2521 ? RTLIB::getSINTTOFP(Op0VT, OpVT)
2522 : RTLIB::getUINTTOFP(Op0VT, OpVT);
2523 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpectd int-to-fp conversion!");
2524 SDValue Dummy;
2525 return ExpandLibCall(LC, Op, DAG, false, Dummy, TLI);
2526 }
2527
Eli Friedman36df4992009-05-27 00:47:34 +00002528 return Op;
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002529}
2530
2531//! Lower ISD::SETCC
2532/*!
Owen Anderson825b72b2009-08-11 20:47:22 +00002533 This handles MVT::f64 (double floating point) condition lowering
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002534 */
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002535static SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG,
2536 const TargetLowering &TLI) {
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002537 CondCodeSDNode *CC = dyn_cast<CondCodeSDNode>(Op.getOperand(2));
Dale Johannesen6f38cb62009-02-07 19:59:05 +00002538 DebugLoc dl = Op.getDebugLoc();
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002539 assert(CC != 0 && "LowerSETCC: CondCodeSDNode should not be null here!\n");
2540
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002541 SDValue lhs = Op.getOperand(0);
2542 SDValue rhs = Op.getOperand(1);
Owen Andersone50ed302009-08-10 22:56:29 +00002543 EVT lhsVT = lhs.getValueType();
Owen Anderson825b72b2009-08-11 20:47:22 +00002544 assert(lhsVT == MVT::f64 && "LowerSETCC: type other than MVT::64\n");
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002545
Owen Andersone50ed302009-08-10 22:56:29 +00002546 EVT ccResultVT = TLI.getSetCCResultType(lhs.getValueType());
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002547 APInt ccResultOnes = APInt::getAllOnesValue(ccResultVT.getSizeInBits());
Owen Anderson825b72b2009-08-11 20:47:22 +00002548 EVT IntVT(MVT::i64);
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002549
2550 // Take advantage of the fact that (truncate (sra arg, 32)) is efficiently
2551 // selected to a NOP:
Wesley Peckbf17cfa2010-11-23 03:31:01 +00002552 SDValue i64lhs = DAG.getNode(ISD::BITCAST, dl, IntVT, lhs);
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002553 SDValue lhsHi32 =
Owen Anderson825b72b2009-08-11 20:47:22 +00002554 DAG.getNode(ISD::TRUNCATE, dl, MVT::i32,
Dale Johannesenf5d97892009-02-04 01:48:28 +00002555 DAG.getNode(ISD::SRL, dl, IntVT,
Owen Anderson825b72b2009-08-11 20:47:22 +00002556 i64lhs, DAG.getConstant(32, MVT::i32)));
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002557 SDValue lhsHi32abs =
Owen Anderson825b72b2009-08-11 20:47:22 +00002558 DAG.getNode(ISD::AND, dl, MVT::i32,
2559 lhsHi32, DAG.getConstant(0x7fffffff, MVT::i32));
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002560 SDValue lhsLo32 =
Owen Anderson825b72b2009-08-11 20:47:22 +00002561 DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, i64lhs);
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002562
2563 // SETO and SETUO only use the lhs operand:
2564 if (CC->get() == ISD::SETO) {
2565 // Evaluates to true if Op0 is not [SQ]NaN - lowers to the inverse of
2566 // SETUO
2567 APInt ccResultAllOnes = APInt::getAllOnesValue(ccResultVT.getSizeInBits());
Dale Johannesenf5d97892009-02-04 01:48:28 +00002568 return DAG.getNode(ISD::XOR, dl, ccResultVT,
2569 DAG.getSetCC(dl, ccResultVT,
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002570 lhs, DAG.getConstantFP(0.0, lhsVT),
2571 ISD::SETUO),
2572 DAG.getConstant(ccResultAllOnes, ccResultVT));
2573 } else if (CC->get() == ISD::SETUO) {
2574 // Evaluates to true if Op0 is [SQ]NaN
Dale Johannesenf5d97892009-02-04 01:48:28 +00002575 return DAG.getNode(ISD::AND, dl, ccResultVT,
2576 DAG.getSetCC(dl, ccResultVT,
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002577 lhsHi32abs,
Owen Anderson825b72b2009-08-11 20:47:22 +00002578 DAG.getConstant(0x7ff00000, MVT::i32),
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002579 ISD::SETGE),
Dale Johannesenf5d97892009-02-04 01:48:28 +00002580 DAG.getSetCC(dl, ccResultVT,
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002581 lhsLo32,
Owen Anderson825b72b2009-08-11 20:47:22 +00002582 DAG.getConstant(0, MVT::i32),
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002583 ISD::SETGT));
2584 }
2585
Wesley Peckbf17cfa2010-11-23 03:31:01 +00002586 SDValue i64rhs = DAG.getNode(ISD::BITCAST, dl, IntVT, rhs);
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002587 SDValue rhsHi32 =
Owen Anderson825b72b2009-08-11 20:47:22 +00002588 DAG.getNode(ISD::TRUNCATE, dl, MVT::i32,
Dale Johannesenf5d97892009-02-04 01:48:28 +00002589 DAG.getNode(ISD::SRL, dl, IntVT,
Owen Anderson825b72b2009-08-11 20:47:22 +00002590 i64rhs, DAG.getConstant(32, MVT::i32)));
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002591
2592 // If a value is negative, subtract from the sign magnitude constant:
2593 SDValue signMag2TC = DAG.getConstant(0x8000000000000000ULL, IntVT);
2594
2595 // Convert the sign-magnitude representation into 2's complement:
Dale Johannesenf5d97892009-02-04 01:48:28 +00002596 SDValue lhsSelectMask = DAG.getNode(ISD::SRA, dl, ccResultVT,
Owen Anderson825b72b2009-08-11 20:47:22 +00002597 lhsHi32, DAG.getConstant(31, MVT::i32));
Dale Johannesenf5d97892009-02-04 01:48:28 +00002598 SDValue lhsSignMag2TC = DAG.getNode(ISD::SUB, dl, IntVT, signMag2TC, i64lhs);
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002599 SDValue lhsSelect =
Dale Johannesenf5d97892009-02-04 01:48:28 +00002600 DAG.getNode(ISD::SELECT, dl, IntVT,
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002601 lhsSelectMask, lhsSignMag2TC, i64lhs);
2602
Dale Johannesenf5d97892009-02-04 01:48:28 +00002603 SDValue rhsSelectMask = DAG.getNode(ISD::SRA, dl, ccResultVT,
Owen Anderson825b72b2009-08-11 20:47:22 +00002604 rhsHi32, DAG.getConstant(31, MVT::i32));
Dale Johannesenf5d97892009-02-04 01:48:28 +00002605 SDValue rhsSignMag2TC = DAG.getNode(ISD::SUB, dl, IntVT, signMag2TC, i64rhs);
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002606 SDValue rhsSelect =
Dale Johannesenf5d97892009-02-04 01:48:28 +00002607 DAG.getNode(ISD::SELECT, dl, IntVT,
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002608 rhsSelectMask, rhsSignMag2TC, i64rhs);
2609
2610 unsigned compareOp;
2611
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002612 switch (CC->get()) {
2613 case ISD::SETOEQ:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002614 case ISD::SETUEQ:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002615 compareOp = ISD::SETEQ; break;
2616 case ISD::SETOGT:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002617 case ISD::SETUGT:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002618 compareOp = ISD::SETGT; break;
2619 case ISD::SETOGE:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002620 case ISD::SETUGE:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002621 compareOp = ISD::SETGE; break;
2622 case ISD::SETOLT:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002623 case ISD::SETULT:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002624 compareOp = ISD::SETLT; break;
2625 case ISD::SETOLE:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002626 case ISD::SETULE:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002627 compareOp = ISD::SETLE; break;
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002628 case ISD::SETUNE:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002629 case ISD::SETONE:
2630 compareOp = ISD::SETNE; break;
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002631 default:
Chris Lattner75361b62010-04-07 22:58:41 +00002632 report_fatal_error("CellSPU ISel Select: unimplemented f64 condition");
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002633 }
2634
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002635 SDValue result =
Scott Michel6e1d1472009-03-16 18:47:25 +00002636 DAG.getSetCC(dl, ccResultVT, lhsSelect, rhsSelect,
Dale Johannesenf5d97892009-02-04 01:48:28 +00002637 (ISD::CondCode) compareOp);
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002638
2639 if ((CC->get() & 0x8) == 0) {
2640 // Ordered comparison:
Dale Johannesenf5d97892009-02-04 01:48:28 +00002641 SDValue lhsNaN = DAG.getSetCC(dl, ccResultVT,
Owen Anderson825b72b2009-08-11 20:47:22 +00002642 lhs, DAG.getConstantFP(0.0, MVT::f64),
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002643 ISD::SETO);
Dale Johannesenf5d97892009-02-04 01:48:28 +00002644 SDValue rhsNaN = DAG.getSetCC(dl, ccResultVT,
Owen Anderson825b72b2009-08-11 20:47:22 +00002645 rhs, DAG.getConstantFP(0.0, MVT::f64),
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002646 ISD::SETO);
Dale Johannesenf5d97892009-02-04 01:48:28 +00002647 SDValue ordered = DAG.getNode(ISD::AND, dl, ccResultVT, lhsNaN, rhsNaN);
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002648
Dale Johannesenf5d97892009-02-04 01:48:28 +00002649 result = DAG.getNode(ISD::AND, dl, ccResultVT, ordered, result);
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002650 }
2651
2652 return result;
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002653}
2654
Scott Michel7a1c9e92008-11-22 23:50:42 +00002655//! Lower ISD::SELECT_CC
2656/*!
2657 ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2658 SELB instruction.
2659
2660 \note Need to revisit this in the future: if the code path through the true
2661 and false value computations is longer than the latency of a branch (6
2662 cycles), then it would be more advantageous to branch and insert a new basic
2663 block and branch on the condition. However, this code does not make that
2664 assumption, given the simplisitc uses so far.
2665 */
2666
Scott Michelf0569be2008-12-27 04:51:36 +00002667static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
2668 const TargetLowering &TLI) {
Owen Andersone50ed302009-08-10 22:56:29 +00002669 EVT VT = Op.getValueType();
Scott Michel7a1c9e92008-11-22 23:50:42 +00002670 SDValue lhs = Op.getOperand(0);
2671 SDValue rhs = Op.getOperand(1);
2672 SDValue trueval = Op.getOperand(2);
2673 SDValue falseval = Op.getOperand(3);
2674 SDValue condition = Op.getOperand(4);
Dale Johannesende064702009-02-06 21:50:26 +00002675 DebugLoc dl = Op.getDebugLoc();
Scott Michel7a1c9e92008-11-22 23:50:42 +00002676
Scott Michelf0569be2008-12-27 04:51:36 +00002677 // NOTE: SELB's arguments: $rA, $rB, $mask
2678 //
2679 // SELB selects bits from $rA where bits in $mask are 0, bits from $rB
2680 // where bits in $mask are 1. CCond will be inverted, having 1s where the
2681 // condition was true and 0s where the condition was false. Hence, the
2682 // arguments to SELB get reversed.
2683
Scott Michel7a1c9e92008-11-22 23:50:42 +00002684 // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2685 // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2686 // with another "cannot select select_cc" assert:
2687
Dale Johannesende064702009-02-06 21:50:26 +00002688 SDValue compare = DAG.getNode(ISD::SETCC, dl,
Duncan Sands5480c042009-01-01 15:52:00 +00002689 TLI.getSetCCResultType(Op.getValueType()),
Scott Michelf0569be2008-12-27 04:51:36 +00002690 lhs, rhs, condition);
Dale Johannesende064702009-02-06 21:50:26 +00002691 return DAG.getNode(SPUISD::SELB, dl, VT, falseval, trueval, compare);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002692}
2693
Scott Michelb30e8f62008-12-02 19:53:53 +00002694//! Custom lower ISD::TRUNCATE
2695static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
2696{
Scott Michel6e1d1472009-03-16 18:47:25 +00002697 // Type to truncate to
Owen Andersone50ed302009-08-10 22:56:29 +00002698 EVT VT = Op.getValueType();
Owen Anderson825b72b2009-08-11 20:47:22 +00002699 MVT simpleVT = VT.getSimpleVT();
Wesley Peckbf17cfa2010-11-23 03:31:01 +00002700 EVT VecVT = EVT::getVectorVT(*DAG.getContext(),
Owen Anderson23b9b192009-08-12 00:36:31 +00002701 VT, (128 / VT.getSizeInBits()));
Dale Johannesende064702009-02-06 21:50:26 +00002702 DebugLoc dl = Op.getDebugLoc();
Scott Michelb30e8f62008-12-02 19:53:53 +00002703
Scott Michel6e1d1472009-03-16 18:47:25 +00002704 // Type to truncate from
Scott Michelb30e8f62008-12-02 19:53:53 +00002705 SDValue Op0 = Op.getOperand(0);
Owen Andersone50ed302009-08-10 22:56:29 +00002706 EVT Op0VT = Op0.getValueType();
Scott Michelb30e8f62008-12-02 19:53:53 +00002707
Duncan Sandscdfad362010-11-03 12:17:33 +00002708 if (Op0VT == MVT::i128 && simpleVT == MVT::i64) {
Scott Michel52d00012009-01-03 00:27:53 +00002709 // Create shuffle mask, least significant doubleword of quadword
Scott Michelf0569be2008-12-27 04:51:36 +00002710 unsigned maskHigh = 0x08090a0b;
2711 unsigned maskLow = 0x0c0d0e0f;
2712 // Use a shuffle to perform the truncation
Owen Anderson825b72b2009-08-11 20:47:22 +00002713 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
2714 DAG.getConstant(maskHigh, MVT::i32),
2715 DAG.getConstant(maskLow, MVT::i32),
2716 DAG.getConstant(maskHigh, MVT::i32),
2717 DAG.getConstant(maskLow, MVT::i32));
Scott Michelf0569be2008-12-27 04:51:36 +00002718
Scott Michel6e1d1472009-03-16 18:47:25 +00002719 SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, dl, VecVT,
2720 Op0, Op0, shufMask);
Scott Michelf0569be2008-12-27 04:51:36 +00002721
Scott Michel6e1d1472009-03-16 18:47:25 +00002722 return DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT, truncShuffle);
Scott Michelb30e8f62008-12-02 19:53:53 +00002723 }
2724
Scott Michelf0569be2008-12-27 04:51:36 +00002725 return SDValue(); // Leave the truncate unmolested
Scott Michelb30e8f62008-12-02 19:53:53 +00002726}
2727
Scott Michel77f452d2009-08-25 22:37:34 +00002728/*!
2729 * Emit the instruction sequence for i64/i32 -> i128 sign extend. The basic
2730 * algorithm is to duplicate the sign bit using rotmai to generate at
2731 * least one byte full of sign bits. Then propagate the "sign-byte" into
2732 * the leftmost words and the i64/i32 into the rightmost words using shufb.
2733 *
2734 * @param Op The sext operand
2735 * @param DAG The current DAG
2736 * @return The SDValue with the entire instruction sequence
2737 */
Scott Michelf1fa4fd2009-08-24 22:28:53 +00002738static SDValue LowerSIGN_EXTEND(SDValue Op, SelectionDAG &DAG)
2739{
Scott Michelf1fa4fd2009-08-24 22:28:53 +00002740 DebugLoc dl = Op.getDebugLoc();
2741
Scott Michel77f452d2009-08-25 22:37:34 +00002742 // Type to extend to
2743 MVT OpVT = Op.getValueType().getSimpleVT();
Scott Michel77f452d2009-08-25 22:37:34 +00002744
Scott Michelf1fa4fd2009-08-24 22:28:53 +00002745 // Type to extend from
2746 SDValue Op0 = Op.getOperand(0);
Scott Michel77f452d2009-08-25 22:37:34 +00002747 MVT Op0VT = Op0.getValueType().getSimpleVT();
Scott Michelf1fa4fd2009-08-24 22:28:53 +00002748
Kalle Raiskila5106b842011-01-20 15:49:06 +00002749 // extend i8 & i16 via i32
2750 if (Op0VT == MVT::i8 || Op0VT == MVT::i16) {
2751 Op0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, Op0);
2752 Op0VT = MVT::i32;
2753 }
2754
Scott Michel77f452d2009-08-25 22:37:34 +00002755 // The type to extend to needs to be a i128 and
2756 // the type to extend from needs to be i64 or i32.
2757 assert((OpVT == MVT::i128 && (Op0VT == MVT::i64 || Op0VT == MVT::i32)) &&
Scott Michelf1fa4fd2009-08-24 22:28:53 +00002758 "LowerSIGN_EXTEND: input and/or output operand have wrong size");
Duncan Sands1f6a3292011-08-12 14:54:45 +00002759 (void)OpVT;
Scott Michelf1fa4fd2009-08-24 22:28:53 +00002760
2761 // Create shuffle mask
Scott Michel77f452d2009-08-25 22:37:34 +00002762 unsigned mask1 = 0x10101010; // byte 0 - 3 and 4 - 7
2763 unsigned mask2 = Op0VT == MVT::i64 ? 0x00010203 : 0x10101010; // byte 8 - 11
2764 unsigned mask3 = Op0VT == MVT::i64 ? 0x04050607 : 0x00010203; // byte 12 - 15
Scott Michelf1fa4fd2009-08-24 22:28:53 +00002765 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
2766 DAG.getConstant(mask1, MVT::i32),
2767 DAG.getConstant(mask1, MVT::i32),
2768 DAG.getConstant(mask2, MVT::i32),
2769 DAG.getConstant(mask3, MVT::i32));
2770
Scott Michel77f452d2009-08-25 22:37:34 +00002771 // Word wise arithmetic right shift to generate at least one byte
2772 // that contains sign bits.
2773 MVT mvt = Op0VT == MVT::i64 ? MVT::v2i64 : MVT::v4i32;
Scott Michelf1fa4fd2009-08-24 22:28:53 +00002774 SDValue sraVal = DAG.getNode(ISD::SRA,
2775 dl,
Scott Michel77f452d2009-08-25 22:37:34 +00002776 mvt,
2777 DAG.getNode(SPUISD::PREFSLOT2VEC, dl, mvt, Op0, Op0),
Scott Michelf1fa4fd2009-08-24 22:28:53 +00002778 DAG.getConstant(31, MVT::i32));
2779
Kalle Raiskila940e7962010-10-18 09:34:19 +00002780 // reinterpret as a i128 (SHUFB requires it). This gets lowered away.
Wesley Peckbf17cfa2010-11-23 03:31:01 +00002781 SDValue extended = SDValue(DAG.getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
Kalle Raiskila940e7962010-10-18 09:34:19 +00002782 dl, Op0VT, Op0,
2783 DAG.getTargetConstant(
Wesley Peckbf17cfa2010-11-23 03:31:01 +00002784 SPU::GPRCRegClass.getID(),
Kalle Raiskila940e7962010-10-18 09:34:19 +00002785 MVT::i32)), 0);
Scott Michel77f452d2009-08-25 22:37:34 +00002786 // Shuffle bytes - Copy the sign bits into the upper 64 bits
2787 // and the input value into the lower 64 bits.
2788 SDValue extShuffle = DAG.getNode(SPUISD::SHUFB, dl, mvt,
Kalle Raiskila940e7962010-10-18 09:34:19 +00002789 extended, sraVal, shufMask);
Wesley Peckbf17cfa2010-11-23 03:31:01 +00002790 return DAG.getNode(ISD::BITCAST, dl, MVT::i128, extShuffle);
Scott Michelf1fa4fd2009-08-24 22:28:53 +00002791}
2792
Scott Michel7a1c9e92008-11-22 23:50:42 +00002793//! Custom (target-specific) lowering entry point
2794/*!
2795 This is where LLVM's DAG selection process calls to do target-specific
2796 lowering of nodes.
2797 */
Dan Gohman475871a2008-07-27 21:46:04 +00002798SDValue
Dan Gohmand858e902010-04-17 15:26:15 +00002799SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const
Scott Michel266bc8f2007-12-04 22:23:35 +00002800{
Scott Michela59d4692008-02-23 18:41:37 +00002801 unsigned Opc = (unsigned) Op.getOpcode();
Owen Andersone50ed302009-08-10 22:56:29 +00002802 EVT VT = Op.getValueType();
Scott Michela59d4692008-02-23 18:41:37 +00002803
2804 switch (Opc) {
Scott Michel266bc8f2007-12-04 22:23:35 +00002805 default: {
Torok Edwindac237e2009-07-08 20:53:28 +00002806#ifndef NDEBUG
Chris Lattner4437ae22009-08-23 07:05:07 +00002807 errs() << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
2808 errs() << "Op.getOpcode() = " << Opc << "\n";
2809 errs() << "*Op.getNode():\n";
Gabor Greifba36cb52008-08-28 21:40:38 +00002810 Op.getNode()->dump();
Torok Edwindac237e2009-07-08 20:53:28 +00002811#endif
Torok Edwinc23197a2009-07-14 16:55:14 +00002812 llvm_unreachable(0);
Scott Michel266bc8f2007-12-04 22:23:35 +00002813 }
2814 case ISD::LOAD:
Scott Michelb30e8f62008-12-02 19:53:53 +00002815 case ISD::EXTLOAD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002816 case ISD::SEXTLOAD:
2817 case ISD::ZEXTLOAD:
2818 return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2819 case ISD::STORE:
2820 return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2821 case ISD::ConstantPool:
2822 return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2823 case ISD::GlobalAddress:
2824 return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2825 case ISD::JumpTable:
2826 return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
Scott Michel266bc8f2007-12-04 22:23:35 +00002827 case ISD::ConstantFP:
2828 return LowerConstantFP(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002829
Scott Michel02d711b2008-12-30 23:28:25 +00002830 // i8, i64 math ops:
Scott Michel8bf61e82008-06-02 22:18:03 +00002831 case ISD::ADD:
Scott Michel266bc8f2007-12-04 22:23:35 +00002832 case ISD::SUB:
2833 case ISD::ROTR:
2834 case ISD::ROTL:
2835 case ISD::SRL:
2836 case ISD::SHL:
Scott Michel8bf61e82008-06-02 22:18:03 +00002837 case ISD::SRA: {
Owen Anderson825b72b2009-08-11 20:47:22 +00002838 if (VT == MVT::i8)
Scott Michelf0569be2008-12-27 04:51:36 +00002839 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michela59d4692008-02-23 18:41:37 +00002840 break;
Scott Michel8bf61e82008-06-02 22:18:03 +00002841 }
Scott Michel266bc8f2007-12-04 22:23:35 +00002842
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002843 case ISD::FP_TO_SINT:
2844 case ISD::FP_TO_UINT:
2845 return LowerFP_TO_INT(Op, DAG, *this);
2846
2847 case ISD::SINT_TO_FP:
2848 case ISD::UINT_TO_FP:
2849 return LowerINT_TO_FP(Op, DAG, *this);
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002850
Scott Michel266bc8f2007-12-04 22:23:35 +00002851 // Vector-related lowering.
2852 case ISD::BUILD_VECTOR:
Scott Michelc9c8b2a2009-01-26 03:31:40 +00002853 return LowerBUILD_VECTOR(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002854 case ISD::SCALAR_TO_VECTOR:
2855 return LowerSCALAR_TO_VECTOR(Op, DAG);
2856 case ISD::VECTOR_SHUFFLE:
2857 return LowerVECTOR_SHUFFLE(Op, DAG);
2858 case ISD::EXTRACT_VECTOR_ELT:
2859 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2860 case ISD::INSERT_VECTOR_ELT:
2861 return LowerINSERT_VECTOR_ELT(Op, DAG);
2862
2863 // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2864 case ISD::AND:
2865 case ISD::OR:
2866 case ISD::XOR:
2867 return LowerByteImmed(Op, DAG);
2868
2869 // Vector and i8 multiply:
2870 case ISD::MUL:
Owen Anderson825b72b2009-08-11 20:47:22 +00002871 if (VT == MVT::i8)
Scott Michelf0569be2008-12-27 04:51:36 +00002872 return LowerI8Math(Op, DAG, Opc, *this);
Scott Michel266bc8f2007-12-04 22:23:35 +00002873
Scott Michel266bc8f2007-12-04 22:23:35 +00002874 case ISD::CTPOP:
2875 return LowerCTPOP(Op, DAG);
Scott Michel7a1c9e92008-11-22 23:50:42 +00002876
2877 case ISD::SELECT_CC:
Scott Michelf0569be2008-12-27 04:51:36 +00002878 return LowerSELECT_CC(Op, DAG, *this);
Scott Michelb30e8f62008-12-02 19:53:53 +00002879
Scott Micheld1e8d9c2009-01-21 04:58:48 +00002880 case ISD::SETCC:
2881 return LowerSETCC(Op, DAG, *this);
2882
Scott Michelb30e8f62008-12-02 19:53:53 +00002883 case ISD::TRUNCATE:
2884 return LowerTRUNCATE(Op, DAG);
Scott Michelf1fa4fd2009-08-24 22:28:53 +00002885
2886 case ISD::SIGN_EXTEND:
2887 return LowerSIGN_EXTEND(Op, DAG);
Scott Michel266bc8f2007-12-04 22:23:35 +00002888 }
2889
Dan Gohman475871a2008-07-27 21:46:04 +00002890 return SDValue();
Scott Michel266bc8f2007-12-04 22:23:35 +00002891}
2892
Duncan Sands1607f052008-12-01 11:39:25 +00002893void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
2894 SmallVectorImpl<SDValue>&Results,
Dan Gohmand858e902010-04-17 15:26:15 +00002895 SelectionDAG &DAG) const
Scott Michel73ce1c52008-11-10 23:43:06 +00002896{
2897#if 0
2898 unsigned Opc = (unsigned) N->getOpcode();
Owen Andersone50ed302009-08-10 22:56:29 +00002899 EVT OpVT = N->getValueType(0);
Scott Michel73ce1c52008-11-10 23:43:06 +00002900
2901 switch (Opc) {
2902 default: {
Chris Lattner4437ae22009-08-23 07:05:07 +00002903 errs() << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2904 errs() << "Op.getOpcode() = " << Opc << "\n";
2905 errs() << "*Op.getNode():\n";
Scott Michel73ce1c52008-11-10 23:43:06 +00002906 N->dump();
2907 abort();
2908 /*NOTREACHED*/
2909 }
2910 }
2911#endif
2912
2913 /* Otherwise, return unchanged */
Scott Michel73ce1c52008-11-10 23:43:06 +00002914}
2915
Scott Michel266bc8f2007-12-04 22:23:35 +00002916//===----------------------------------------------------------------------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002917// Target Optimization Hooks
2918//===----------------------------------------------------------------------===//
2919
Dan Gohman475871a2008-07-27 21:46:04 +00002920SDValue
Scott Michel266bc8f2007-12-04 22:23:35 +00002921SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2922{
2923#if 0
2924 TargetMachine &TM = getTargetMachine();
Scott Michel053c1da2008-01-29 02:16:57 +00002925#endif
2926 const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
Scott Michel266bc8f2007-12-04 22:23:35 +00002927 SelectionDAG &DAG = DCI.DAG;
Scott Michel1a6cdb62008-12-01 17:56:02 +00002928 SDValue Op0 = N->getOperand(0); // everything has at least one operand
Owen Andersone50ed302009-08-10 22:56:29 +00002929 EVT NodeVT = N->getValueType(0); // The node's value type
2930 EVT Op0VT = Op0.getValueType(); // The first operand's result
Scott Michel1a6cdb62008-12-01 17:56:02 +00002931 SDValue Result; // Initially, empty result
Dale Johannesende064702009-02-06 21:50:26 +00002932 DebugLoc dl = N->getDebugLoc();
Scott Michel266bc8f2007-12-04 22:23:35 +00002933
2934 switch (N->getOpcode()) {
2935 default: break;
Scott Michel053c1da2008-01-29 02:16:57 +00002936 case ISD::ADD: {
Dan Gohman475871a2008-07-27 21:46:04 +00002937 SDValue Op1 = N->getOperand(1);
Scott Michel053c1da2008-01-29 02:16:57 +00002938
Scott Michelf0569be2008-12-27 04:51:36 +00002939 if (Op0.getOpcode() == SPUISD::IndirectAddr
2940 || Op1.getOpcode() == SPUISD::IndirectAddr) {
2941 // Normalize the operands to reduce repeated code
2942 SDValue IndirectArg = Op0, AddArg = Op1;
Scott Michel1df30c42008-12-29 03:23:36 +00002943
Scott Michelf0569be2008-12-27 04:51:36 +00002944 if (Op1.getOpcode() == SPUISD::IndirectAddr) {
2945 IndirectArg = Op1;
2946 AddArg = Op0;
2947 }
2948
2949 if (isa<ConstantSDNode>(AddArg)) {
2950 ConstantSDNode *CN0 = cast<ConstantSDNode > (AddArg);
2951 SDValue IndOp1 = IndirectArg.getOperand(1);
2952
2953 if (CN0->isNullValue()) {
2954 // (add (SPUindirect <arg>, <arg>), 0) ->
2955 // (SPUindirect <arg>, <arg>)
Scott Michel053c1da2008-01-29 02:16:57 +00002956
Scott Michel23f2ff72008-12-04 17:16:59 +00002957#if !defined(NDEBUG)
Scott Michelf0569be2008-12-27 04:51:36 +00002958 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Chris Lattner4437ae22009-08-23 07:05:07 +00002959 errs() << "\n"
Scott Michelf0569be2008-12-27 04:51:36 +00002960 << "Replace: (add (SPUindirect <arg>, <arg>), 0)\n"
2961 << "With: (SPUindirect <arg>, <arg>)\n";
2962 }
Scott Michel30ee7df2008-12-04 03:02:42 +00002963#endif
2964
Scott Michelf0569be2008-12-27 04:51:36 +00002965 return IndirectArg;
2966 } else if (isa<ConstantSDNode>(IndOp1)) {
2967 // (add (SPUindirect <arg>, <const>), <const>) ->
2968 // (SPUindirect <arg>, <const + const>)
2969 ConstantSDNode *CN1 = cast<ConstantSDNode > (IndOp1);
2970 int64_t combinedConst = CN0->getSExtValue() + CN1->getSExtValue();
2971 SDValue combinedValue = DAG.getConstant(combinedConst, Op0VT);
Scott Michel053c1da2008-01-29 02:16:57 +00002972
Scott Michelf0569be2008-12-27 04:51:36 +00002973#if !defined(NDEBUG)
2974 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Chris Lattner4437ae22009-08-23 07:05:07 +00002975 errs() << "\n"
Scott Michelf0569be2008-12-27 04:51:36 +00002976 << "Replace: (add (SPUindirect <arg>, " << CN1->getSExtValue()
2977 << "), " << CN0->getSExtValue() << ")\n"
2978 << "With: (SPUindirect <arg>, "
2979 << combinedConst << ")\n";
2980 }
2981#endif
Scott Michel053c1da2008-01-29 02:16:57 +00002982
Dale Johannesende064702009-02-06 21:50:26 +00002983 return DAG.getNode(SPUISD::IndirectAddr, dl, Op0VT,
Scott Michelf0569be2008-12-27 04:51:36 +00002984 IndirectArg, combinedValue);
2985 }
Scott Michel053c1da2008-01-29 02:16:57 +00002986 }
2987 }
Scott Michela59d4692008-02-23 18:41:37 +00002988 break;
2989 }
2990 case ISD::SIGN_EXTEND:
2991 case ISD::ZERO_EXTEND:
2992 case ISD::ANY_EXTEND: {
Scott Michel1a6cdb62008-12-01 17:56:02 +00002993 if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
Scott Michela59d4692008-02-23 18:41:37 +00002994 // (any_extend (SPUextract_elt0 <arg>)) ->
2995 // (SPUextract_elt0 <arg>)
2996 // Types must match, however...
Scott Michel23f2ff72008-12-04 17:16:59 +00002997#if !defined(NDEBUG)
2998 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Chris Lattner4437ae22009-08-23 07:05:07 +00002999 errs() << "\nReplace: ";
Scott Michel30ee7df2008-12-04 03:02:42 +00003000 N->dump(&DAG);
Chris Lattner4437ae22009-08-23 07:05:07 +00003001 errs() << "\nWith: ";
Scott Michel30ee7df2008-12-04 03:02:42 +00003002 Op0.getNode()->dump(&DAG);
Chris Lattner4437ae22009-08-23 07:05:07 +00003003 errs() << "\n";
Scott Michel23f2ff72008-12-04 17:16:59 +00003004 }
Scott Michel30ee7df2008-12-04 03:02:42 +00003005#endif
Scott Michela59d4692008-02-23 18:41:37 +00003006
3007 return Op0;
3008 }
3009 break;
3010 }
3011 case SPUISD::IndirectAddr: {
3012 if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
Scott Micheld1e8d9c2009-01-21 04:58:48 +00003013 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1));
Dan Gohmane368b462010-06-18 14:22:04 +00003014 if (CN != 0 && CN->isNullValue()) {
Scott Michela59d4692008-02-23 18:41:37 +00003015 // (SPUindirect (SPUaform <addr>, 0), 0) ->
3016 // (SPUaform <addr>, 0)
3017
Chris Lattner4437ae22009-08-23 07:05:07 +00003018 DEBUG(errs() << "Replace: ");
Scott Michela59d4692008-02-23 18:41:37 +00003019 DEBUG(N->dump(&DAG));
Chris Lattner4437ae22009-08-23 07:05:07 +00003020 DEBUG(errs() << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00003021 DEBUG(Op0.getNode()->dump(&DAG));
Chris Lattner4437ae22009-08-23 07:05:07 +00003022 DEBUG(errs() << "\n");
Scott Michela59d4692008-02-23 18:41:37 +00003023
3024 return Op0;
3025 }
Scott Michelf0569be2008-12-27 04:51:36 +00003026 } else if (Op0.getOpcode() == ISD::ADD) {
3027 SDValue Op1 = N->getOperand(1);
3028 if (ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(Op1)) {
3029 // (SPUindirect (add <arg>, <arg>), 0) ->
3030 // (SPUindirect <arg>, <arg>)
3031 if (CN1->isNullValue()) {
3032
3033#if !defined(NDEBUG)
3034 if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
Chris Lattner4437ae22009-08-23 07:05:07 +00003035 errs() << "\n"
Scott Michelf0569be2008-12-27 04:51:36 +00003036 << "Replace: (SPUindirect (add <arg>, <arg>), 0)\n"
3037 << "With: (SPUindirect <arg>, <arg>)\n";
3038 }
3039#endif
3040
Dale Johannesende064702009-02-06 21:50:26 +00003041 return DAG.getNode(SPUISD::IndirectAddr, dl, Op0VT,
Scott Michelf0569be2008-12-27 04:51:36 +00003042 Op0.getOperand(0), Op0.getOperand(1));
3043 }
3044 }
Scott Michela59d4692008-02-23 18:41:37 +00003045 }
3046 break;
3047 }
Kalle Raiskila7ea1ab52010-11-12 10:14:03 +00003048 case SPUISD::SHL_BITS:
3049 case SPUISD::SHL_BYTES:
Scott Michelf0569be2008-12-27 04:51:36 +00003050 case SPUISD::ROTBYTES_LEFT: {
Dan Gohman475871a2008-07-27 21:46:04 +00003051 SDValue Op1 = N->getOperand(1);
Scott Michela59d4692008-02-23 18:41:37 +00003052
Scott Michelf0569be2008-12-27 04:51:36 +00003053 // Kill degenerate vector shifts:
3054 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1)) {
3055 if (CN->isNullValue()) {
Scott Michela59d4692008-02-23 18:41:37 +00003056 Result = Op0;
3057 }
3058 }
3059 break;
3060 }
Scott Michelf0569be2008-12-27 04:51:36 +00003061 case SPUISD::PREFSLOT2VEC: {
Scott Michela59d4692008-02-23 18:41:37 +00003062 switch (Op0.getOpcode()) {
3063 default:
3064 break;
3065 case ISD::ANY_EXTEND:
3066 case ISD::ZERO_EXTEND:
3067 case ISD::SIGN_EXTEND: {
Scott Michel1df30c42008-12-29 03:23:36 +00003068 // (SPUprefslot2vec (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
Scott Michela59d4692008-02-23 18:41:37 +00003069 // <arg>
Scott Michel1df30c42008-12-29 03:23:36 +00003070 // but only if the SPUprefslot2vec and <arg> types match.
Dan Gohman475871a2008-07-27 21:46:04 +00003071 SDValue Op00 = Op0.getOperand(0);
Scott Michel104de432008-11-24 17:11:17 +00003072 if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
Dan Gohman475871a2008-07-27 21:46:04 +00003073 SDValue Op000 = Op00.getOperand(0);
Scott Michel1a6cdb62008-12-01 17:56:02 +00003074 if (Op000.getValueType() == NodeVT) {
Scott Michela59d4692008-02-23 18:41:37 +00003075 Result = Op000;
3076 }
3077 }
3078 break;
3079 }
Scott Michel104de432008-11-24 17:11:17 +00003080 case SPUISD::VEC2PREFSLOT: {
Scott Michel1df30c42008-12-29 03:23:36 +00003081 // (SPUprefslot2vec (SPUvec2prefslot <arg>)) ->
Scott Michela59d4692008-02-23 18:41:37 +00003082 // <arg>
3083 Result = Op0.getOperand(0);
3084 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003085 }
Scott Michela59d4692008-02-23 18:41:37 +00003086 }
3087 break;
Scott Michel053c1da2008-01-29 02:16:57 +00003088 }
3089 }
Scott Micheld1e8d9c2009-01-21 04:58:48 +00003090
Scott Michel58c58182008-01-17 20:38:41 +00003091 // Otherwise, return unchanged.
Scott Michel1a6cdb62008-12-01 17:56:02 +00003092#ifndef NDEBUG
Gabor Greifba36cb52008-08-28 21:40:38 +00003093 if (Result.getNode()) {
Chris Lattner4437ae22009-08-23 07:05:07 +00003094 DEBUG(errs() << "\nReplace.SPU: ");
Scott Michela59d4692008-02-23 18:41:37 +00003095 DEBUG(N->dump(&DAG));
Chris Lattner4437ae22009-08-23 07:05:07 +00003096 DEBUG(errs() << "\nWith: ");
Gabor Greifba36cb52008-08-28 21:40:38 +00003097 DEBUG(Result.getNode()->dump(&DAG));
Chris Lattner4437ae22009-08-23 07:05:07 +00003098 DEBUG(errs() << "\n");
Scott Michela59d4692008-02-23 18:41:37 +00003099 }
3100#endif
3101
3102 return Result;
Scott Michel266bc8f2007-12-04 22:23:35 +00003103}
3104
3105//===----------------------------------------------------------------------===//
3106// Inline Assembly Support
3107//===----------------------------------------------------------------------===//
3108
3109/// getConstraintType - Given a constraint letter, return the type of
3110/// constraint it is for this target.
Scott Michel5af8f0e2008-07-16 17:17:29 +00003111SPUTargetLowering::ConstraintType
Scott Michel266bc8f2007-12-04 22:23:35 +00003112SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3113 if (ConstraintLetter.size() == 1) {
3114 switch (ConstraintLetter[0]) {
3115 default: break;
3116 case 'b':
3117 case 'r':
3118 case 'f':
3119 case 'v':
3120 case 'y':
3121 return C_RegisterClass;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003122 }
Scott Michel266bc8f2007-12-04 22:23:35 +00003123 }
3124 return TargetLowering::getConstraintType(ConstraintLetter);
3125}
3126
John Thompson44ab89e2010-10-29 17:29:13 +00003127/// Examine constraint type and operand type and determine a weight value.
3128/// This object must already have been set up with the operand type
3129/// and the current alternative constraint selected.
3130TargetLowering::ConstraintWeight
3131SPUTargetLowering::getSingleConstraintMatchWeight(
3132 AsmOperandInfo &info, const char *constraint) const {
3133 ConstraintWeight weight = CW_Invalid;
3134 Value *CallOperandVal = info.CallOperandVal;
3135 // If we don't have a value, we can't do a match,
3136 // but allow it at the lowest weight.
3137 if (CallOperandVal == NULL)
3138 return CW_Default;
3139 // Look at the constraint type.
3140 switch (*constraint) {
3141 default:
3142 weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
Owen Anderson95771af2011-02-25 21:41:48 +00003143 break;
John Thompson44ab89e2010-10-29 17:29:13 +00003144 //FIXME: Seems like the supported constraint letters were just copied
3145 // from PPC, as the following doesn't correspond to the GCC docs.
3146 // I'm leaving it so until someone adds the corresponding lowering support.
3147 case 'b':
3148 case 'r':
3149 case 'f':
3150 case 'd':
3151 case 'v':
3152 case 'y':
3153 weight = CW_Register;
3154 break;
3155 }
3156 return weight;
3157}
3158
Scott Michel5af8f0e2008-07-16 17:17:29 +00003159std::pair<unsigned, const TargetRegisterClass*>
Scott Michel266bc8f2007-12-04 22:23:35 +00003160SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
Owen Andersone50ed302009-08-10 22:56:29 +00003161 EVT VT) const
Scott Michel266bc8f2007-12-04 22:23:35 +00003162{
3163 if (Constraint.size() == 1) {
3164 // GCC RS6000 Constraint Letters
3165 switch (Constraint[0]) {
3166 case 'b': // R1-R31
3167 case 'r': // R0-R31
Owen Anderson825b72b2009-08-11 20:47:22 +00003168 if (VT == MVT::i64)
Scott Michel266bc8f2007-12-04 22:23:35 +00003169 return std::make_pair(0U, SPU::R64CRegisterClass);
3170 return std::make_pair(0U, SPU::R32CRegisterClass);
3171 case 'f':
Owen Anderson825b72b2009-08-11 20:47:22 +00003172 if (VT == MVT::f32)
Scott Michel266bc8f2007-12-04 22:23:35 +00003173 return std::make_pair(0U, SPU::R32FPRegisterClass);
Owen Anderson825b72b2009-08-11 20:47:22 +00003174 else if (VT == MVT::f64)
Scott Michel266bc8f2007-12-04 22:23:35 +00003175 return std::make_pair(0U, SPU::R64FPRegisterClass);
3176 break;
Scott Michel5af8f0e2008-07-16 17:17:29 +00003177 case 'v':
Scott Michel266bc8f2007-12-04 22:23:35 +00003178 return std::make_pair(0U, SPU::GPRCRegisterClass);
3179 }
3180 }
Scott Michel5af8f0e2008-07-16 17:17:29 +00003181
Scott Michel266bc8f2007-12-04 22:23:35 +00003182 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3183}
3184
Scott Michela59d4692008-02-23 18:41:37 +00003185//! Compute used/known bits for a SPU operand
Scott Michel266bc8f2007-12-04 22:23:35 +00003186void
Dan Gohman475871a2008-07-27 21:46:04 +00003187SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Dan Gohman977a76f2008-02-13 22:28:48 +00003188 const APInt &Mask,
Scott Michel5af8f0e2008-07-16 17:17:29 +00003189 APInt &KnownZero,
Dan Gohmanfd29e0e2008-02-13 00:35:47 +00003190 APInt &KnownOne,
Scott Michel7f9ba9b2008-01-30 02:55:46 +00003191 const SelectionDAG &DAG,
3192 unsigned Depth ) const {
Scott Michel203b2d62008-04-30 00:30:08 +00003193#if 0
Dan Gohmande551f92009-04-01 18:45:54 +00003194 const uint64_t uint64_sizebits = sizeof(uint64_t) * CHAR_BIT;
Scott Michela59d4692008-02-23 18:41:37 +00003195
3196 switch (Op.getOpcode()) {
3197 default:
3198 // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3199 break;
Scott Michela59d4692008-02-23 18:41:37 +00003200 case CALL:
3201 case SHUFB:
Scott Michel7a1c9e92008-11-22 23:50:42 +00003202 case SHUFFLE_MASK:
Scott Michela59d4692008-02-23 18:41:37 +00003203 case CNTB:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00003204 case SPUISD::PREFSLOT2VEC:
Scott Michela59d4692008-02-23 18:41:37 +00003205 case SPUISD::LDRESULT:
Scott Micheld1e8d9c2009-01-21 04:58:48 +00003206 case SPUISD::VEC2PREFSLOT:
Scott Michel203b2d62008-04-30 00:30:08 +00003207 case SPUISD::SHLQUAD_L_BITS:
3208 case SPUISD::SHLQUAD_L_BYTES:
Scott Michel203b2d62008-04-30 00:30:08 +00003209 case SPUISD::VEC_ROTL:
3210 case SPUISD::VEC_ROTR:
Scott Michel203b2d62008-04-30 00:30:08 +00003211 case SPUISD::ROTBYTES_LEFT:
Scott Michel8bf61e82008-06-02 22:18:03 +00003212 case SPUISD::SELECT_MASK:
3213 case SPUISD::SELB:
Scott Michela59d4692008-02-23 18:41:37 +00003214 }
Scott Micheld1e8d9c2009-01-21 04:58:48 +00003215#endif
Scott Michel266bc8f2007-12-04 22:23:35 +00003216}
Scott Michel02d711b2008-12-30 23:28:25 +00003217
Scott Michelf0569be2008-12-27 04:51:36 +00003218unsigned
3219SPUTargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op,
3220 unsigned Depth) const {
3221 switch (Op.getOpcode()) {
3222 default:
3223 return 1;
Scott Michel266bc8f2007-12-04 22:23:35 +00003224
Scott Michelf0569be2008-12-27 04:51:36 +00003225 case ISD::SETCC: {
Owen Andersone50ed302009-08-10 22:56:29 +00003226 EVT VT = Op.getValueType();
Scott Michelf0569be2008-12-27 04:51:36 +00003227
Owen Anderson825b72b2009-08-11 20:47:22 +00003228 if (VT != MVT::i8 && VT != MVT::i16 && VT != MVT::i32) {
3229 VT = MVT::i32;
Scott Michelf0569be2008-12-27 04:51:36 +00003230 }
3231 return VT.getSizeInBits();
3232 }
3233 }
3234}
Scott Michel1df30c42008-12-29 03:23:36 +00003235
Scott Michel203b2d62008-04-30 00:30:08 +00003236// LowerAsmOperandForConstraint
3237void
Dan Gohman475871a2008-07-27 21:46:04 +00003238SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Eric Christopher100c8332011-06-02 23:16:42 +00003239 std::string &Constraint,
Dan Gohman475871a2008-07-27 21:46:04 +00003240 std::vector<SDValue> &Ops,
Scott Michel203b2d62008-04-30 00:30:08 +00003241 SelectionDAG &DAG) const {
3242 // Default, for the time being, to the base class handler
Eric Christopher100c8332011-06-02 23:16:42 +00003243 TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
Scott Michel203b2d62008-04-30 00:30:08 +00003244}
3245
Scott Michel266bc8f2007-12-04 22:23:35 +00003246/// isLegalAddressImmediate - Return true if the integer value can be used
3247/// as the offset of the target addressing mode.
Gabor Greif93c53e52008-08-31 15:37:04 +00003248bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
Chris Lattnerdb125cf2011-07-18 04:54:35 +00003249 Type *Ty) const {
Scott Michel266bc8f2007-12-04 22:23:35 +00003250 // SPU's addresses are 256K:
3251 return (V > -(1 << 18) && V < (1 << 18) - 1);
3252}
3253
3254bool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
Scott Michel5af8f0e2008-07-16 17:17:29 +00003255 return false;
Scott Michel266bc8f2007-12-04 22:23:35 +00003256}
Dan Gohman6520e202008-10-18 02:06:02 +00003257
3258bool
3259SPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3260 // The SPU target isn't yet aware of offsets.
3261 return false;
3262}
Kalle Raiskila8a52fa62010-10-07 16:24:35 +00003263
3264// can we compare to Imm without writing it into a register?
3265bool SPUTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
3266 //ceqi, cgti, etc. all take s10 operand
3267 return isInt<10>(Imm);
3268}
3269
Wesley Peckbf17cfa2010-11-23 03:31:01 +00003270bool
3271SPUTargetLowering::isLegalAddressingMode(const AddrMode &AM,
Chris Lattnerdb125cf2011-07-18 04:54:35 +00003272 Type * ) const{
Kalle Raiskila8a52fa62010-10-07 16:24:35 +00003273
Wesley Peckbf17cfa2010-11-23 03:31:01 +00003274 // A-form: 18bit absolute address.
Kalle Raiskila8a52fa62010-10-07 16:24:35 +00003275 if (AM.BaseGV && !AM.HasBaseReg && AM.Scale == 0 && AM.BaseOffs == 0)
3276 return true;
Wesley Peckbf17cfa2010-11-23 03:31:01 +00003277
Kalle Raiskila8a52fa62010-10-07 16:24:35 +00003278 // D-form: reg + 14bit offset
3279 if (AM.BaseGV ==0 && AM.HasBaseReg && AM.Scale == 0 && isInt<14>(AM.BaseOffs))
3280 return true;
3281
3282 // X-form: reg+reg
3283 if (AM.BaseGV == 0 && AM.HasBaseReg && AM.Scale == 1 && AM.BaseOffs ==0)
3284 return true;
3285
3286 return false;
3287}