SPUInstrInfo.cpp revision cbad42cfd1cc93a41ff26ea2e8895bfbc09f54f2
1//===- SPUInstrInfo.cpp - Cell SPU Instruction Information ----------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the Cell SPU implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPURegisterNames.h"
15#include "SPUInstrInfo.h"
16#include "SPUInstrBuilder.h"
17#include "SPUTargetMachine.h"
18#include "SPUGenInstrInfo.inc"
19#include "llvm/CodeGen/MachineInstrBuilder.h"
20#include "llvm/Support/Streams.h"
21
22using namespace llvm;
23
24SPUInstrInfo::SPUInstrInfo(SPUTargetMachine &tm)
25  : TargetInstrInfoImpl(SPUInsts, sizeof(SPUInsts)/sizeof(SPUInsts[0])),
26    TM(tm),
27    RI(*TM.getSubtargetImpl(), *this)
28{
29  /* NOP */
30}
31
32/// getPointerRegClass - Return the register class to use to hold pointers.
33/// This is used for addressing modes.
34const TargetRegisterClass *
35SPUInstrInfo::getPointerRegClass() const
36{
37  return &SPU::R32CRegClass;
38}
39
40bool
41SPUInstrInfo::isMoveInstr(const MachineInstr& MI,
42                          unsigned& sourceReg,
43                          unsigned& destReg) const {
44  // Primarily, ORI and OR are generated by copyRegToReg. But, there are other
45  // cases where we can safely say that what's being done is really a move
46  // (see how PowerPC does this -- it's the model for this code too.)
47  switch (MI.getOpcode()) {
48  default:
49    break;
50  case SPU::ORIv4i32:
51  case SPU::ORIr32:
52  case SPU::ORHIv8i16:
53  case SPU::ORHIr16:
54  case SPU::ORHIi8i16:
55  case SPU::ORBIv16i8:
56  case SPU::ORBIr8:
57  case SPU::ORIi16i32:
58  case SPU::ORIi8i32:
59  case SPU::AHIvec:
60  case SPU::AHIr16:
61  case SPU::AIvec:
62    assert(MI.getNumOperands() == 3 &&
63           MI.getOperand(0).isReg() &&
64           MI.getOperand(1).isReg() &&
65           MI.getOperand(2).isImm() &&
66           "invalid SPU ORI/ORHI/ORBI/AHI/AI/SFI/SFHI instruction!");
67    if (MI.getOperand(2).getImm() == 0) {
68      sourceReg = MI.getOperand(1).getReg();
69      destReg = MI.getOperand(0).getReg();
70      return true;
71    }
72    break;
73  case SPU::AIr32:
74    assert(MI.getNumOperands() == 3 &&
75           "wrong number of operands to AIr32");
76    if (MI.getOperand(0).isReg() &&
77        (MI.getOperand(1).isReg() ||
78         MI.getOperand(1).isFI()) &&
79        (MI.getOperand(2).isImm() &&
80         MI.getOperand(2).getImm() == 0)) {
81      sourceReg = MI.getOperand(1).getReg();
82      destReg = MI.getOperand(0).getReg();
83      return true;
84    }
85    break;
86  case SPU::ORv16i8_i8:
87  case SPU::ORv8i16_i16:
88  case SPU::ORv4i32_i32:
89  case SPU::ORv2i64_i64:
90  case SPU::ORv4f32_f32:
91  case SPU::ORv2f64_f64:
92  case SPU::ORi8_v16i8:
93  case SPU::ORi16_v8i16:
94  case SPU::ORi32_v4i32:
95  case SPU::ORi64_v2i64:
96  case SPU::ORf32_v4f32:
97  case SPU::ORf64_v2f64:
98  case SPU::ORv16i8:
99  case SPU::ORv8i16:
100  case SPU::ORv4i32:
101  case SPU::ORr32:
102  case SPU::ORr64:
103  case SPU::ORf32:
104  case SPU::ORf64:
105    assert(MI.getNumOperands() == 3 &&
106           MI.getOperand(0).isReg() &&
107           MI.getOperand(1).isReg() &&
108           MI.getOperand(2).isReg() &&
109           "invalid SPU OR(vec|r32|r64|gprc) instruction!");
110    if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
111      sourceReg = MI.getOperand(1).getReg();
112      destReg = MI.getOperand(0).getReg();
113      return true;
114    }
115    break;
116  }
117
118  return false;
119}
120
121unsigned
122SPUInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
123                                  int &FrameIndex) const {
124  switch (MI->getOpcode()) {
125  default: break;
126  case SPU::LQDv16i8:
127  case SPU::LQDv8i16:
128  case SPU::LQDv4i32:
129  case SPU::LQDv4f32:
130  case SPU::LQDv2f64:
131  case SPU::LQDr128:
132  case SPU::LQDr64:
133  case SPU::LQDr32:
134  case SPU::LQDr16:
135  case SPU::LQXv4i32:
136  case SPU::LQXr128:
137  case SPU::LQXr64:
138  case SPU::LQXr32:
139  case SPU::LQXr16:
140    if (MI->getOperand(1).isImm() && !MI->getOperand(1).getImm() &&
141        MI->getOperand(2).isFI()) {
142      FrameIndex = MI->getOperand(2).getIndex();
143      return MI->getOperand(0).getReg();
144    }
145    break;
146  }
147  return 0;
148}
149
150unsigned
151SPUInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
152                                 int &FrameIndex) const {
153  switch (MI->getOpcode()) {
154  default: break;
155  case SPU::STQDv16i8:
156  case SPU::STQDv8i16:
157  case SPU::STQDv4i32:
158  case SPU::STQDv4f32:
159  case SPU::STQDv2f64:
160  case SPU::STQDr128:
161  case SPU::STQDr64:
162  case SPU::STQDr32:
163  case SPU::STQDr16:
164    // case SPU::STQDr8:
165  case SPU::STQXv16i8:
166  case SPU::STQXv8i16:
167  case SPU::STQXv4i32:
168  case SPU::STQXv4f32:
169  case SPU::STQXv2f64:
170  case SPU::STQXr128:
171  case SPU::STQXr64:
172  case SPU::STQXr32:
173  case SPU::STQXr16:
174    // case SPU::STQXr8:
175    if (MI->getOperand(1).isImm() && !MI->getOperand(1).getImm() &&
176        MI->getOperand(2).isFI()) {
177      FrameIndex = MI->getOperand(2).getIndex();
178      return MI->getOperand(0).getReg();
179    }
180    break;
181  }
182  return 0;
183}
184
185bool SPUInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
186                                   MachineBasicBlock::iterator MI,
187                                   unsigned DestReg, unsigned SrcReg,
188                                   const TargetRegisterClass *DestRC,
189                                   const TargetRegisterClass *SrcRC) const
190{
191  // We support cross register class moves for our aliases, such as R3 in any
192  // reg class to any other reg class containing R3.  This is required because
193  // we instruction select bitconvert i64 -> f64 as a noop for example, so our
194  // types have no specific meaning.
195
196  //if (DestRC != SrcRC) {
197  //  cerr << "SPUInstrInfo::copyRegToReg(): DestRC != SrcRC not supported!\n";
198  //  abort();
199  //}
200
201  if (DestRC == SPU::R8CRegisterClass) {
202    BuildMI(MBB, MI, get(SPU::ORBIr8), DestReg).addReg(SrcReg).addImm(0);
203  } else if (DestRC == SPU::R16CRegisterClass) {
204    BuildMI(MBB, MI, get(SPU::ORHIr16), DestReg).addReg(SrcReg).addImm(0);
205  } else if (DestRC == SPU::R32CRegisterClass) {
206    BuildMI(MBB, MI, get(SPU::ORIr32), DestReg).addReg(SrcReg).addImm(0);
207  } else if (DestRC == SPU::R32FPRegisterClass) {
208    BuildMI(MBB, MI, get(SPU::ORf32), DestReg).addReg(SrcReg)
209      .addReg(SrcReg);
210  } else if (DestRC == SPU::R64CRegisterClass) {
211    BuildMI(MBB, MI, get(SPU::ORr64), DestReg).addReg(SrcReg)
212      .addReg(SrcReg);
213  } else if (DestRC == SPU::R64FPRegisterClass) {
214    BuildMI(MBB, MI, get(SPU::ORf64), DestReg).addReg(SrcReg)
215      .addReg(SrcReg);
216  } /* else if (DestRC == SPU::GPRCRegisterClass) {
217    BuildMI(MBB, MI, get(SPU::ORgprc), DestReg).addReg(SrcReg)
218      .addReg(SrcReg);
219  } */ else if (DestRC == SPU::VECREGRegisterClass) {
220    BuildMI(MBB, MI, get(SPU::ORv4i32), DestReg).addReg(SrcReg)
221      .addReg(SrcReg);
222  } else {
223    // Attempt to copy unknown/unsupported register class!
224    return false;
225  }
226
227  return true;
228}
229
230void
231SPUInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
232                                     MachineBasicBlock::iterator MI,
233                                     unsigned SrcReg, bool isKill, int FrameIdx,
234                                     const TargetRegisterClass *RC) const
235{
236  unsigned opc;
237  if (RC == SPU::GPRCRegisterClass) {
238    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
239      ? SPU::STQDr128
240      : SPU::STQXr128;
241  } else if (RC == SPU::R64CRegisterClass) {
242    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
243      ? SPU::STQDr64
244      : SPU::STQXr64;
245  } else if (RC == SPU::R64FPRegisterClass) {
246    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
247      ? SPU::STQDr64
248      : SPU::STQXr64;
249  } else if (RC == SPU::R32CRegisterClass) {
250    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
251      ? SPU::STQDr32
252      : SPU::STQXr32;
253  } else if (RC == SPU::R32FPRegisterClass) {
254    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
255      ? SPU::STQDr32
256      : SPU::STQXr32;
257  } else if (RC == SPU::R16CRegisterClass) {
258    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) ?
259      SPU::STQDr16
260      : SPU::STQXr16;
261  } else {
262    assert(0 && "Unknown regclass!");
263    abort();
264  }
265
266  addFrameReference(BuildMI(MBB, MI, get(opc))
267                    .addReg(SrcReg, false, false, isKill), FrameIdx);
268}
269
270void SPUInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
271                                     bool isKill,
272                                     SmallVectorImpl<MachineOperand> &Addr,
273                                     const TargetRegisterClass *RC,
274                                     SmallVectorImpl<MachineInstr*> &NewMIs) const {
275  cerr << "storeRegToAddr() invoked!\n";
276  abort();
277
278  if (Addr[0].isFI()) {
279    /* do what storeRegToStackSlot does here */
280  } else {
281    unsigned Opc = 0;
282    if (RC == SPU::GPRCRegisterClass) {
283      /* Opc = PPC::STW; */
284    } else if (RC == SPU::R16CRegisterClass) {
285      /* Opc = PPC::STD; */
286    } else if (RC == SPU::R32CRegisterClass) {
287      /* Opc = PPC::STFD; */
288    } else if (RC == SPU::R32FPRegisterClass) {
289      /* Opc = PPC::STFD; */
290    } else if (RC == SPU::R64FPRegisterClass) {
291      /* Opc = PPC::STFS; */
292    } else if (RC == SPU::VECREGRegisterClass) {
293      /* Opc = PPC::STVX; */
294    } else {
295      assert(0 && "Unknown regclass!");
296      abort();
297    }
298    MachineInstrBuilder MIB = BuildMI(MF, get(Opc))
299      .addReg(SrcReg, false, false, isKill);
300    for (unsigned i = 0, e = Addr.size(); i != e; ++i) {
301      MachineOperand &MO = Addr[i];
302      if (MO.isReg())
303        MIB.addReg(MO.getReg());
304      else if (MO.isImm())
305        MIB.addImm(MO.getImm());
306      else
307        MIB.addFrameIndex(MO.getIndex());
308    }
309    NewMIs.push_back(MIB);
310  }
311}
312
313void
314SPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
315                                        MachineBasicBlock::iterator MI,
316                                        unsigned DestReg, int FrameIdx,
317                                        const TargetRegisterClass *RC) const
318{
319  unsigned opc;
320  if (RC == SPU::GPRCRegisterClass) {
321    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
322      ? SPU::LQDr128
323      : SPU::LQXr128;
324  } else if (RC == SPU::R64CRegisterClass) {
325    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
326      ? SPU::LQDr64
327      : SPU::LQXr64;
328  } else if (RC == SPU::R64FPRegisterClass) {
329    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
330      ? SPU::LQDr64
331      : SPU::LQXr64;
332  } else if (RC == SPU::R32CRegisterClass) {
333    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
334      ? SPU::LQDr32
335      : SPU::LQXr32;
336  } else if (RC == SPU::R32FPRegisterClass) {
337    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
338      ? SPU::LQDr32
339      : SPU::LQXr32;
340  } else if (RC == SPU::R16CRegisterClass) {
341    opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
342      ? SPU::LQDr16
343      : SPU::LQXr16;
344  } else {
345    assert(0 && "Unknown regclass in loadRegFromStackSlot!");
346    abort();
347  }
348
349  addFrameReference(BuildMI(MBB, MI, get(opc)).addReg(DestReg), FrameIdx);
350}
351
352/*!
353  \note We are really pessimistic here about what kind of a load we're doing.
354 */
355void SPUInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
356                                      SmallVectorImpl<MachineOperand> &Addr,
357                                      const TargetRegisterClass *RC,
358                                      SmallVectorImpl<MachineInstr*> &NewMIs)
359    const {
360  cerr << "loadRegToAddr() invoked!\n";
361  abort();
362
363  if (Addr[0].isFI()) {
364    /* do what loadRegFromStackSlot does here... */
365  } else {
366    unsigned Opc = 0;
367    if (RC == SPU::R8CRegisterClass) {
368      /* do brilliance here */
369    } else if (RC == SPU::R16CRegisterClass) {
370      /* Opc = PPC::LWZ; */
371    } else if (RC == SPU::R32CRegisterClass) {
372      /* Opc = PPC::LD; */
373    } else if (RC == SPU::R32FPRegisterClass) {
374      /* Opc = PPC::LFD; */
375    } else if (RC == SPU::R64FPRegisterClass) {
376      /* Opc = PPC::LFS; */
377    } else if (RC == SPU::VECREGRegisterClass) {
378      /* Opc = PPC::LVX; */
379    } else if (RC == SPU::GPRCRegisterClass) {
380      /* Opc = something else! */
381    } else {
382      assert(0 && "Unknown regclass!");
383      abort();
384    }
385    MachineInstrBuilder MIB = BuildMI(MF, get(Opc), DestReg);
386    for (unsigned i = 0, e = Addr.size(); i != e; ++i) {
387      MachineOperand &MO = Addr[i];
388      if (MO.isReg())
389        MIB.addReg(MO.getReg());
390      else if (MO.isImm())
391        MIB.addImm(MO.getImm());
392      else
393        MIB.addFrameIndex(MO.getIndex());
394    }
395    NewMIs.push_back(MIB);
396  }
397}
398
399/// foldMemoryOperand - SPU, like PPC, can only fold spills into
400/// copy instructions, turning them into load/store instructions.
401MachineInstr *
402SPUInstrInfo::foldMemoryOperand(MachineFunction &MF,
403                                MachineInstr *MI,
404                                const SmallVectorImpl<unsigned> &Ops,
405                                int FrameIndex) const
406{
407#if SOMEDAY_SCOTT_LOOKS_AT_ME_AGAIN
408  if (Ops.size() != 1) return NULL;
409
410  unsigned OpNum = Ops[0];
411  unsigned Opc = MI->getOpcode();
412  MachineInstr *NewMI = 0;
413
414  if ((Opc == SPU::ORr32
415       || Opc == SPU::ORv4i32)
416       && MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) {
417    if (OpNum == 0) {  // move -> store
418      unsigned InReg = MI->getOperand(1).getReg();
419      bool isKill = MI->getOperand(1).isKill();
420      if (FrameIndex < SPUFrameInfo::maxFrameOffset()) {
421        NewMI = addFrameReference(BuildMI(MF, TII.get(SPU::STQDr32))
422                                  .addReg(InReg, false, false, isKill),
423                                  FrameIndex);
424      }
425    } else {           // move -> load
426      unsigned OutReg = MI->getOperand(0).getReg();
427      bool isDead = MI->getOperand(0).isDead();
428      Opc = (FrameIndex < SPUFrameInfo::maxFrameOffset())
429        ? SPU::STQDr32 : SPU::STQXr32;
430      NewMI = addFrameReference(BuildMI(MF, TII.get(Opc))
431                       .addReg(OutReg, true, false, false, isDead), FrameIndex);
432    }
433  }
434
435  return NewMI;
436#else
437  return 0;
438#endif
439}
440
441