diff options
Diffstat (limited to 'llvm/lib/Target/Sparc/SparcInstrInfo.cpp')
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrInfo.cpp | 158 | 
1 files changed, 135 insertions, 23 deletions
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp index 63f662c41f93..90662cd87dcf 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp @@ -28,6 +28,14 @@ using namespace llvm;  #define GET_INSTRINFO_CTOR_DTOR  #include "SparcGenInstrInfo.inc" +static cl::opt<unsigned> BPccDisplacementBits( +    "sparc-bpcc-offset-bits", cl::Hidden, cl::init(19), +    cl::desc("Restrict range of BPcc/FBPfcc instructions (DEBUG)")); + +static cl::opt<unsigned> +    BPrDisplacementBits("sparc-bpr-offset-bits", cl::Hidden, cl::init(16), +                        cl::desc("Restrict range of BPr instructions (DEBUG)")); +  // Pin the vtable to this file.  void SparcInstrInfo::anchor() {} @@ -73,11 +81,6 @@ unsigned SparcInstrInfo::isStoreToStackSlot(const MachineInstr &MI,    return 0;  } -static bool IsIntegerCC(unsigned CC) -{ -  return  (CC <= SPCC::ICC_VC); -} -  static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)  {    switch(CC) { @@ -155,9 +158,7 @@ static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)    llvm_unreachable("Invalid cond code");  } -static bool isUncondBranchOpcode(int Opc) { -  return Opc == SP::BA || Opc == SP::BPA; -} +static bool isUncondBranchOpcode(int Opc) { return Opc == SP::BA; }  static bool isI32CondBranchOpcode(int Opc) {    return Opc == SP::BCOND || Opc == SP::BPICC || Opc == SP::BPICCA || @@ -169,11 +170,19 @@ static bool isI64CondBranchOpcode(int Opc) {           Opc == SP::BPXCCANT;  } -static bool isFCondBranchOpcode(int Opc) { return Opc == SP::FBCOND; } +static bool isRegCondBranchOpcode(int Opc) { +  return Opc == SP::BPR || Opc == SP::BPRA || Opc == SP::BPRNT || +         Opc == SP::BPRANT; +} + +static bool isFCondBranchOpcode(int Opc) { +  return Opc == SP::FBCOND || Opc == SP::FBCONDA || Opc == SP::FBCOND_V9 || +         Opc == SP::FBCONDA_V9; +}  static bool isCondBranchOpcode(int Opc) {    return isI32CondBranchOpcode(Opc) || isI64CondBranchOpcode(Opc) || -         isFCondBranchOpcode(Opc); +         isRegCondBranchOpcode(Opc) || isFCondBranchOpcode(Opc);  }  static bool isIndirectBranchOpcode(int Opc) { @@ -190,9 +199,48 @@ static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,    Cond.push_back(MachineOperand::CreateImm(Opc));    Cond.push_back(MachineOperand::CreateImm(CC)); +  // Branch on register contents need another argument to indicate +  // the register it branches on. +  if (isRegCondBranchOpcode(Opc)) { +      Register Reg = LastInst->getOperand(2).getReg(); +      Cond.push_back(MachineOperand::CreateReg(Reg, false)); +  } +    Target = LastInst->getOperand(0).getMBB();  } +MachineBasicBlock * +SparcInstrInfo::getBranchDestBlock(const MachineInstr &MI) const { +  switch (MI.getOpcode()) { +  default: +      llvm_unreachable("unexpected opcode!"); +  case SP::BA: +  case SP::BCOND: +  case SP::BCONDA: +  case SP::FBCOND: +  case SP::FBCONDA: +  case SP::BPICC: +  case SP::BPICCA: +  case SP::BPICCNT: +  case SP::BPICCANT: +  case SP::BPXCC: +  case SP::BPXCCA: +  case SP::BPXCCNT: +  case SP::BPXCCANT: +  case SP::BPFCC: +  case SP::BPFCCA: +  case SP::BPFCCNT: +  case SP::BPFCCANT: +  case SP::FBCOND_V9: +  case SP::FBCONDA_V9: +  case SP::BPR: +  case SP::BPRA: +  case SP::BPRNT: +  case SP::BPRANT: +      return MI.getOperand(0).getMBB(); +  } +} +  bool SparcInstrInfo::analyzeBranch(MachineBasicBlock &MBB,                                     MachineBasicBlock *&TBB,                                     MachineBasicBlock *&FBB, @@ -283,38 +331,44 @@ unsigned SparcInstrInfo::insertBranch(MachineBasicBlock &MBB,                                        const DebugLoc &DL,                                        int *BytesAdded) const {    assert(TBB && "insertBranch must not be told to insert a fallthrough"); -  assert((Cond.size() <= 2) && -         "Sparc branch conditions should have at most two components!"); -  assert(!BytesAdded && "code size not handled"); +  assert((Cond.size() <= 3) && +         "Sparc branch conditions should have at most three components!");    if (Cond.empty()) {      assert(!FBB && "Unconditional branch with multiple successors!"); -    BuildMI(&MBB, DL, get(Subtarget.isV9() ? SP::BPA : SP::BA)).addMBB(TBB); +    BuildMI(&MBB, DL, get(SP::BA)).addMBB(TBB); +    if (BytesAdded) +      *BytesAdded = 8;      return 1;    }    // Conditional branch    unsigned Opc = Cond[0].getImm();    unsigned CC = Cond[1].getImm(); - -  if (IsIntegerCC(CC)) { -    BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC); +  if (isRegCondBranchOpcode(Opc)) { +    Register Reg = Cond[2].getReg(); +    BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC).addReg(Reg);    } else { -    BuildMI(&MBB, DL, get(SP::FBCOND)).addMBB(TBB).addImm(CC); +    BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC);    } -  if (!FBB) + +  if (!FBB) { +    if (BytesAdded) +      *BytesAdded = 8;      return 1; +  } -  BuildMI(&MBB, DL, get(Subtarget.isV9() ? SP::BPA : SP::BA)).addMBB(FBB); +  BuildMI(&MBB, DL, get(SP::BA)).addMBB(FBB); +  if (BytesAdded) +    *BytesAdded = 16;    return 2;  }  unsigned SparcInstrInfo::removeBranch(MachineBasicBlock &MBB,                                        int *BytesRemoved) const { -  assert(!BytesRemoved && "code size not handled"); -    MachineBasicBlock::iterator I = MBB.end();    unsigned Count = 0; +  int Removed = 0;    while (I != MBB.begin()) {      --I; @@ -325,21 +379,62 @@ unsigned SparcInstrInfo::removeBranch(MachineBasicBlock &MBB,          !isUncondBranchOpcode(I->getOpcode()))        break; // Not a branch +    Removed += getInstSizeInBytes(*I);      I->eraseFromParent();      I = MBB.end();      ++Count;    } + +  if (BytesRemoved) +    *BytesRemoved = Removed;    return Count;  }  bool SparcInstrInfo::reverseBranchCondition(      SmallVectorImpl<MachineOperand> &Cond) const { -  assert(Cond.size() <= 2); +  assert(Cond.size() <= 3);    SPCC::CondCodes CC = static_cast<SPCC::CondCodes>(Cond[1].getImm());    Cond[1].setImm(GetOppositeBranchCondition(CC));    return false;  } +bool SparcInstrInfo::isBranchOffsetInRange(unsigned BranchOpc, +                                           int64_t Offset) const { +  assert((Offset & 0b11) == 0 && "Malformed branch offset"); +  switch (BranchOpc) { +  case SP::BA: +  case SP::BCOND: +  case SP::BCONDA: +  case SP::FBCOND: +  case SP::FBCONDA: +    return isIntN(22, Offset >> 2); + +  case SP::BPICC: +  case SP::BPICCA: +  case SP::BPICCNT: +  case SP::BPICCANT: +  case SP::BPXCC: +  case SP::BPXCCA: +  case SP::BPXCCNT: +  case SP::BPXCCANT: +  case SP::BPFCC: +  case SP::BPFCCA: +  case SP::BPFCCNT: +  case SP::BPFCCANT: +  case SP::FBCOND_V9: +  case SP::FBCONDA_V9: +    return isIntN(BPccDisplacementBits, Offset >> 2); + +  case SP::BPR: +  case SP::BPRA: +  case SP::BPRNT: +  case SP::BPRANT: +    return isIntN(BPrDisplacementBits, Offset >> 2); +  } + +  llvm_unreachable("Unknown branch instruction!"); +} +  void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB,                                   MachineBasicBlock::iterator I,                                   const DebugLoc &DL, MCRegister DestReg, @@ -530,6 +625,23 @@ Register SparcInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {    return GlobalBaseReg;  } +unsigned SparcInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { +  unsigned Opcode = MI.getOpcode(); + +  if (MI.isInlineAsm()) { +    const MachineFunction *MF = MI.getParent()->getParent(); +    const char *AsmStr = MI.getOperand(0).getSymbolName(); +    return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); +  } + +  // If the instruction has a delay slot, be conservative and also include +  // it for sizing purposes. This is done so that the BranchRelaxation pass +  // will not mistakenly mark out-of-range branches as in-range. +  if (MI.hasDelaySlot()) +    return get(Opcode).getSize() * 2; +  return get(Opcode).getSize(); +} +  bool SparcInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {    switch (MI.getOpcode()) {    case TargetOpcode::LOAD_STACK_GUARD: {  | 
