//===- SPUInstrInfo.cpp - Cell SPU Instruction Information ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the Cell SPU implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//

#include "SPURegisterNames.h"
#include "SPUInstrInfo.h"
#include "SPUInstrBuilder.h"
#include "SPUTargetMachine.h"
#include "SPUGenInstrInfo.inc"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {
  //! Predicate for an unconditional branch instruction
  inline bool isUncondBranch(const MachineInstr *I) {
    unsigned opc = I->getOpcode();

    return (opc == SPU::BR
            || opc == SPU::BRA
            || opc == SPU::BI);
  }

  //! Predicate for a conditional branch instruction
  inline bool isCondBranch(const MachineInstr *I) {
    unsigned opc = I->getOpcode();

    return (opc == SPU::BRNZr32
            || opc == SPU::BRNZv4i32
            || opc == SPU::BRZr32
            || opc == SPU::BRZv4i32
            || opc == SPU::BRHNZr16
            || opc == SPU::BRHNZv8i16
            || opc == SPU::BRHZr16
            || opc == SPU::BRHZv8i16);
  }
}

SPUInstrInfo::SPUInstrInfo(SPUTargetMachine &tm)
  : TargetInstrInfoImpl(SPUInsts, sizeof(SPUInsts)/sizeof(SPUInsts[0])),
    TM(tm),
    RI(*TM.getSubtargetImpl(), *this)
{ /* NOP */ }

unsigned
SPUInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
                                  int &FrameIndex) const {
  switch (MI->getOpcode()) {
  default: break;
  case SPU::LQDv16i8:
  case SPU::LQDv8i16:
  case SPU::LQDv4i32:
  case SPU::LQDv4f32:
  case SPU::LQDv2f64:
  case SPU::LQDr128:
  case SPU::LQDr64:
  case SPU::LQDr32:
  case SPU::LQDr16: {
    const MachineOperand MOp1 = MI->getOperand(1);
    const MachineOperand MOp2 = MI->getOperand(2);
    if (MOp1.isImm() && MOp2.isFI()) {
      FrameIndex = MOp2.getIndex();
      return MI->getOperand(0).getReg();
    }
    break;
  }
  }
  return 0;
}

unsigned
SPUInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
                                 int &FrameIndex) const {
  switch (MI->getOpcode()) {
  default: break;
  case SPU::STQDv16i8:
  case SPU::STQDv8i16:
  case SPU::STQDv4i32:
  case SPU::STQDv4f32:
  case SPU::STQDv2f64:
  case SPU::STQDr128:
  case SPU::STQDr64:
  case SPU::STQDr32:
  case SPU::STQDr16:
  case SPU::STQDr8: {
    const MachineOperand MOp1 = MI->getOperand(1);
    const MachineOperand MOp2 = MI->getOperand(2);
    if (MOp1.isImm() && MOp2.isFI()) {
      FrameIndex = MOp2.getIndex();
      return MI->getOperand(0).getReg();
    }
    break;
  }
  }
  return 0;
}

void SPUInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                               MachineBasicBlock::iterator I, DebugLoc DL,
                               unsigned DestReg, unsigned SrcReg,
                               bool KillSrc) const
{
  // We support cross register class moves for our aliases, such as R3 in any
  // reg class to any other reg class containing R3.  This is required because
  // we instruction select bitconvert i64 -> f64 as a noop for example, so our
  // types have no specific meaning.

  BuildMI(MBB, I, DL, get(SPU::LRr128), DestReg)
    .addReg(SrcReg, getKillRegState(KillSrc));
}

void
SPUInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
                                  MachineBasicBlock::iterator MI,
                                  unsigned SrcReg, bool isKill, int FrameIdx,
                                  const TargetRegisterClass *RC,
                                  const TargetRegisterInfo *TRI) const
{
  unsigned opc;
  bool isValidFrameIdx = (FrameIdx < SPUFrameInfo::maxFrameOffset());
  if (RC == SPU::GPRCRegisterClass) {
    opc = (isValidFrameIdx ? SPU::STQDr128 : SPU::STQXr128);
  } else if (RC == SPU::R64CRegisterClass) {
    opc = (isValidFrameIdx ? SPU::STQDr64 : SPU::STQXr64);
  } else if (RC == SPU::R64FPRegisterClass) {
    opc = (isValidFrameIdx ? SPU::STQDr64 : SPU::STQXr64);
  } else if (RC == SPU::R32CRegisterClass) {
    opc = (isValidFrameIdx ? SPU::STQDr32 : SPU::STQXr32);
  } else if (RC == SPU::R32FPRegisterClass) {
    opc = (isValidFrameIdx ? SPU::STQDr32 : SPU::STQXr32);
  } else if (RC == SPU::R16CRegisterClass) {
    opc = (isValidFrameIdx ? SPU::STQDr16 : SPU::STQXr16);
  } else if (RC == SPU::R8CRegisterClass) {
    opc = (isValidFrameIdx ? SPU::STQDr8 : SPU::STQXr8);
  } else if (RC == SPU::VECREGRegisterClass) {
    opc = (isValidFrameIdx) ? SPU::STQDv16i8 : SPU::STQXv16i8;
  } else {
    llvm_unreachable("Unknown regclass!");
  }

  DebugLoc DL;
  if (MI != MBB.end()) DL = MI->getDebugLoc();
  addFrameReference(BuildMI(MBB, MI, DL, get(opc))
                    .addReg(SrcReg, getKillRegState(isKill)), FrameIdx);
}

