blob: f51aba2fda655281fef0e2867bd0dbfe9f19da39 [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
Dan Gohman475871a2008-07-27 21:46:04 +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 {}
232
233 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 }
239
240 /// 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 }
251
252 /// 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 Michel266bc8f2007-12-04 22:23:35 +0000261 //! Returns true if the address N is an A-form (local store) address
Dan Gohman475871a2008-07-27 21:46:04 +0000262 bool SelectAFormAddr(SDValue Op, SDValue N, SDValue &Base,
263 SDValue &Index);
Scott Michel266bc8f2007-12-04 22:23:35 +0000264
265 //! D-form address predicate
Dan Gohman475871a2008-07-27 21:46:04 +0000266 bool SelectDFormAddr(SDValue Op, SDValue N, SDValue &Base,
267 SDValue &Index);
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000268
269 /// Alternate D-form address using i7 offset predicate
Dan Gohman475871a2008-07-27 21:46:04 +0000270 bool SelectDForm2Addr(SDValue Op, SDValue N, SDValue &Disp,
271 SDValue &Base);
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000272
273 /// D-form address selection workhorse
Dan Gohman475871a2008-07-27 21:46:04 +0000274 bool DFormAddressPredicate(SDValue Op, SDValue N, SDValue &Disp,
275 SDValue &Base, int minOffset, int maxOffset);
Scott Michel266bc8f2007-12-04 22:23:35 +0000276
277 //! Address predicate if N can be expressed as an indexed [r+r] operation.
Dan Gohman475871a2008-07-27 21:46:04 +0000278 bool SelectXFormAddr(SDValue Op, SDValue N, SDValue &Base,
279 SDValue &Index);
Scott Michel266bc8f2007-12-04 22:23:35 +0000280
281 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
282 /// inline asm expressions.
Dan Gohman475871a2008-07-27 21:46:04 +0000283 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000284 char ConstraintCode,
Dan Gohmanf350b272008-08-23 02:25:05 +0000285 std::vector<SDValue> &OutOps) {
Dan Gohman475871a2008-07-27 21:46:04 +0000286 SDValue Op0, Op1;
Scott Michel266bc8f2007-12-04 22:23:35 +0000287 switch (ConstraintCode) {
288 default: return true;
289 case 'm': // memory
290 if (!SelectDFormAddr(Op, Op, Op0, Op1)
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000291 && !SelectAFormAddr(Op, Op, Op0, Op1))
292 SelectXFormAddr(Op, Op, Op0, Op1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000293 break;
294 case 'o': // offsetable
295 if (!SelectDFormAddr(Op, Op, Op0, Op1)
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000296 && !SelectAFormAddr(Op, Op, Op0, Op1)) {
297 Op0 = Op;
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000298 Op1 = getSmallIPtrImm(0);
Scott Michel266bc8f2007-12-04 22:23:35 +0000299 }
300 break;
301 case 'v': // not offsetable
302#if 1
303 assert(0 && "InlineAsmMemoryOperand 'v' constraint not handled.");
304#else
305 SelectAddrIdxOnly(Op, Op, Op0, Op1);
306#endif
307 break;
308 }
309
310 OutOps.push_back(Op0);
311 OutOps.push_back(Op1);
312 return false;
313 }
314
Evan Chengdb8d56b2008-06-30 20:45:06 +0000315 /// InstructionSelect - This callback is invoked by
Scott Michel266bc8f2007-12-04 22:23:35 +0000316 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
Dan Gohmanf350b272008-08-23 02:25:05 +0000317 virtual void InstructionSelect();
Scott Michel266bc8f2007-12-04 22:23:35 +0000318
319 virtual const char *getPassName() const {
320 return "Cell SPU DAG->DAG Pattern Instruction Selection";
321 }
322
323 /// CreateTargetHazardRecognizer - Return the hazard recognizer to use for
324 /// this target when scheduling the DAG.
325 virtual HazardRecognizer *CreateTargetHazardRecognizer() {
Dan Gohman6448d912008-09-04 15:39:15 +0000326 const TargetInstrInfo *II = TM.getInstrInfo();
Scott Michel266bc8f2007-12-04 22:23:35 +0000327 assert(II && "No InstrInfo?");
328 return new SPUHazardRecognizer(*II);
329 }
330
331 // Include the pieces autogenerated from the target description.
332#include "SPUGenDAGISel.inc"
333};
334
Dan Gohman844731a2008-05-13 00:00:25 +0000335}
336
Evan Chengdb8d56b2008-06-30 20:45:06 +0000337/// InstructionSelect - This callback is invoked by
Scott Michel266bc8f2007-12-04 22:23:35 +0000338/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
339void
Dan Gohmanf350b272008-08-23 02:25:05 +0000340SPUDAGToDAGISel::InstructionSelect()
Scott Michel266bc8f2007-12-04 22:23:35 +0000341{
342 DEBUG(BB->dump());
343
344 // Select target instructions for the DAG.
David Greene8ad4c002008-10-27 21:56:29 +0000345 SelectRoot(*CurDAG);
Dan Gohmanf350b272008-08-23 02:25:05 +0000346 CurDAG->RemoveDeadNodes();
Scott Michel266bc8f2007-12-04 22:23:35 +0000347}
348
Scott Michel266bc8f2007-12-04 22:23:35 +0000349/*!
350 \arg Op The ISD instructio operand
351 \arg N The address to be tested
352 \arg Base The base address
353 \arg Index The base address index
354 */
355bool
Dan Gohman475871a2008-07-27 21:46:04 +0000356SPUDAGToDAGISel::SelectAFormAddr(SDValue Op, SDValue N, SDValue &Base,
357 SDValue &Index) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000358 // These match the addr256k operand type:
Duncan Sands83ec4b62008-06-06 12:08:01 +0000359 MVT OffsVT = MVT::i16;
Dan Gohman475871a2008-07-27 21:46:04 +0000360 SDValue Zero = CurDAG->getTargetConstant(0, OffsVT);
Scott Michel266bc8f2007-12-04 22:23:35 +0000361
362 switch (N.getOpcode()) {
363 case ISD::Constant:
Scott Michel9de5d0d2008-01-11 02:53:15 +0000364 case ISD::ConstantPool:
365 case ISD::GlobalAddress:
366 cerr << "SPU SelectAFormAddr: Constant/Pool/Global not lowered.\n";
367 abort();
368 /*NOTREACHED*/
369
Scott Michel053c1da2008-01-29 02:16:57 +0000370 case ISD::TargetConstant:
Scott Michel9de5d0d2008-01-11 02:53:15 +0000371 case ISD::TargetGlobalAddress:
Scott Michel053c1da2008-01-29 02:16:57 +0000372 case ISD::TargetJumpTable:
373 cerr << "SPUSelectAFormAddr: Target Constant/Pool/Global not wrapped as "
374 << "A-form address.\n";
375 abort();
376 /*NOTREACHED*/
Scott Michel266bc8f2007-12-04 22:23:35 +0000377
Scott Michel053c1da2008-01-29 02:16:57 +0000378 case SPUISD::AFormAddr:
379 // Just load from memory if there's only a single use of the location,
380 // otherwise, this will get handled below with D-form offset addresses
381 if (N.hasOneUse()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000382 SDValue Op0 = N.getOperand(0);
Scott Michel053c1da2008-01-29 02:16:57 +0000383 switch (Op0.getOpcode()) {
384 case ISD::TargetConstantPool:
385 case ISD::TargetJumpTable:
386 Base = Op0;
387 Index = Zero;
388 return true;
389
390 case ISD::TargetGlobalAddress: {
391 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op0);
392 GlobalValue *GV = GSDN->getGlobal();
393 if (GV->getAlignment() == 16) {
394 Base = Op0;
395 Index = Zero;
396 return true;
397 }
398 break;
399 }
400 }
401 }
402 break;
403 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000404 return false;
405}
406
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000407bool
Dan Gohman475871a2008-07-27 21:46:04 +0000408SPUDAGToDAGISel::SelectDForm2Addr(SDValue Op, SDValue N, SDValue &Disp,
409 SDValue &Base) {
Scott Michel203b2d62008-04-30 00:30:08 +0000410 const int minDForm2Offset = -(1 << 7);
411 const int maxDForm2Offset = (1 << 7) - 1;
412 return DFormAddressPredicate(Op, N, Disp, Base, minDForm2Offset,
413 maxDForm2Offset);
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000414}
415
Scott Michel266bc8f2007-12-04 22:23:35 +0000416/*!
417 \arg Op The ISD instruction (ignored)
418 \arg N The address to be tested
419 \arg Base Base address register/pointer
420 \arg Index Base address index
421
422 Examine the input address by a base register plus a signed 10-bit
423 displacement, [r+I10] (D-form address).
424
425 \return true if \a N is a D-form address with \a Base and \a Index set
Dan Gohman475871a2008-07-27 21:46:04 +0000426 to non-empty SDValue instances.
Scott Michel266bc8f2007-12-04 22:23:35 +0000427*/
428bool
Dan Gohman475871a2008-07-27 21:46:04 +0000429SPUDAGToDAGISel::SelectDFormAddr(SDValue Op, SDValue N, SDValue &Base,
430 SDValue &Index) {
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000431 return DFormAddressPredicate(Op, N, Base, Index,
Scott Michel9c0c6b22008-11-21 02:56:16 +0000432 SPUFrameInfo::minFrameOffset(),
433 SPUFrameInfo::maxFrameOffset());
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000434}
435
436bool
Dan Gohman475871a2008-07-27 21:46:04 +0000437SPUDAGToDAGISel::DFormAddressPredicate(SDValue Op, SDValue N, SDValue &Base,
438 SDValue &Index, int minOffset,
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000439 int maxOffset) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000440 unsigned Opc = N.getOpcode();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000441 MVT PtrTy = SPUtli.getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +0000442
Scott Michel053c1da2008-01-29 02:16:57 +0000443 if (Opc == ISD::FrameIndex) {
444 // Stack frame index must be less than 512 (divided by 16):
Scott Michel203b2d62008-04-30 00:30:08 +0000445 FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N);
446 int FI = int(FIN->getIndex());
Scott Michel266bc8f2007-12-04 22:23:35 +0000447 DEBUG(cerr << "SelectDFormAddr: ISD::FrameIndex = "
Scott Michel203b2d62008-04-30 00:30:08 +0000448 << FI << "\n");
449 if (SPUFrameInfo::FItoStackOffset(FI) < maxOffset) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000450 Base = CurDAG->getTargetConstant(0, PtrTy);
Scott Michel203b2d62008-04-30 00:30:08 +0000451 Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
Scott Michel266bc8f2007-12-04 22:23:35 +0000452 return true;
453 }
454 } else if (Opc == ISD::ADD) {
455 // Generated by getelementptr
Dan Gohman475871a2008-07-27 21:46:04 +0000456 const SDValue Op0 = N.getOperand(0);
457 const SDValue Op1 = N.getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000458
Scott Michel053c1da2008-01-29 02:16:57 +0000459 if ((Op0.getOpcode() == SPUISD::Hi && Op1.getOpcode() == SPUISD::Lo)
460 || (Op1.getOpcode() == SPUISD::Hi && Op0.getOpcode() == SPUISD::Lo)) {
461 Base = CurDAG->getTargetConstant(0, PtrTy);
462 Index = N;
463 return true;
464 } else if (Op1.getOpcode() == ISD::Constant
465 || Op1.getOpcode() == ISD::TargetConstant) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000466 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1);
Dan Gohman7810bfe2008-09-26 21:54:37 +0000467 int32_t offset = int32_t(CN->getSExtValue());
Scott Michel9de5d0d2008-01-11 02:53:15 +0000468
Scott Michel053c1da2008-01-29 02:16:57 +0000469 if (Op0.getOpcode() == ISD::FrameIndex) {
Scott Michel203b2d62008-04-30 00:30:08 +0000470 FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Op0);
471 int FI = int(FIN->getIndex());
Scott Michel9de5d0d2008-01-11 02:53:15 +0000472 DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset
Scott Michel203b2d62008-04-30 00:30:08 +0000473 << " frame index = " << FI << "\n");
Scott Michel9de5d0d2008-01-11 02:53:15 +0000474
Scott Michel203b2d62008-04-30 00:30:08 +0000475 if (SPUFrameInfo::FItoStackOffset(FI) < maxOffset) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000476 Base = CurDAG->getTargetConstant(offset, PtrTy);
Scott Michel203b2d62008-04-30 00:30:08 +0000477 Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000478 return true;
479 }
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000480 } else if (offset > minOffset && offset < maxOffset) {
Scott Michel9de5d0d2008-01-11 02:53:15 +0000481 Base = CurDAG->getTargetConstant(offset, PtrTy);
Scott Michel053c1da2008-01-29 02:16:57 +0000482 Index = Op0;
483 return true;
484 }
485 } else if (Op0.getOpcode() == ISD::Constant
486 || Op0.getOpcode() == ISD::TargetConstant) {
487 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op0);
Dan Gohman7810bfe2008-09-26 21:54:37 +0000488 int32_t offset = int32_t(CN->getSExtValue());
Scott Michel053c1da2008-01-29 02:16:57 +0000489
490 if (Op1.getOpcode() == ISD::FrameIndex) {
Scott Michel203b2d62008-04-30 00:30:08 +0000491 FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Op1);
492 int FI = int(FIN->getIndex());
Scott Michel053c1da2008-01-29 02:16:57 +0000493 DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset
Scott Michel203b2d62008-04-30 00:30:08 +0000494 << " frame index = " << FI << "\n");
Scott Michel053c1da2008-01-29 02:16:57 +0000495
Scott Michel203b2d62008-04-30 00:30:08 +0000496 if (SPUFrameInfo::FItoStackOffset(FI) < maxOffset) {
Scott Michel053c1da2008-01-29 02:16:57 +0000497 Base = CurDAG->getTargetConstant(offset, PtrTy);
Scott Michel203b2d62008-04-30 00:30:08 +0000498 Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
Scott Michel9de5d0d2008-01-11 02:53:15 +0000499 return true;
500 }
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000501 } else if (offset > minOffset && offset < maxOffset) {
Scott Michel053c1da2008-01-29 02:16:57 +0000502 Base = CurDAG->getTargetConstant(offset, PtrTy);
503 Index = Op1;
504 return true;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000505 }
Scott Michel053c1da2008-01-29 02:16:57 +0000506 }
507 } else if (Opc == SPUISD::IndirectAddr) {
508 // Indirect with constant offset -> D-Form address
Dan Gohman475871a2008-07-27 21:46:04 +0000509 const SDValue Op0 = N.getOperand(0);
510 const SDValue Op1 = N.getOperand(1);
Scott Michel497e8882008-01-11 21:01:19 +0000511
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000512 if (Op0.getOpcode() == SPUISD::Hi
513 && Op1.getOpcode() == SPUISD::Lo) {
Scott Michel053c1da2008-01-29 02:16:57 +0000514 // (SPUindirect (SPUhi <arg>, 0), (SPUlo <arg>, 0))
Scott Michel9de5d0d2008-01-11 02:53:15 +0000515 Base = CurDAG->getTargetConstant(0, PtrTy);
Scott Michel053c1da2008-01-29 02:16:57 +0000516 Index = N;
Scott Michel9de5d0d2008-01-11 02:53:15 +0000517 return true;
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000518 } else if (isa<ConstantSDNode>(Op0) || isa<ConstantSDNode>(Op1)) {
519 int32_t offset = 0;
Dan Gohman475871a2008-07-27 21:46:04 +0000520 SDValue idxOp;
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000521
522 if (isa<ConstantSDNode>(Op1)) {
523 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
Dan Gohman7810bfe2008-09-26 21:54:37 +0000524 offset = int32_t(CN->getSExtValue());
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000525 idxOp = Op0;
526 } else if (isa<ConstantSDNode>(Op0)) {
527 ConstantSDNode *CN = cast<ConstantSDNode>(Op0);
Dan Gohman7810bfe2008-09-26 21:54:37 +0000528 offset = int32_t(CN->getSExtValue());
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000529 idxOp = Op1;
530 }
531
532 if (offset >= minOffset && offset <= maxOffset) {
533 Base = CurDAG->getTargetConstant(offset, PtrTy);
534 Index = idxOp;
535 return true;
536 }
Scott Michel9de5d0d2008-01-11 02:53:15 +0000537 }
Scott Michel053c1da2008-01-29 02:16:57 +0000538 } else if (Opc == SPUISD::AFormAddr) {
539 Base = CurDAG->getTargetConstant(0, N.getValueType());
540 Index = N;
Scott Michel58c58182008-01-17 20:38:41 +0000541 return true;
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000542 } else if (Opc == SPUISD::LDRESULT) {
543 Base = CurDAG->getTargetConstant(0, N.getValueType());
544 Index = N;
545 return true;
Scott Michel9c0c6b22008-11-21 02:56:16 +0000546 } else if (Opc == ISD::Register || Opc == ISD::CopyFromReg) {
547 unsigned OpOpc = Op.getOpcode();
548
549 if (OpOpc == ISD::STORE || OpOpc == ISD::LOAD) {
550 // Direct load/store without getelementptr
551 SDValue Addr, Offs;
552
553 // Get the register from CopyFromReg
554 if (Opc == ISD::CopyFromReg)
555 Addr = N.getOperand(1);
556 else
557 Addr = N; // Register
558
Scott Michelaedc6372008-12-10 00:15:19 +0000559 Offs = ((OpOpc == ISD::STORE) ? Op.getOperand(3) : Op.getOperand(2));
Scott Michel9c0c6b22008-11-21 02:56:16 +0000560
561 if (Offs.getOpcode() == ISD::Constant || Offs.getOpcode() == ISD::UNDEF) {
562 if (Offs.getOpcode() == ISD::UNDEF)
563 Offs = CurDAG->getTargetConstant(0, Offs.getValueType());
564
565 Base = Offs;
566 Index = Addr;
567 return true;
568 }
Scott Michelaedc6372008-12-10 00:15:19 +0000569 } else {
570 /* If otherwise unadorned, default to D-form address with 0 offset: */
571 if (Opc == ISD::CopyFromReg) {
572 Index = N.getOperand(1);
573 } else {
574 Index = N;
575 }
576
577 Base = CurDAG->getTargetConstant(0, Index.getValueType());
578 return true;
Scott Michel9c0c6b22008-11-21 02:56:16 +0000579 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000580 }
Scott Michel9c0c6b22008-11-21 02:56:16 +0000581
Scott Michel266bc8f2007-12-04 22:23:35 +0000582 return false;
583}
584
585/*!
586 \arg Op The ISD instruction operand
587 \arg N The address operand
588 \arg Base The base pointer operand
589 \arg Index The offset/index operand
590
Scott Michel9c0c6b22008-11-21 02:56:16 +0000591 If the address \a N can be expressed as an A-form or D-form address, returns
592 false. Otherwise, creates two operands, Base and Index that will become the
593 (r)(r) X-form address.
Scott Michel266bc8f2007-12-04 22:23:35 +0000594*/
595bool
Dan Gohman475871a2008-07-27 21:46:04 +0000596SPUDAGToDAGISel::SelectXFormAddr(SDValue Op, SDValue N, SDValue &Base,
597 SDValue &Index) {
Scott Michel9c0c6b22008-11-21 02:56:16 +0000598 if (!SelectAFormAddr(Op, N, Base, Index)
599 && !SelectDFormAddr(Op, N, Base, Index)) {
Scott Michel18fae692008-11-25 17:29:43 +0000600 // If the address is neither A-form or D-form, punt and use an X-form
601 // address:
Scott Michel1a6cdb62008-12-01 17:56:02 +0000602 Base = N.getOperand(1);
603 Index = N.getOperand(0);
Scott Michel50843c02008-11-25 04:03:47 +0000604 return true;
Scott Michel9c0c6b22008-11-21 02:56:16 +0000605 }
606
607 return false;
Scott Michel58c58182008-01-17 20:38:41 +0000608}
609
Scott Michel266bc8f2007-12-04 22:23:35 +0000610//! Convert the operand from a target-independent to a target-specific node
611/*!
612 */
613SDNode *
Dan Gohman475871a2008-07-27 21:46:04 +0000614SPUDAGToDAGISel::Select(SDValue Op) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000615 SDNode *N = Op.getNode();
Scott Michel266bc8f2007-12-04 22:23:35 +0000616 unsigned Opc = N->getOpcode();
Scott Michel58c58182008-01-17 20:38:41 +0000617 int n_ops = -1;
618 unsigned NewOpc;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000619 MVT OpVT = Op.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +0000620 SDValue Ops[8];
Scott Michel266bc8f2007-12-04 22:23:35 +0000621
Dan Gohmane8be6c62008-07-17 19:10:17 +0000622 if (N->isMachineOpcode()) {
Scott Michel266bc8f2007-12-04 22:23:35 +0000623 return NULL; // Already selected.
624 } else if (Opc == ISD::FrameIndex) {
Scott Michel203b2d62008-04-30 00:30:08 +0000625 // Selects to (add $sp, FI * stackSlotSize)
626 int FI =
627 SPUFrameInfo::FItoStackOffset(cast<FrameIndexSDNode>(N)->getIndex());
Duncan Sands83ec4b62008-06-06 12:08:01 +0000628 MVT PtrVT = SPUtli.getPointerTy();
Scott Michel266bc8f2007-12-04 22:23:35 +0000629
Scott Michel203b2d62008-04-30 00:30:08 +0000630 // Adjust stack slot to actual offset in frame:
631 if (isS10Constant(FI)) {
632 DEBUG(cerr << "SPUDAGToDAGISel: Replacing FrameIndex with AIr32 $sp, "
633 << FI
634 << "\n");
635 NewOpc = SPU::AIr32;
636 Ops[0] = CurDAG->getRegister(SPU::R1, PtrVT);
637 Ops[1] = CurDAG->getTargetConstant(FI, PtrVT);
638 n_ops = 2;
639 } else {
640 DEBUG(cerr << "SPUDAGToDAGISel: Replacing FrameIndex with Ar32 $sp, "
641 << FI
642 << "\n");
643 NewOpc = SPU::Ar32;
644 Ops[0] = CurDAG->getRegister(SPU::R1, PtrVT);
645 Ops[1] = CurDAG->getConstant(FI, PtrVT);
646 n_ops = 2;
Scott Michel203b2d62008-04-30 00:30:08 +0000647 }
Scott Michel58c58182008-01-17 20:38:41 +0000648 } else if (Opc == ISD::ZERO_EXTEND) {
649 // (zero_extend:i16 (and:i8 <arg>, <const>))
Dan Gohman475871a2008-07-27 21:46:04 +0000650 const SDValue &Op1 = N->getOperand(0);
Scott Michel58c58182008-01-17 20:38:41 +0000651
652 if (Op.getValueType() == MVT::i16 && Op1.getValueType() == MVT::i8) {
653 if (Op1.getOpcode() == ISD::AND) {
654 // Fold this into a single ANDHI. This is often seen in expansions of i1
655 // to i8, then i8 to i16 in logical/branching operations.
656 DEBUG(cerr << "CellSPU: Coalescing (zero_extend:i16 (and:i8 "
657 "<arg>, <const>))\n");
Scott Michela59d4692008-02-23 18:41:37 +0000658 NewOpc = SPU::ANDHIi8i16;
Scott Michel58c58182008-01-17 20:38:41 +0000659 Ops[0] = Op1.getOperand(0);
660 Ops[1] = Op1.getOperand(1);
661 n_ops = 2;
662 }
663 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000664 } else if (Opc == SPUISD::LDRESULT) {
665 // Custom select instructions for LDRESULT
Duncan Sands83ec4b62008-06-06 12:08:01 +0000666 MVT VT = N->getValueType(0);
Dan Gohman475871a2008-07-27 21:46:04 +0000667 SDValue Arg = N->getOperand(0);
668 SDValue Chain = N->getOperand(1);
Scott Michel266bc8f2007-12-04 22:23:35 +0000669 SDNode *Result;
Scott Michela59d4692008-02-23 18:41:37 +0000670 const valtype_map_s *vtm = getValueTypeMapEntry(VT);
671
672 if (vtm->ldresult_ins == 0) {
673 cerr << "LDRESULT for unsupported type: "
Duncan Sands83ec4b62008-06-06 12:08:01 +0000674 << VT.getMVTString()
Scott Michela59d4692008-02-23 18:41:37 +0000675 << "\n";
676 abort();
677 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000678
Scott Michela59d4692008-02-23 18:41:37 +0000679 Opc = vtm->ldresult_ins;
680 if (vtm->ldresult_imm) {
Dan Gohman475871a2008-07-27 21:46:04 +0000681 SDValue Zero = CurDAG->getTargetConstant(0, VT);
Scott Michel86c041f2007-12-20 00:44:13 +0000682
Scott Michel58c58182008-01-17 20:38:41 +0000683 Result = CurDAG->getTargetNode(Opc, VT, MVT::Other, Arg, Zero, Chain);
Scott Michel86c041f2007-12-20 00:44:13 +0000684 } else {
Scott Michel30ee7df2008-12-04 03:02:42 +0000685 Result = CurDAG->getTargetNode(Opc, VT, MVT::Other, Arg, Arg, Chain);
Scott Michel86c041f2007-12-20 00:44:13 +0000686 }
687
Scott Michel266bc8f2007-12-04 22:23:35 +0000688 return Result;
Scott Michel053c1da2008-01-29 02:16:57 +0000689 } else if (Opc == SPUISD::IndirectAddr) {
Scott Michelf0569be2008-12-27 04:51:36 +0000690 // Look at the operands: SelectCode() will catch the cases that aren't
691 // specifically handled here.
692 //
693 // SPUInstrInfo catches the following patterns:
694 // (SPUindirect (SPUhi ...), (SPUlo ...))
695 // (SPUindirect $sp, imm)
696 MVT VT = Op.getValueType();
697 SDValue Op0 = N->getOperand(0);
698 SDValue Op1 = N->getOperand(1);
699 RegisterSDNode *RN;
Scott Michel58c58182008-01-17 20:38:41 +0000700
Scott Michelf0569be2008-12-27 04:51:36 +0000701 if ((Op0.getOpcode() != SPUISD::Hi && Op1.getOpcode() != SPUISD::Lo)
702 || (Op0.getOpcode() == ISD::Register
703 && ((RN = dyn_cast<RegisterSDNode>(Op0.getNode())) != 0
704 && RN->getReg() != SPU::R1))) {
705 NewOpc = SPU::Ar32;
Scott Michel58c58182008-01-17 20:38:41 +0000706 if (Op1.getOpcode() == ISD::Constant) {
707 ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
Scott Michelf0569be2008-12-27 04:51:36 +0000708 Op1 = CurDAG->getTargetConstant(CN->getSExtValue(), VT);
Scott Michel7f9ba9b2008-01-30 02:55:46 +0000709 NewOpc = (isI32IntS10Immediate(CN) ? SPU::AIr32 : SPU::Ar32);
Scott Michel58c58182008-01-17 20:38:41 +0000710 }
Scott Michelf0569be2008-12-27 04:51:36 +0000711 Ops[0] = Op0;
712 Ops[1] = Op1;
713 n_ops = 2;
Scott Michel58c58182008-01-17 20:38:41 +0000714 }
Scott Michel266bc8f2007-12-04 22:23:35 +0000715 }
716
Scott Michel58c58182008-01-17 20:38:41 +0000717 if (n_ops > 0) {
718 if (N->hasOneUse())
719 return CurDAG->SelectNodeTo(N, NewOpc, OpVT, Ops, n_ops);
720 else
721 return CurDAG->getTargetNode(NewOpc, OpVT, Ops, n_ops);
722 } else
723 return SelectCode(Op);
Scott Michel266bc8f2007-12-04 22:23:35 +0000724}
725
726/// createPPCISelDag - This pass converts a legalized DAG into a
727/// SPU-specific DAG, ready for instruction scheduling.
728///
729FunctionPass *llvm::createSPUISelDag(SPUTargetMachine &TM) {
730 return new SPUDAGToDAGISel(TM);
731}