blob: 76b22843696a05ed827c6dba19f74bc66ec917db [file] [log] [blame]
Chris Lattner4ee451d2007-12-29 20:36:04 +00001//===-- SPUISelDAGToDAG.cpp - CellSPU pattern matching inst selector ------===//
Scott Michel266bc8f2007-12-04 22:23:35 +00002//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Scott Michel266bc8f2007-12-04 22:23:35 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a pattern matching instruction selector for the Cell SPU,
11// converting from a legalized dag to a SPU-target dag.
12//
13//===----------------------------------------------------------------------===//
14
15#include "SPU.h"
16#include "SPUTargetMachine.h"
17#include "SPUISelLowering.h"
18#include "SPUHazardRecognizers.h"
19#include "SPUFrameInfo.h"
Scott Michel203b2d62008-04-30 00:30:08 +000020#include "SPURegisterNames.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000021#include "llvm/CodeGen/MachineConstantPool.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineFunction.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000024#include "llvm/CodeGen/SelectionDAG.h"
25#include "llvm/CodeGen/SelectionDAGISel.h"
26#include "llvm/Target/TargetOptions.h"
27#include "llvm/ADT/Statistic.h"
28#include "llvm/Constants.h"
29#include "llvm/GlobalValue.h"
30#include "llvm/Intrinsics.h"
31#include "llvm/Support/Debug.h"
32#include "llvm/Support/MathExtras.h"
33#include "llvm/Support/Compiler.h"
Scott Michel266bc8f2007-12-04 22:23:35 +000034
35using namespace llvm;
36
37namespace {
38 //! ConstantSDNode predicate for i32 sign-extended, 10-bit immediates
39 bool
40 isI64IntS10Immediate(ConstantSDNode *CN)
41 {
Dan Gohman7810bfe2008-09-26 21:54:37 +000042 return isS10Constant(CN->getSExtValue());
Scott Michel266bc8f2007-12-04 22:23:35 +000043 }
44
45 //! ConstantSDNode predicate for i32 sign-extended, 10-bit immediates
46 bool
47 isI32IntS10Immediate(ConstantSDNode *CN)
48 {
Dan Gohman7810bfe2008-09-26 21:54:37 +000049 return isS10Constant(CN->getSExtValue());
Scott Michel266bc8f2007-12-04 22:23:35 +000050 }
51
52#if 0
53 //! SDNode predicate for sign-extended, 10-bit immediate values
54 bool
55 isI32IntS10Immediate(SDNode *N)
56 {
57 return (N->getOpcode() == ISD::Constant
58 && isI32IntS10Immediate(cast<ConstantSDNode>(N)));
59 }
60#endif
61
Scott Michel504c3692007-12-17 22:32:34 +000062 //! ConstantSDNode predicate for i32 unsigned 10-bit immediate values
63 bool
64 isI32IntU10Immediate(ConstantSDNode *CN)
65 {
Dan Gohman7810bfe2008-09-26 21:54:37 +000066 return isU10Constant(CN->getSExtValue());
Scott Michel504c3692007-12-17 22:32:34 +000067 }
68
Scott Michel266bc8f2007-12-04 22:23:35 +000069 //! ConstantSDNode predicate for i16 sign-extended, 10-bit immediate values
70 bool
71 isI16IntS10Immediate(ConstantSDNode *CN)
72 {
Dan Gohman7810bfe2008-09-26 21:54:37 +000073 return isS10Constant(CN->getSExtValue());
Scott Michel266bc8f2007-12-04 22:23:35 +000074 }
75
76 //! SDNode predicate for i16 sign-extended, 10-bit immediate values
77 bool
78 isI16IntS10Immediate(SDNode *N)
79 {
80 return (N->getOpcode() == ISD::Constant
81 && isI16IntS10Immediate(cast<ConstantSDNode>(N)));
82 }
83
Scott Michelec2a08f2007-12-15 00:38:50 +000084 //! ConstantSDNode predicate for i16 unsigned 10-bit immediate values
85 bool
86 isI16IntU10Immediate(ConstantSDNode *CN)
87 {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +000088 return isU10Constant((short) CN->getZExtValue());
Scott Michelec2a08f2007-12-15 00:38:50 +000089 }
90
91 //! SDNode predicate for i16 sign-extended, 10-bit immediate values
92 bool
93 isI16IntU10Immediate(SDNode *N)
94 {
95 return (N->getOpcode() == ISD::Constant
96 && isI16IntU10Immediate(cast<ConstantSDNode>(N)));
97 }
98
Scott Michel266bc8f2007-12-04 22:23:35 +000099 //! ConstantSDNode predicate for signed 16-bit values
100 /*!
101 \arg CN The constant SelectionDAG node holding the value
102 \arg Imm The returned 16-bit value, if returning true
103
104 This predicate tests the value in \a CN to see whether it can be
105 represented as a 16-bit, sign-extended quantity. Returns true if
106 this is the case.
107 */
108 bool
109 isIntS16Immediate(ConstantSDNode *CN, short &Imm)
110 {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000111 MVT vt = CN->getValueType(0);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000112 Imm = (short) CN->getZExtValue();
Duncan Sands8e4eb092008-06-08 20:54:56 +0000113 if (vt.getSimpleVT() >= MVT::i1 && vt.getSimpleVT() <= MVT::i16) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000114 return true;
115 } else if (vt == MVT::i32) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000116 int32_t i_val = (int32_t) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000117 short s_val = (short) i_val;
118 return i_val == s_val;
119 } else {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000120 int64_t i_val = (int64_t) CN->getZExtValue();
Scott Michel266bc8f2007-12-04 22:23:35 +0000121 short s_val = (short) i_val;
122 return i_val == s_val;
123 }
124
125 return false;
126 }
127
128 //! SDNode predicate for signed 16-bit values.
129 bool
130 isIntS16Immediate(SDNode *N, short &Imm)
131 {
132 return (N->getOpcode() == ISD::Constant
133 && isIntS16Immediate(cast<ConstantSDNode>(N), Imm));
134 }
135
136 //! ConstantFPSDNode predicate for representing floats as 16-bit sign ext.
137 static bool
138 isFPS16Immediate(ConstantFPSDNode *FPN, short &Imm)
139 {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000140 MVT vt = FPN->getValueType(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000141 if (vt == MVT::f32) {
Chris Lattnerd3ada752007-12-22 22:45:38 +0000142 int val = FloatToBits(FPN->getValueAPF().convertToFloat());
Scott Michel266bc8f2007-12-04 22:23:35 +0000143 int sval = (int) ((val << 16) >> 16);
144 Imm = (short) val;
145 return val == sval;
146 }
147
148 return false;
149 }
150
Scott Michel053c1da2008-01-29 02:16:57 +0000151 bool
Scott Michel02d711b2008-12-30 23:28:25 +0000152 isHighLow(const SDValue &Op)
Scott Michel053c1da2008-01-29 02:16:57 +0000153 {
154 return (Op.getOpcode() == SPUISD::IndirectAddr
155 && ((Op.getOperand(0).getOpcode() == SPUISD::Hi
156 && Op.getOperand(1).getOpcode() == SPUISD::Lo)
157 || (Op.getOperand(0).getOpcode() == SPUISD::Lo
158 && Op.getOperand(1).getOpcode() == SPUISD::Hi)));
159 }
160
Scott Michel266bc8f2007-12-04 22:23:35 +0000161 //===------------------------------------------------------------------===//
Duncan Sands83ec4b62008-06-06 12:08:01 +0000162 //! MVT to "useful stuff" mapping structure:
Scott Michel266bc8f2007-12-04 22:23:35 +0000163
164 struct valtype_map_s {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000165 MVT VT;
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000166 unsigned ldresult_ins; /// LDRESULT instruction (0 = undefined)
Scott Michela59d4692008-02-23 18:41:37 +0000167 bool ldresult_imm; /// LDRESULT instruction requires immediate?
Scott Michelf0569be2008-12-27 04:51:36 +0000168 unsigned lrinst; /// LR instruction
Scott Michel266bc8f2007-12-04 22:23:35 +0000169 };
170
171 const valtype_map_s valtype_map[] = {
Scott Michelf0569be2008-12-27 04:51:36 +0000172 { MVT::i8, SPU::ORBIr8, true, SPU::LRr8 },
173 { MVT::i16, SPU::ORHIr16, true, SPU::LRr16 },
174 { MVT::i32, SPU::ORIr32, true, SPU::LRr32 },
175 { MVT::i64, SPU::ORr64, false, SPU::LRr64 },
176 { MVT::f32, SPU::ORf32, false, SPU::LRf32 },
177 { MVT::f64, SPU::ORf64, false, SPU::LRf64 },
Scott Michel58c58182008-01-17 20:38:41 +0000178 // vector types... (sigh!)
Scott Michelf0569be2008-12-27 04:51:36 +0000179 { MVT::v16i8, 0, false, SPU::LRv16i8 },
180 { MVT::v8i16, 0, false, SPU::LRv8i16 },
181 { MVT::v4i32, 0, false, SPU::LRv4i32 },
182 { MVT::v2i64, 0, false, SPU::LRv2i64 },
183 { MVT::v4f32, 0, false, SPU::LRv4f32 },
184 { MVT::v2f64, 0, false, SPU::LRv2f64 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000185 };
186
187 const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
188
Duncan Sands83ec4b62008-06-06 12:08:01 +0000189 const valtype_map_s *getValueTypeMapEntry(MVT VT)
Scott Michel266bc8f2007-12-04 22:23:35 +0000190 {
191 const valtype_map_s *retval = 0;
192 for (size_t i = 0; i < n_valtype_map; ++i) {
193 if (valtype_map[i].VT == VT) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000194 retval = valtype_map + i;
195 break;
Scott Michel266bc8f2007-12-04 22:23:35 +0000196 }
197 }
198
199
200#ifndef NDEBUG
201 if (retval == 0) {
202 cerr << "SPUISelDAGToDAG.cpp: getValueTypeMapEntry returns NULL for "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000203 << VT.getMVTString()
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000204 << "\n";
Scott Michel266bc8f2007-12-04 22:23:35 +0000205 abort();
206 }
207#endif
208
209 return retval;
210 }
211}
212
Dan Gohman844731a2008-05-13 00:00:25 +0000213namespace {
214
Scott Michel266bc8f2007-12-04 22:23:35 +0000215//===--------------------------------------------------------------------===//
216/// SPUDAGToDAGISel - Cell SPU-specific code to select SPU machine
217/// instructions for SelectionDAG operations.
218///
219class SPUDAGToDAGISel :
220 public SelectionDAGISel
221{
222 SPUTargetMachine &TM;
223 SPUTargetLowering &SPUtli;
224 unsigned GlobalBaseReg;
225
226public:
Dan Gohman1002c022008-07-07 18:00:37 +0000227 explicit SPUDAGToDAGISel(SPUTargetMachine &tm) :
Scott Michel266bc8f2007-12-04 22:23:35 +0000228 SelectionDAGISel(*tm.getTargetLowering()),
229 TM(tm),
230 SPUtli(*tm.getTargetLowering())
231 {}
Scott Michel02d711b2008-12-30 23:28:25 +0000232
Scott Michel266bc8f2007-12-04 22:23:35 +0000233 virtual bool runOnFunction(Function &Fn) {
234 // Make sure we re-emit a set of the global base reg if necessary
235 GlobalBaseReg = 0;
236 SelectionDAGISel::runOnFunction(Fn);
237 return true;
238 }
Scott Michel02d711b2008-12-30 23:28:25 +0000239
Scott Michel266bc8f2007-12-04 22:23:35 +0000240 /// getI32Imm - Return a target constant with the specified value, of type
241 /// i32.
Dan Gohman475871a2008-07-27 21:46:04 +0000242 inline SDValue getI32Imm(uint32_t Imm) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000243 return CurDAG->getTargetConstant(Imm, MVT::i32);
244 }
245
246 /// getI64Imm - Return a target constant with the specified value, of type
247 /// i64.
Dan Gohman475871a2008-07-27 21:46:04 +0000248 inline SDValue getI64Imm(uint64_t Imm) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000249 return CurDAG->getTargetConstant(Imm, MVT::i64);
250 }
Scott Michel02d711b2008-12-30 23:28:25 +0000251
Scott Michel266bc8f2007-12-04 22:23:35 +0000252 /// getSmallIPtrImm - Return a target constant of pointer type.
Dan Gohman475871a2008-07-27 21:46:04 +0000253 inline SDValue getSmallIPtrImm(unsigned Imm) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000254 return CurDAG->getTargetConstant(Imm, SPUtli.getPointerTy());
255 }
256
257 /// Select - Convert the specified operand from a target-independent to a
258 /// target-specific node if it hasn't already been changed.
Dan Gohman475871a2008-07-27 21:46:04 +0000259 SDNode *Select(SDValue Op);
Scott Michel266bc8f2007-12-04 22:23:35 +0000260
Scott Michel02d711b2008-12-30 23:28:25 +0000261 //! Emit the instruction sequence for i64 shl
262 SDNode *SelectSHLi64(SDValue &Op, MVT OpVT);
263
264 //! Emit the instruction sequence for i64 srl
265 SDNode *SelectSRLi64(SDValue &Op, MVT OpVT);
266
267 //! Emit the instruction sequence for i64 sra
268 SDNode *SelectSRAi64(SDValue &Op, MVT OpVT);
269
Scott Michel266bc8f2007-12-04 22:23:35 +0000270 //! Returns true if the address N is an A-form (local store) address
Dan Gohman475871a2008-07-27 21:46:04 +0000271 bool SelectAFormAddr(SDValue Op, SDValue N, SDValue &Base,
272 SDValue &Index);
Scott Michel266bc8f2007-12-04 22:23:35 +0000273
274 //! D-form address predicate
Dan Gohman475871a2008-07-27 21:46:04 +0000275 bool SelectDFormAddr(SDValue Op, SDValue N, SDValue &Base,
276 SDValue &Index);
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000277
278 /// Alternate D-form address using i7 offset predicate
Dan Gohman475871a2008-07-27 21:46:04 +0000279 bool SelectDForm2Addr(SDValue Op, SDValue N, SDValue &Disp,
280 SDValue &Base);
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000281
282 /// D-form address selection workhorse
Dan Gohman475871a2008-07-27 21:46:04 +0000283 bool DFormAddressPredicate(SDValue Op, SDValue N, SDValue &Disp,
284 SDValue &Base, int minOffset, int maxOffset);
Scott Michel266bc8f2007-12-04 22:23:35 +0000285
286 //! Address predicate if N can be expressed as an indexed [r+r] operation.
Dan Gohman475871a2008-07-27 21:46:04 +0000287 bool SelectXFormAddr(SDValue Op, SDValue N, SDValue &Base,
288 SDValue &Index);
Scott Michel266bc8f2007-12-04 22:23:35 +0000289
290 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
291 /// inline asm expressions.
Dan Gohman475871a2008-07-27 21:46:04 +0000292 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000293 char ConstraintCode,
Dan Gohmanf350b272008-08-23 02:25:05 +0000294 std::vector<SDValue> &OutOps) {
Dan Gohman475871a2008-07-27 21:46:04 +0000295 SDValue Op0, Op1;
Scott Michel266bc8f2007-12-04 22:23:35 +0000296 switch (ConstraintCode) {
297 default: return true;
298 case 'm': // memory
Scott Michel02d711b2008-12-30 23:28:25 +0000299 if (!SelectDFormAddr(Op, Op, Op0, Op1)
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000300 && !SelectAFormAddr(Op, Op, Op0, Op1))
301 SelectXFormAddr(Op, Op, Op0, Op1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000302 break;
303 case 'o': // offsetable
304 if (!SelectDFormAddr(Op, Op, Op0, Op1)
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000305 && !SelectAFormAddr(Op, Op, Op0, Op1)) {
306 Op0 = Op;
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000307 Op1 = getSmallIPtrImm(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000308 }
309 break;
310 case 'v': // not offsetable
311#if 1
312 assert(0 && "InlineAsmMemoryOperand 'v' constraint not handled.");
313#else
314 SelectAddrIdxOnly(Op, Op, Op0, Op1);
315#endif
316 break;
317 }
Scott Michel02d711b2008-12-30 23:28:25 +0000318
Scott Michel266bc8f2007-12-04 22:23:35 +0000319 OutOps.push_back(Op0);
320 OutOps.push_back(Op1);
321 return false;
322 }
323
Evan Chengdb8d56b2008-06-30 20:45:06 +0000324 /// InstructionSelect - This callback is invoked by
Scott Michel266bc8f2007-12-04 22:23:35 +0000325 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
Dan Gohmanf350b272008-08-23 02:25:05 +0000326 virtual void InstructionSelect();
Scott Michel266bc8f2007-12-04 22:23:35 +0000327
328 virtual const char *getPassName() const {
329 return "Cell SPU DAG->DAG Pattern Instruction Selection";
Scott Michel02d711b2008-12-30 23:28:25 +0000330 }
331
Scott Michel266bc8f2007-12-04 22:23:35 +0000332 /// CreateTargetHazardRecognizer - Return the hazard recognizer to use for
333 /// this target when scheduling the DAG.
334 virtual HazardRecognizer *CreateTargetHazardRecognizer() {
Dan Gohman6448d912008-09-04 15:39:15 +0000335 const TargetInstrInfo *II = TM.getInstrInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +0000336 assert(II && "No InstrInfo?");
Scott Michel02d711b2008-12-30 23:28:25 +0000337 return new SPUHazardRecognizer(*II);
Scott Michel266bc8f2007-12-04 22:23:35 +0000338 }
339
340 // Include the pieces autogenerated from the target description.
341#include "SPUGenDAGISel.inc"
342};
343
Dan Gohman844731a2008-05-13 00:00:25 +0000344}
345
Evan Chengdb8d56b2008-06-30 20:45:06 +0000346/// InstructionSelect - This callback is invoked by
Scott Michel266bc8f2007-12-04 22:23:35 +0000347/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
348void
Dan Gohmanf350b272008-08-23 02:25:05 +0000349SPUDAGToDAGISel::InstructionSelect()
Scott Michel266bc8f2007-12-04 22:23:35 +0000350{
351 DEBUG(BB->dump());
352
353 // Select target instructions for the DAG.
David Greene8ad4c002008-10-27 21:56:29 +0000354 SelectRoot(*CurDAG);
Dan Gohmanf350b272008-08-23 02:25:05 +0000355 CurDAG->RemoveDeadNodes();
Scott Michel266bc8f2007-12-04 22:23:35 +0000356}
357
Scott Michel266bc8f2007-12-04 22:23:35 +0000358/*!
359 \arg Op The ISD instructio operand
360 \arg N The address to be tested
361 \arg Base The base address
362 \arg Index The base address index
363 */
364bool
Dan Gohman475871a2008-07-27 21:46:04 +0000365SPUDAGToDAGISel::SelectAFormAddr(SDValue Op, SDValue N, SDValue &Base,
366 SDValue &Index) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000367 // These match the addr256k operand type:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000368 MVT OffsVT = MVT::i16;
Dan Gohman475871a2008-07-27 21:46:04 +0000369 SDValue Zero = CurDAG->getTargetConstant(0, OffsVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000370
371 switch (N.getOpcode()) {
372 case ISD::Constant:
Scott Michel9de5d0d2008-01-11 02:53:15 +0000373 case ISD::ConstantPool:
374 case ISD::GlobalAddress:
375 cerr << "SPU SelectAFormAddr: Constant/Pool/Global not lowered.\n";
376 abort();
377 /*NOTREACHED*/
378
Scott Michel053c1da2008-01-29 02:16:57 +0000379 case ISD::TargetConstant:
Scott Michel9de5d0d2008-01-11 02:53:15 +0000380 case ISD::TargetGlobalAddress:
Scott Michel053c1da2008-01-29 02:16:57 +0000381 case ISD::TargetJumpTable:
382 cerr << "SPUSelectAFormAddr: Target Constant/Pool/Global not wrapped as "
383 << "A-form address.\n";
384 abort();
385 /*NOTREACHED*/
Scott Michel266bc8f2007-12-04 22:23:35 +0000386
Scott Michel02d711b2008-12-30 23:28:25 +0000387 case SPUISD::AFormAddr:
Scott Michel053c1da2008-01-29 02:16:57 +0000388 // Just load from memory if there's only a single use of the location,
389 // otherwise, this will get handled below with D-form offset addresses
390 if (N.hasOneUse()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000391 SDValue Op0 = N.getOperand(0);
Scott Michel053c1da2008-01-29 02:16:57 +0000392 switch (Op0.getOpcode()) {
393 case ISD::TargetConstantPool:
394 case ISD::TargetJumpTable:
395 Base = Op0;
396 Index = Zero;
397 return true;
398
399 case ISD::TargetGlobalAddress: {
400 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op0);
401 GlobalValue *GV = GSDN->getGlobal();
402 if (GV->getAlignment() == 16) {
403 Base = Op0;
404 Index = Zero;
405 return true;
406 }
407 break;
408 }
409 }
410 }
411 break;
412 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000413 return false;
414}
415
Scott Michel02d711b2008-12-30 23:28:25 +0000416bool
Dan Gohman475871a2008-07-27 21:46:04 +0000417SPUDAGToDAGISel::SelectDForm2Addr(SDValue Op, SDValue N, SDValue &Disp,
418 SDValue &Base) {
Scott Michel203b2d62008-04-30 00:30:08 +0000419 const int minDForm2Offset = -(1 << 7);
420 const int maxDForm2Offset = (1 << 7) - 1;
421 return DFormAddressPredicate(Op, N, Disp, Base, minDForm2Offset,
422 maxDForm2Offset);
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000423}
424
Scott Michel266bc8f2007-12-04 22:23:35 +0000425/*!
426 \arg Op The ISD instruction (ignored)
427 \arg N The address to be tested
428 \arg Base Base address register/pointer
429 \arg Index Base address index
430
431 Examine the input address by a base register plus a signed 10-bit
432 displacement, [r+I10] (D-form address).
433
434 \return true if \a N is a D-form address with \a Base and \a Index set
Dan Gohman475871a2008-07-27 21:46:04 +0000435 to non-empty SDValue instances.
Scott Michel266bc8f2007-12-04 22:23:35 +0000436*/
437bool
Dan Gohman475871a2008-07-27 21:46:04 +0000438SPUDAGToDAGISel::SelectDFormAddr(SDValue Op, SDValue N, SDValue &Base,
439 SDValue &Index) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000440 return DFormAddressPredicate(Op, N, Base, Index,
Scott Michel9c0c6b22008-11-21 02:56:16 +0000441 SPUFrameInfo::minFrameOffset(),
442 SPUFrameInfo::maxFrameOffset());
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000443}
444
445bool
Dan Gohman475871a2008-07-27 21:46:04 +0000446SPUDAGToDAGISel::DFormAddressPredicate(SDValue Op, SDValue N, SDValue &Base,
447 SDValue &Index, int minOffset,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000448 int maxOffset) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000449 unsigned Opc = N.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000450 MVT PtrTy = SPUtli.getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +0000451
Scott Michel053c1da2008-01-29 02:16:57 +0000452 if (Opc == ISD::FrameIndex) {
453 // Stack frame index must be less than 512 (divided by 16):
Scott Michel203b2d62008-04-30 00:30:08 +0000454 FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N);
455 int FI = int(FIN->getIndex());
Scott Michel266bc8f2007-12-04 22:23:35 +0000456 DEBUG(cerr << "SelectDFormAddr: ISD::FrameIndex = "
Scott Michel203b2d62008-04-30 00:30:08 +0000457 << FI << "\n");
458 if (SPUFrameInfo::FItoStackOffset(FI) < maxOffset) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000459 Base = CurDAG->getTargetConstant(0, PtrTy);
Scott Michel203b2d62008-04-30 00:30:08 +0000460 Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
Scott Michel266bc8f2007-12-04 22:23:35 +0000461 return true;
462 }
463 } else if (Opc == ISD::ADD) {
464 // Generated by getelementptr
Dan Gohman475871a2008-07-27 21:46:04 +0000465 const SDValue Op0 = N.getOperand(0);
466 const SDValue Op1 = N.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000467
Scott Michel053c1da2008-01-29 02:16:57 +0000468 if ((Op0.getOpcode() == SPUISD::Hi && Op1.getOpcode() == SPUISD::Lo)
469 || (Op1.getOpcode() == SPUISD::Hi && Op0.getOpcode() == SPUISD::Lo)) {
470 Base = CurDAG->getTargetConstant(0, PtrTy);
471 Index = N;
472 return true;
473 } else if (Op1.getOpcode() == ISD::Constant
474 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000475 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1);
Dan Gohman7810bfe2008-09-26 21:54:37 +0000476 int32_t offset = int32_t(CN->getSExtValue());
Scott Michel9de5d0d2008-01-11 02:53:15 +0000477
Scott Michel053c1da2008-01-29 02:16:57 +0000478 if (Op0.getOpcode() == ISD::FrameIndex) {
Scott Michel203b2d62008-04-30 00:30:08 +0000479 FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Op0);
480 int FI = int(FIN->getIndex());
Scott Michel9de5d0d2008-01-11 02:53:15 +0000481 DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset
Scott Michel203b2d62008-04-30 00:30:08 +0000482 << " frame index = " << FI << "\n");
Scott Michel9de5d0d2008-01-11 02:53:15 +0000483
Scott Michel203b2d62008-04-30 00:30:08 +0000484 if (SPUFrameInfo::FItoStackOffset(FI) < maxOffset) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000485 Base = CurDAG->getTargetConstant(offset, PtrTy);
Scott Michel203b2d62008-04-30 00:30:08 +0000486 Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000487 return true;
488 }
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000489 } else if (offset > minOffset && offset < maxOffset) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000490 Base = CurDAG->getTargetConstant(offset, PtrTy);
Scott Michel053c1da2008-01-29 02:16:57 +0000491 Index = Op0;
492 return true;
493 }
494 } else if (Op0.getOpcode() == ISD::Constant
495 || Op0.getOpcode() == ISD::TargetConstant) {
496 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op0);
Dan Gohman7810bfe2008-09-26 21:54:37 +0000497 int32_t offset = int32_t(CN->getSExtValue());
Scott Michel053c1da2008-01-29 02:16:57 +0000498
499 if (Op1.getOpcode() == ISD::FrameIndex) {
Scott Michel203b2d62008-04-30 00:30:08 +0000500 FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Op1);
501 int FI = int(FIN->getIndex());
Scott Michel053c1da2008-01-29 02:16:57 +0000502 DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset
Scott Michel203b2d62008-04-30 00:30:08 +0000503 << " frame index = " << FI << "\n");
Scott Michel053c1da2008-01-29 02:16:57 +0000504
Scott Michel203b2d62008-04-30 00:30:08 +0000505 if (SPUFrameInfo::FItoStackOffset(FI) < maxOffset) {
Scott Michel053c1da2008-01-29 02:16:57 +0000506 Base = CurDAG->getTargetConstant(offset, PtrTy);
Scott Michel203b2d62008-04-30 00:30:08 +0000507 Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000508 return true;
509 }
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000510 } else if (offset > minOffset && offset < maxOffset) {
Scott Michel053c1da2008-01-29 02:16:57 +0000511 Base = CurDAG->getTargetConstant(offset, PtrTy);
512 Index = Op1;
513 return true;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000514 }
Scott Michel053c1da2008-01-29 02:16:57 +0000515 }
516 } else if (Opc == SPUISD::IndirectAddr) {
517 // Indirect with constant offset -> D-Form address
Dan Gohman475871a2008-07-27 21:46:04 +0000518 const SDValue Op0 = N.getOperand(0);
519 const SDValue Op1 = N.getOperand(1);
Scott Michel497e8882008-01-11 21:01:19 +0000520
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000521 if (Op0.getOpcode() == SPUISD::Hi
522 && Op1.getOpcode() == SPUISD::Lo) {
Scott Michel053c1da2008-01-29 02:16:57 +0000523 // (SPUindirect (SPUhi <arg>, 0), (SPUlo <arg>, 0))
Scott Michel9de5d0d2008-01-11 02:53:15 +0000524 Base = CurDAG->getTargetConstant(0, PtrTy);
Scott Michel053c1da2008-01-29 02:16:57 +0000525 Index = N;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000526 return true;
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000527 } else if (isa<ConstantSDNode>(Op0) || isa<ConstantSDNode>(Op1)) {
528 int32_t offset = 0;
Dan Gohman475871a2008-07-27 21:46:04 +0000529 SDValue idxOp;
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000530
531 if (isa<ConstantSDNode>(Op1)) {
532 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
Dan Gohman7810bfe2008-09-26 21:54:37 +0000533 offset = int32_t(CN->getSExtValue());
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000534 idxOp = Op0;
535 } else if (isa<ConstantSDNode>(Op0)) {
536 ConstantSDNode *CN = cast<ConstantSDNode>(Op0);
Dan Gohman7810bfe2008-09-26 21:54:37 +0000537 offset = int32_t(CN->getSExtValue());
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000538 idxOp = Op1;
Scott Michel02d711b2008-12-30 23:28:25 +0000539 }
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000540
541 if (offset >= minOffset && offset <= maxOffset) {
542 Base = CurDAG->getTargetConstant(offset, PtrTy);
543 Index = idxOp;
544 return true;
545 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000546 }
Scott Michel053c1da2008-01-29 02:16:57 +0000547 } else if (Opc == SPUISD::AFormAddr) {
548 Base = CurDAG->getTargetConstant(0, N.getValueType());
549 Index = N;
Scott Michel58c58182008-01-17 20:38:41 +0000550 return true;
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000551 } else if (Opc == SPUISD::LDRESULT) {
552 Base = CurDAG->getTargetConstant(0, N.getValueType());
553 Index = N;
554 return true;
Scott Michel9c0c6b22008-11-21 02:56:16 +0000555 } else if (Opc == ISD::Register || Opc == ISD::CopyFromReg) {
556 unsigned OpOpc = Op.getOpcode();
557
558 if (OpOpc == ISD::STORE || OpOpc == ISD::LOAD) {
559 // Direct load/store without getelementptr
560 SDValue Addr, Offs;
561
562 // Get the register from CopyFromReg
563 if (Opc == ISD::CopyFromReg)
564 Addr = N.getOperand(1);
565 else
566 Addr = N; // Register
567
Scott Michelaedc6372008-12-10 00:15:19 +0000568 Offs = ((OpOpc == ISD::STORE) ? Op.getOperand(3) : Op.getOperand(2));
Scott Michel9c0c6b22008-11-21 02:56:16 +0000569
570 if (Offs.getOpcode() == ISD::Constant || Offs.getOpcode() == ISD::UNDEF) {
571 if (Offs.getOpcode() == ISD::UNDEF)
572 Offs = CurDAG->getTargetConstant(0, Offs.getValueType());
573
574 Base = Offs;
575 Index = Addr;
576 return true;
577 }
Scott Michelaedc6372008-12-10 00:15:19 +0000578 } else {
579 /* If otherwise unadorned, default to D-form address with 0 offset: */
580 if (Opc == ISD::CopyFromReg) {
581 Index = N.getOperand(1);
582 } else {
583 Index = N;
584 }
585
586 Base = CurDAG->getTargetConstant(0, Index.getValueType());
587 return true;
Scott Michel9c0c6b22008-11-21 02:56:16 +0000588 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000589 }
Scott Michel9c0c6b22008-11-21 02:56:16 +0000590
Scott Michel266bc8f2007-12-04 22:23:35 +0000591 return false;
592}
593
594/*!
595 \arg Op The ISD instruction operand
596 \arg N The address operand
597 \arg Base The base pointer operand
598 \arg Index The offset/index operand
599
Scott Michel9c0c6b22008-11-21 02:56:16 +0000600 If the address \a N can be expressed as an A-form or D-form address, returns
601 false. Otherwise, creates two operands, Base and Index that will become the
602 (r)(r) X-form address.
Scott Michel266bc8f2007-12-04 22:23:35 +0000603*/
604bool
Dan Gohman475871a2008-07-27 21:46:04 +0000605SPUDAGToDAGISel::SelectXFormAddr(SDValue Op, SDValue N, SDValue &Base,
606 SDValue &Index) {
Scott Michel9c0c6b22008-11-21 02:56:16 +0000607 if (!SelectAFormAddr(Op, N, Base, Index)
608 && !SelectDFormAddr(Op, N, Base, Index)) {
Scott Michel18fae692008-11-25 17:29:43 +0000609 // If the address is neither A-form or D-form, punt and use an X-form
610 // address:
Scott Michel1a6cdb62008-12-01 17:56:02 +0000611 Base = N.getOperand(1);
612 Index = N.getOperand(0);
Scott Michel50843c02008-11-25 04:03:47 +0000613 return true;
Scott Michel9c0c6b22008-11-21 02:56:16 +0000614 }
615
616 return false;
Scott Michel58c58182008-01-17 20:38:41 +0000617}
618
Scott Michel266bc8f2007-12-04 22:23:35 +0000619//! Convert the operand from a target-independent to a target-specific node
620/*!
621 */
622SDNode *
Dan Gohman475871a2008-07-27 21:46:04 +0000623SPUDAGToDAGISel::Select(SDValue Op) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000624 SDNode *N = Op.getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +0000625 unsigned Opc = N->getOpcode();
Scott Michel58c58182008-01-17 20:38:41 +0000626 int n_ops = -1;
627 unsigned NewOpc;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000628 MVT OpVT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +0000629 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000630
Dan Gohmane8be6c62008-07-17 19:10:17 +0000631 if (N->isMachineOpcode()) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000632 return NULL; // Already selected.
633 } else if (Opc == ISD::FrameIndex) {
Scott Michel02d711b2008-12-30 23:28:25 +0000634 int FI = cast<FrameIndexSDNode>(N)->getIndex();
635 SDValue TFI = CurDAG->getTargetFrameIndex(FI, Op.getValueType());
636 SDValue Imm0 = CurDAG->getTargetConstant(0, Op.getValueType());
Scott Michel266bc8f2007-12-04 22:23:35 +0000637
Scott Michel02d711b2008-12-30 23:28:25 +0000638 if (FI < 128) {
Scott Michel203b2d62008-04-30 00:30:08 +0000639 NewOpc = SPU::AIr32;
Scott Michel02d711b2008-12-30 23:28:25 +0000640 Ops[0] = TFI;
641 Ops[1] = Imm0;
Scott Michel203b2d62008-04-30 00:30:08 +0000642 n_ops = 2;
643 } else {
Scott Michel203b2d62008-04-30 00:30:08 +0000644 NewOpc = SPU::Ar32;
Scott Michel02d711b2008-12-30 23:28:25 +0000645 Ops[0] = CurDAG->getRegister(SPU::R1, Op.getValueType());
646 Ops[1] = SDValue(CurDAG->getTargetNode(SPU::ILAr32, Op.getValueType(),
647 TFI, Imm0), 0);
Scott Michel203b2d62008-04-30 00:30:08 +0000648 n_ops = 2;
Scott Michel203b2d62008-04-30 00:30:08 +0000649 }
Scott Michel58c58182008-01-17 20:38:41 +0000650 } else if (Opc == ISD::ZERO_EXTEND) {
651 // (zero_extend:i16 (and:i8 <arg>, <const>))
Dan Gohman475871a2008-07-27 21:46:04 +0000652 const SDValue &Op1 = N->getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000653
654 if (Op.getValueType() == MVT::i16 && Op1.getValueType() == MVT::i8) {
655 if (Op1.getOpcode() == ISD::AND) {
656 // Fold this into a single ANDHI. This is often seen in expansions of i1
657 // to i8, then i8 to i16 in logical/branching operations.
658 DEBUG(cerr << "CellSPU: Coalescing (zero_extend:i16 (and:i8 "
659 "<arg>, <const>))\n");
Scott Michela59d4692008-02-23 18:41:37 +0000660 NewOpc = SPU::ANDHIi8i16;
Scott Michel58c58182008-01-17 20:38:41 +0000661 Ops[0] = Op1.getOperand(0);
662 Ops[1] = Op1.getOperand(1);
663 n_ops = 2;
664 }
665 }
Scott Michel02d711b2008-12-30 23:28:25 +0000666 } else if (Opc == ISD::SHL) {
667 if (OpVT == MVT::i64) {
668 return SelectSHLi64(Op, OpVT);
669 }
670 } else if (Opc == ISD::SRL) {
671 if (OpVT == MVT::i64) {
672 return SelectSRLi64(Op, OpVT);
673 }
674 } else if (Opc == ISD::SRA) {
675 if (OpVT == MVT::i64) {
676 return SelectSRAi64(Op, OpVT);
677 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000678 } else if (Opc == SPUISD::LDRESULT) {
679 // Custom select instructions for LDRESULT
Duncan Sands83ec4b62008-06-06 12:08:01 +0000680 MVT VT = N->getValueType(0);
Dan Gohman475871a2008-07-27 21:46:04 +0000681 SDValue Arg = N->getOperand(0);
682 SDValue Chain = N->getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000683 SDNode *Result;
Scott Michela59d4692008-02-23 18:41:37 +0000684 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
685
686 if (vtm->ldresult_ins == 0) {
687 cerr << "LDRESULT for unsupported type: "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000688 << VT.getMVTString()
Scott Michela59d4692008-02-23 18:41:37 +0000689 << "\n";
690 abort();
691 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000692
Scott Michela59d4692008-02-23 18:41:37 +0000693 Opc = vtm->ldresult_ins;
694 if (vtm->ldresult_imm) {
Dan Gohman475871a2008-07-27 21:46:04 +0000695 SDValue Zero = CurDAG->getTargetConstant(0, VT);
Scott Michel86c041f2007-12-20 00:44:13 +0000696
Scott Michel58c58182008-01-17 20:38:41 +0000697 Result = CurDAG->getTargetNode(Opc, VT, MVT::Other, Arg, Zero, Chain);
Scott Michel86c041f2007-12-20 00:44:13 +0000698 } else {
Scott Michel30ee7df2008-12-04 03:02:42 +0000699 Result = CurDAG->getTargetNode(Opc, VT, MVT::Other, Arg, Arg, Chain);
Scott Michel86c041f2007-12-20 00:44:13 +0000700 }
701
Scott Michel266bc8f2007-12-04 22:23:35 +0000702 return Result;
Scott Michel053c1da2008-01-29 02:16:57 +0000703 } else if (Opc == SPUISD::IndirectAddr) {
Scott Michelf0569be2008-12-27 04:51:36 +0000704 // Look at the operands: SelectCode() will catch the cases that aren't
705 // specifically handled here.
706 //
707 // SPUInstrInfo catches the following patterns:
708 // (SPUindirect (SPUhi ...), (SPUlo ...))
709 // (SPUindirect $sp, imm)
710 MVT VT = Op.getValueType();
711 SDValue Op0 = N->getOperand(0);
712 SDValue Op1 = N->getOperand(1);
713 RegisterSDNode *RN;
Scott Michel58c58182008-01-17 20:38:41 +0000714
Scott Michelf0569be2008-12-27 04:51:36 +0000715 if ((Op0.getOpcode() != SPUISD::Hi && Op1.getOpcode() != SPUISD::Lo)
716 || (Op0.getOpcode() == ISD::Register
717 && ((RN = dyn_cast<RegisterSDNode>(Op0.getNode())) != 0
718 && RN->getReg() != SPU::R1))) {
719 NewOpc = SPU::Ar32;
Scott Michel58c58182008-01-17 20:38:41 +0000720 if (Op1.getOpcode() == ISD::Constant) {
721 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
Scott Michelf0569be2008-12-27 04:51:36 +0000722 Op1 = CurDAG->getTargetConstant(CN->getSExtValue(), VT);
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000723 NewOpc = (isI32IntS10Immediate(CN) ? SPU::AIr32 : SPU::Ar32);
Scott Michel58c58182008-01-17 20:38:41 +0000724 }
Scott Michelf0569be2008-12-27 04:51:36 +0000725 Ops[0] = Op0;
726 Ops[1] = Op1;
727 n_ops = 2;
Scott Michel58c58182008-01-17 20:38:41 +0000728 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000729 }
Scott Michel02d711b2008-12-30 23:28:25 +0000730
Scott Michel58c58182008-01-17 20:38:41 +0000731 if (n_ops > 0) {
732 if (N->hasOneUse())
733 return CurDAG->SelectNodeTo(N, NewOpc, OpVT, Ops, n_ops);
734 else
735 return CurDAG->getTargetNode(NewOpc, OpVT, Ops, n_ops);
736 } else
737 return SelectCode(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +0000738}
739
Scott Michel02d711b2008-12-30 23:28:25 +0000740/*!
741 * Emit the instruction sequence for i64 left shifts. The basic algorithm
742 * is to fill the bottom two word slots with zeros so that zeros are shifted
743 * in as the entire quadword is shifted left.
744 *
745 * \note This code could also be used to implement v2i64 shl.
746 *
747 * @param Op The shl operand
748 * @param OpVT Op's machine value value type (doesn't need to be passed, but
749 * makes life easier.)
750 * @return The SDNode with the entire instruction sequence
751 */
752SDNode *
753SPUDAGToDAGISel::SelectSHLi64(SDValue &Op, MVT OpVT) {
754 SDValue Op0 = Op.getOperand(0);
755 MVT VecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
756 SDValue ShiftAmt = Op.getOperand(1);
757 MVT ShiftAmtVT = ShiftAmt.getValueType();
758 SDNode *VecOp0, *SelMask, *ZeroFill, *Shift = 0;
759 SDValue SelMaskVal;
760
761 VecOp0 = CurDAG->getTargetNode(SPU::ORv2i64_i64, VecVT, Op0);
762 SelMaskVal = CurDAG->getTargetConstant(0xff00ULL, MVT::i16);
763 SelMask = CurDAG->getTargetNode(SPU::FSMBIv2i64, VecVT, SelMaskVal);
764 ZeroFill = CurDAG->getTargetNode(SPU::ILv2i64, VecVT,
765 CurDAG->getTargetConstant(0, OpVT));
766 VecOp0 = CurDAG->getTargetNode(SPU::SELBv2i64, VecVT,
767 SDValue(ZeroFill, 0),
768 SDValue(VecOp0, 0),
769 SDValue(SelMask, 0));
770
771 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(ShiftAmt)) {
772 unsigned bytes = unsigned(CN->getZExtValue()) >> 3;
773 unsigned bits = unsigned(CN->getZExtValue()) & 7;
774
775 if (bytes > 0) {
776 Shift =
777 CurDAG->getTargetNode(SPU::SHLQBYIv2i64, VecVT,
778 SDValue(VecOp0, 0),
779 CurDAG->getTargetConstant(bytes, ShiftAmtVT));
780 }
781
782 if (bits > 0) {
783 Shift =
784 CurDAG->getTargetNode(SPU::SHLQBIIv2i64, VecVT,
785 SDValue((Shift != 0 ? Shift : VecOp0), 0),
786 CurDAG->getTargetConstant(bits, ShiftAmtVT));
787 }
788 } else {
789 SDNode *Bytes =
790 CurDAG->getTargetNode(SPU::ROTMIr32, ShiftAmtVT,
791 ShiftAmt,
792 CurDAG->getTargetConstant(3, ShiftAmtVT));
793 SDNode *Bits =
794 CurDAG->getTargetNode(SPU::ANDIr32, ShiftAmtVT,
795 ShiftAmt,
796 CurDAG->getTargetConstant(7, ShiftAmtVT));
797 Shift =
798 CurDAG->getTargetNode(SPU::SHLQBYv2i64, VecVT,
799 SDValue(VecOp0, 0), SDValue(Bytes, 0));
800 Shift =
801 CurDAG->getTargetNode(SPU::SHLQBIv2i64, VecVT,
802 SDValue(Shift, 0), SDValue(Bits, 0));
803 }
804
805 return CurDAG->getTargetNode(SPU::ORi64_v2i64, OpVT, SDValue(Shift, 0));
806}
807
808/*!
809 * Emit the instruction sequence for i64 logical right shifts.
810 *
811 * @param Op The shl operand
812 * @param OpVT Op's machine value value type (doesn't need to be passed, but
813 * makes life easier.)
814 * @return The SDNode with the entire instruction sequence
815 */
816SDNode *
817SPUDAGToDAGISel::SelectSRLi64(SDValue &Op, MVT OpVT) {
818 SDValue Op0 = Op.getOperand(0);
819 MVT VecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
820 SDValue ShiftAmt = Op.getOperand(1);
821 MVT ShiftAmtVT = ShiftAmt.getValueType();
822 SDNode *VecOp0, *Shift = 0;
823
824 VecOp0 = CurDAG->getTargetNode(SPU::ORv2i64_i64, VecVT, Op0);
825
826 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(ShiftAmt)) {
827 unsigned bytes = unsigned(CN->getZExtValue()) >> 3;
828 unsigned bits = unsigned(CN->getZExtValue()) & 7;
829
830 if (bytes > 0) {
831 Shift =
832 CurDAG->getTargetNode(SPU::ROTQMBYIv2i64, VecVT,
833 SDValue(VecOp0, 0),
834 CurDAG->getTargetConstant(bytes, ShiftAmtVT));
835 }
836
837 if (bits > 0) {
838 Shift =
839 CurDAG->getTargetNode(SPU::ROTQMBIIv2i64, VecVT,
840 SDValue((Shift != 0 ? Shift : VecOp0), 0),
841 CurDAG->getTargetConstant(bits, ShiftAmtVT));
842 }
843 } else {
844 SDNode *Bytes =
845 CurDAG->getTargetNode(SPU::ROTMIr32, ShiftAmtVT,
846 ShiftAmt,
847 CurDAG->getTargetConstant(3, ShiftAmtVT));
848 SDNode *Bits =
849 CurDAG->getTargetNode(SPU::ANDIr32, ShiftAmtVT,
850 ShiftAmt,
851 CurDAG->getTargetConstant(7, ShiftAmtVT));
852
853 // Ensure that the shift amounts are negated!
854 Bytes = CurDAG->getTargetNode(SPU::SFIr32, ShiftAmtVT,
855 SDValue(Bytes, 0),
856 CurDAG->getTargetConstant(0, ShiftAmtVT));
857
858 Bits = CurDAG->getTargetNode(SPU::SFIr32, ShiftAmtVT,
859 SDValue(Bits, 0),
860 CurDAG->getTargetConstant(0, ShiftAmtVT));
861
862 Shift =
863 CurDAG->getTargetNode(SPU::ROTQMBYv2i64, VecVT,
864 SDValue(VecOp0, 0), SDValue(Bytes, 0));
865 Shift =
866 CurDAG->getTargetNode(SPU::ROTQMBIv2i64, VecVT,
867 SDValue(Shift, 0), SDValue(Bits, 0));
868 }
869
870 return CurDAG->getTargetNode(SPU::ORi64_v2i64, OpVT, SDValue(Shift, 0));
871}
872
873/*!
874 * Emit the instruction sequence for i64 arithmetic right shifts.
875 *
876 * @param Op The shl operand
877 * @param OpVT Op's machine value value type (doesn't need to be passed, but
878 * makes life easier.)
879 * @return The SDNode with the entire instruction sequence
880 */
881SDNode *
882SPUDAGToDAGISel::SelectSRAi64(SDValue &Op, MVT OpVT) {
883 // Promote Op0 to vector
884 MVT VecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
885 SDValue ShiftAmt = Op.getOperand(1);
886 MVT ShiftAmtVT = ShiftAmt.getValueType();
887
888 SDNode *VecOp0 =
889 CurDAG->getTargetNode(SPU::ORv2i64_i64, VecVT, Op.getOperand(0));
890
891 SDValue SignRotAmt = CurDAG->getTargetConstant(31, ShiftAmtVT);
892 SDNode *SignRot =
893 CurDAG->getTargetNode(SPU::ROTMAIv2i64_i32, MVT::v2i64,
894 SDValue(VecOp0, 0), SignRotAmt);
895 SDNode *UpperHalfSign =
896 CurDAG->getTargetNode(SPU::ORi32_v4i32, MVT::i32, SDValue(SignRot, 0));
897
898 SDNode *UpperHalfSignMask =
899 CurDAG->getTargetNode(SPU::FSM64r32, VecVT, SDValue(UpperHalfSign, 0));
900 SDNode *UpperLowerMask =
901 CurDAG->getTargetNode(SPU::FSMBIv2i64, VecVT,
902 CurDAG->getTargetConstant(0xff00ULL, MVT::i16));
903 SDNode *UpperLowerSelect =
904 CurDAG->getTargetNode(SPU::SELBv2i64, VecVT,
905 SDValue(UpperHalfSignMask, 0),
906 SDValue(VecOp0, 0),
907 SDValue(UpperLowerMask, 0));
908
909 SDNode *Shift = 0;
910
911 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(ShiftAmt)) {
912 unsigned bytes = unsigned(CN->getZExtValue()) >> 3;
913 unsigned bits = unsigned(CN->getZExtValue()) & 7;
914
915 if (bytes > 0) {
916 bytes = 31 - bytes;
917 Shift =
918 CurDAG->getTargetNode(SPU::ROTQBYIv2i64, VecVT,
919 SDValue(UpperLowerSelect, 0),
920 CurDAG->getTargetConstant(bytes, ShiftAmtVT));
921 }
922
923 if (bits > 0) {
924 bits = 8 - bits;
925 Shift =
926 CurDAG->getTargetNode(SPU::ROTQBIIv2i64, VecVT,
927 SDValue((Shift != 0 ? Shift : UpperLowerSelect), 0),
928 CurDAG->getTargetConstant(bits, ShiftAmtVT));
929 }
930 } else {
931 SDNode *NegShift =
932 CurDAG->getTargetNode(SPU::SFIr32, ShiftAmtVT,
933 ShiftAmt, CurDAG->getTargetConstant(0, ShiftAmtVT));
934
935 Shift =
936 CurDAG->getTargetNode(SPU::ROTQBYBIv2i64_r32, VecVT,
937 SDValue(UpperLowerSelect, 0), SDValue(NegShift, 0));
938 Shift =
939 CurDAG->getTargetNode(SPU::ROTQBIv2i64, VecVT,
940 SDValue(Shift, 0), SDValue(NegShift, 0));
941 }
942
943 return CurDAG->getTargetNode(SPU::ORi64_v2i64, OpVT, SDValue(Shift, 0));
944}
945
946/// createSPUISelDag - This pass converts a legalized DAG into a
Scott Michel266bc8f2007-12-04 22:23:35 +0000947/// SPU-specific DAG, ready for instruction scheduling.
948///
949FunctionPass *llvm::createSPUISelDag(SPUTargetMachine &TM) {
950 return new SPUDAGToDAGISel(TM);
951}