void
SPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
                                   MachineBasicBlock::iterator MI,
                                   unsigned DestReg, int FrameIdx,
                                   const TargetRegisterClass *RC,
                                   const TargetRegisterInfo *TRI) const
{
  unsigned opc;
  bool isValidFrameIdx = (FrameIdx < SPUFrameInfo::maxFrameOffset());
  if (RC == SPU::GPRCRegisterClass) {
    opc = (isValidFrameIdx ? SPU::LQDr128 : SPU::LQXr128);
  } else if (RC == SPU::R64CRegisterClass) {
    opc = (isValidFrameIdx ? SPU::LQDr64 : SPU::LQXr64);
  } else if (RC == SPU::R64FPRegisterClass) {
    opc = (isValidFrameIdx ? SPU::LQDr64 : SPU::LQXr64);
  } else if (RC == SPU::R32CRegisterClass) {
    opc = (isValidFrameIdx ? SPU::LQDr32 : SPU::LQXr32);
  } else if (RC == SPU::R32FPRegisterClass) {
    opc = (isValidFrameIdx ? SPU::LQDr32 : SPU::LQXr32);
  } else if (RC == SPU::R16CRegisterClass) {
    opc = (isValidFrameIdx ? SPU::LQDr16 : SPU::LQXr16);
  } else if (RC == SPU::R8CRegisterClass) {
    opc = (isValidFrameIdx ? SPU::LQDr8 : SPU::LQXr8);
  } else if (RC == SPU::VECREGRegisterClass) {
    opc = (isValidFrameIdx) ? SPU::LQDv16i8 : SPU::LQXv16i8;
  } else {
    llvm_unreachable("Unknown regclass in loadRegFromStackSlot!");
  }

  DebugLoc DL;
  if (MI != MBB.end()) DL = MI->getDebugLoc();
  addFrameReference(BuildMI(MBB, MI, DL, get(opc), DestReg), FrameIdx);
}

//! Branch analysis
/*!
  \note This code was kiped from PPC. There may be more branch analysis for
  CellSPU than what's currently done here.
 */
bool
SPUInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
                            MachineBasicBlock *&FBB,
                            SmallVectorImpl<MachineOperand> &Cond,
                            bool AllowModify) const {
  // If the block has no terminators, it just falls into the block after it.
  MachineBasicBlock::iterator I = MBB.end();
  if (I == MBB.begin())
    return false;
  --I;
  while (I->isDebugValue()) {
    if (I == MBB.begin())
      return false;
    --I;
  }
  if (!isUnpredicatedTerminator(I))
    return false;

  // Get the last instruction in the block.
  MachineInstr *LastInst = I;

  // If there is only one terminator instruction, process it.
  if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
    if (isUncondBranch(LastInst)) {
      // Check for jump tables
      if (!LastInst->getOperand(0).isMBB())
        return true;
      TBB = LastInst->getOperand(0).getMBB();
      return false;
    } else if (isCondBranch(LastInst)) {
      // Block ends with fall-through condbranch.
      TBB = LastInst->getOperand(1).getMBB();
      DEBUG(errs() << "Pushing LastInst:               ");
      DEBUG(LastInst->dump());
      Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
      Cond.push_back(LastInst->getOperand(0));
      return false;
    }
    // Otherwise, don't know what this is.
    return true;
  }

  // Get the instruction before it if it's a terminator.
  MachineInstr *SecondLastInst = I;

  // If there are three terminators, we don't know what sort of block this is.
  if (SecondLastInst && I != MBB.begin() &&
      isUnpredicatedTerminator(--I))
    return true;

  // If the block ends with a conditional and unconditional branch, handle it.
  if (isCondBranch(SecondLastInst) && isUncondBranch(LastInst)) {
    TBB =  SecondLastInst->getOperand(1).getMBB();
    DEBUG(errs() << "Pushing SecondLastInst:         ");
    DEBUG(SecondLastInst->dump());
    Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode()));
    Cond.push_back(SecondLastInst->getOperand(0));
    FBB = LastInst->getOperand(0).getMBB();
    return false;
  }

  // If the block ends with two unconditional branches, handle it.  The second
  // one is not executed, so remove it.
  if (isUncondBranch(SecondLastInst) && isUncondBranch(LastInst)) {
    TBB = SecondLastInst->getOperand(0).getMBB();
    I = LastInst;
    if (AllowModify)
      I->eraseFromParent();
    return false;
  }

  // Otherwise, can't handle this.
  return true;
}

