diff options
Diffstat (limited to 'lib/Target/Mips/MipsInstrInfo.cpp')
| -rw-r--r-- | lib/Target/Mips/MipsInstrInfo.cpp | 192 | 
1 files changed, 163 insertions, 29 deletions
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index 4adf77f8d9a9..51ddc0d44c00 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -1,4 +1,4 @@ -//===-- MipsInstrInfo.cpp - Mips Instruction Information ------------------===// +//===- MipsInstrInfo.cpp - Mips Instruction Information -------------------===//  //  //                     The LLVM Compiler Infrastructure  // @@ -12,14 +12,22 @@  //===----------------------------------------------------------------------===//  #include "MipsInstrInfo.h" -#include "InstPrinter/MipsInstPrinter.h" -#include "MipsMachineFunction.h" +#include "MCTargetDesc/MipsBaseInfo.h" +#include "MCTargetDesc/MipsMCTargetDesc.h"  #include "MipsSubtarget.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h"  #include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/TargetRegistry.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/DebugLoc.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/Target/TargetMachine.h" +#include <cassert>  using namespace llvm; @@ -35,9 +43,9 @@ MipsInstrInfo::MipsInstrInfo(const MipsSubtarget &STI, unsigned UncondBr)  const MipsInstrInfo *MipsInstrInfo::create(MipsSubtarget &STI) {    if (STI.inMips16Mode()) -    return llvm::createMips16InstrInfo(STI); +    return createMips16InstrInfo(STI); -  return llvm::createMipsSEInstrInfo(STI); +  return createMipsSEInstrInfo(STI);  }  bool MipsInstrInfo::isZeroImm(const MachineOperand &op) const { @@ -80,7 +88,7 @@ void MipsInstrInfo::AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc,    BB = Inst->getOperand(NumOp-1).getMBB();    Cond.push_back(MachineOperand::CreateImm(Opc)); -  for (int i=0; i<NumOp-1; i++) +  for (int i = 0; i < NumOp-1; i++)      Cond.push_back(Inst->getOperand(i));  } @@ -149,24 +157,23 @@ unsigned MipsInstrInfo::removeBranch(MachineBasicBlock &MBB,    assert(!BytesRemoved && "code size not handled");    MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); -  unsigned removed; - -  // Skip all the debug instructions. -  while (I != REnd && I->isDebugValue()) -    ++I; - -  if (I == REnd) -    return 0; - -  MachineBasicBlock::iterator FirstBr = ++I.getReverse(); +  unsigned removed = 0;    // Up to 2 branches are removed.    // Note that indirect branches are not removed. -  for (removed = 0; I != REnd && removed < 2; ++I, ++removed) +  while (I != REnd && removed < 2) { +    // Skip past debug instructions. +    if (I->isDebugValue()) { +      ++I; +      continue; +    }      if (!getAnalyzableBrOpc(I->getOpcode()))        break; - -  MBB.erase((--I).getReverse(), FirstBr); +    // Remove the branch. +    I->eraseFromParent(); +    I = MBB.rbegin(); +    ++removed; +  }    return removed;  } @@ -185,7 +192,6 @@ MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch(      MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB,      SmallVectorImpl<MachineOperand> &Cond, bool AllowModify,      SmallVectorImpl<MachineInstr *> &BranchInstrs) const { -    MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend();    // Skip all the debug instructions. @@ -211,7 +217,13 @@ MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch(    unsigned SecondLastOpc = 0;    MachineInstr *SecondLastInst = nullptr; -  if (++I != REnd) { +  // Skip past any debug instruction to see if the second last actual +  // is a branch. +  ++I; +  while (I != REnd && I->isDebugValue()) +    ++I; + +  if (I != REnd) {      SecondLastInst = &*I;      SecondLastOpc = getAnalyzableBrOpc(SecondLastInst->getOpcode()); @@ -396,7 +408,6 @@ bool MipsInstrInfo::SafeInForbiddenSlot(const MachineInstr &MI) const {      return false;    return (MI.getDesc().TSFlags & MipsII::IsCTI) == 0; -  }  /// Predicate for distingushing instructions that have forbidden slots. @@ -469,7 +480,7 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,    MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc));    // For MIPSR6 JI*C requires an immediate 0 as an operand, JIALC(64) an -  // immediate 0 as an operand and requires the removal of it's %RA<imp-def> +  // immediate 0 as an operand and requires the removal of it's implicit-def %ra    // implicit operand as copying the implicit operations of the instructio we're    // looking at will give us the correct flags.    if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 || @@ -514,7 +525,7 @@ bool MipsInstrInfo::findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1,    case Mips::DPADD_U_D:    case Mips::DPADD_S_H:    case Mips::DPADD_S_W: -  case Mips::DPADD_S_D: { +  case Mips::DPADD_S_D:      // The first operand is both input and output, so it should not commute      if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3))        return false; @@ -523,6 +534,129 @@ bool MipsInstrInfo::findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1,        return false;      return true;    } -  }    return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2);  } + +// ins, ext, dext*, dins have the following constraints: +// X <= pos      <  Y +// X <  size     <= Y +// X <  pos+size <= Y +// +// dinsm and dinsu have the following constraints: +// X <= pos      <  Y +// X <= size     <= Y +// X <  pos+size <= Y +// +// The callee of verifyInsExtInstruction however gives the bounds of +// dins[um] like the other (d)ins (d)ext(um) instructions, so that this +// function doesn't have to vary it's behaviour based on the instruction +// being checked. +static bool verifyInsExtInstruction(const MachineInstr &MI, StringRef &ErrInfo, +                                    const int64_t PosLow, const int64_t PosHigh, +                                    const int64_t SizeLow, +                                    const int64_t SizeHigh, +                                    const int64_t BothLow, +                                    const int64_t BothHigh) { +  MachineOperand MOPos = MI.getOperand(2); +  if (!MOPos.isImm()) { +    ErrInfo = "Position is not an immediate!"; +    return false; +  } +  int64_t Pos = MOPos.getImm(); +  if (!((PosLow <= Pos) && (Pos < PosHigh))) { +    ErrInfo = "Position operand is out of range!"; +    return false; +  } + +  MachineOperand MOSize = MI.getOperand(3); +  if (!MOSize.isImm()) { +    ErrInfo = "Size operand is not an immediate!"; +    return false; +  } +  int64_t Size = MOSize.getImm(); +  if (!((SizeLow < Size) && (Size <= SizeHigh))) { +    ErrInfo = "Size operand is out of range!"; +    return false; +  } + +  if (!((BothLow < (Pos + Size)) && ((Pos + Size) <= BothHigh))) { +    ErrInfo = "Position + Size is out of range!"; +    return false; +  } + +  return true; +} + +//  Perform target specific instruction verification. +bool MipsInstrInfo::verifyInstruction(const MachineInstr &MI, +                                      StringRef &ErrInfo) const { +  // Verify that ins and ext instructions are well formed. +  switch (MI.getOpcode()) { +    case Mips::EXT: +    case Mips::EXT_MM: +    case Mips::INS: +    case Mips::INS_MM: +    case Mips::DINS: +      return verifyInsExtInstruction(MI, ErrInfo, 0, 32, 0, 32, 0, 32); +    case Mips::DINSM: +      // The ISA spec has a subtle difference difference between dinsm and dextm +      // in that it says: +      // 2 <= size <= 64 for 'dinsm' but 'dextm' has 32 < size <= 64. +      // To make the bounds checks similar, the range 1 < size <= 64 is checked +      // for 'dinsm'. +      return verifyInsExtInstruction(MI, ErrInfo, 0, 32, 1, 64, 32, 64); +    case Mips::DINSU: +      // The ISA spec has a subtle difference between dinsu and dextu in that +      // the size range of dinsu is specified as 1 <= size <= 32 whereas size +      // for dextu is 0 < size <= 32. The range checked for dinsu here is +      // 0 < size <= 32, which is equivalent and similar to dextu. +      return verifyInsExtInstruction(MI, ErrInfo, 32, 64, 0, 32, 32, 64); +    case Mips::DEXT: +      return verifyInsExtInstruction(MI, ErrInfo, 0, 32, 0, 32, 0, 63); +    case Mips::DEXTM: +      return verifyInsExtInstruction(MI, ErrInfo, 0, 32, 32, 64, 32, 64); +    case Mips::DEXTU: +      return verifyInsExtInstruction(MI, ErrInfo, 32, 64, 0, 32, 32, 64); +    default: +      return true; +  } + +  return true; +} + +std::pair<unsigned, unsigned> +MipsInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { +  return std::make_pair(TF, 0u); +} + +ArrayRef<std::pair<unsigned, const char*>> +MipsInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { + using namespace MipsII; + + static const std::pair<unsigned, const char*> Flags[] = { +    {MO_GOT,          "mips-got"}, +    {MO_GOT_CALL,     "mips-got-call"}, +    {MO_GPREL,        "mips-gprel"}, +    {MO_ABS_HI,       "mips-abs-hi"}, +    {MO_ABS_LO,       "mips-abs-lo"}, +    {MO_TLSGD,        "mips-tlsgd"}, +    {MO_TLSLDM,       "mips-tlsldm"}, +    {MO_DTPREL_HI,    "mips-dtprel-hi"}, +    {MO_DTPREL_LO,    "mips-dtprel-lo"}, +    {MO_GOTTPREL,     "mips-gottprel"}, +    {MO_TPREL_HI,     "mips-tprel-hi"}, +    {MO_TPREL_LO,     "mips-tprel-lo"}, +    {MO_GPOFF_HI,     "mips-gpoff-hi"}, +    {MO_GPOFF_LO,     "mips-gpoff-lo"}, +    {MO_GOT_DISP,     "mips-got-disp"}, +    {MO_GOT_PAGE,     "mips-got-page"}, +    {MO_GOT_OFST,     "mips-got-ofst"}, +    {MO_HIGHER,       "mips-higher"}, +    {MO_HIGHEST,      "mips-highest"}, +    {MO_GOT_HI16,     "mips-got-hi16"}, +    {MO_GOT_LO16,     "mips-got-lo16"}, +    {MO_CALL_HI16,    "mips-call-hi16"}, +    {MO_CALL_LO16,    "mips-call-lo16"} +  }; +  return makeArrayRef(Flags); +}  | 