unsigned
SPUInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
  MachineBasicBlock::iterator I = MBB.end();
  if (I == MBB.begin())
    return 0;
  --I;
  while (I->isDebugValue()) {
    if (I == MBB.begin())
      return 0;
    --I;
  }
  if (!isCondBranch(I) && !isUncondBranch(I))
    return 0;

  // Remove the first branch.
  DEBUG(errs() << "Removing branch:                ");
  DEBUG(I->dump());
  I->eraseFromParent();
  I = MBB.end();
  if (I == MBB.begin())
    return 1;

  --I;
  if (!(isCondBranch(I) || isUncondBranch(I)))
    return 1;

  // Remove the second branch.
  DEBUG(errs() << "Removing second branch:         ");
  DEBUG(I->dump());
  I->eraseFromParent();
  return 2;
}

unsigned
SPUInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
                           MachineBasicBlock *FBB,
                           const SmallVectorImpl<MachineOperand> &Cond,
                           DebugLoc DL) const {
  // Shouldn't be a fall through.
  assert(TBB && "InsertBranch must not be told to insert a fallthrough");
  assert((Cond.size() == 2 || Cond.size() == 0) &&
         "SPU branch conditions have two components!");

  // One-way branch.
  if (FBB == 0) {
    if (Cond.empty()) {
      // Unconditional branch
      MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(SPU::BR));
      MIB.addMBB(TBB);

      DEBUG(errs() << "Inserted one-way uncond branch: ");
      DEBUG((*MIB).dump());
    } else {
      // Conditional branch
      MachineInstrBuilder  MIB = BuildMI(&MBB, DL, get(Cond[0].getImm()));
      MIB.addReg(Cond[1].getReg()).addMBB(TBB);

      DEBUG(errs() << "Inserted one-way cond branch:   ");
      DEBUG((*MIB).dump());
    }
    return 1;
  } else {
    MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm()));
    MachineInstrBuilder MIB2 = BuildMI(&MBB, DL, get(SPU::BR));

    // Two-way Conditional Branch.
    MIB.addReg(Cond[1].getReg()).addMBB(TBB);
    MIB2.addMBB(FBB);

    DEBUG(errs() << "Inserted conditional branch:    ");
    DEBUG((*MIB).dump());
    DEBUG(errs() << "part 2: ");
    DEBUG((*MIB2).dump());
   return 2;
  }
}

//! Reverses a branch's condition, returning false on success.
bool
SPUInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond)
  const {
  // Pretty brainless way of inverting the condition, but it works, considering
  // there are only two conditions...
  static struct {
    unsigned Opc;               //! The incoming opcode
    unsigned RevCondOpc;        //! The reversed condition opcode
  } revconds[] = {
    { SPU::BRNZr32, SPU::BRZr32 },
    { SPU::BRNZv4i32, SPU::BRZv4i32 },
    { SPU::BRZr32, SPU::BRNZr32 },
    { SPU::BRZv4i32, SPU::BRNZv4i32 },
    { SPU::BRHNZr16, SPU::BRHZr16 },
    { SPU::BRHNZv8i16, SPU::BRHZv8i16 },
    { SPU::BRHZr16, SPU::BRHNZr16 },
    { SPU::BRHZv8i16, SPU::BRHNZv8i16 }
  };

  unsigned Opc = unsigned(Cond[0].getImm());
  // Pretty dull mapping between the two conditions that SPU can generate:
  for (int i = sizeof(revconds)/sizeof(revconds[0]) - 1; i >= 0; --i) {
    if (revconds[i].Opc == Opc) {
      Cond[0].setImm(revconds[i].RevCondOpc);
      return false;
    }
  }

  return true;
}
