[llvm] r332837 - [mips] Revert Merge MipsLongBranch and MipsHazardSchedule passes

Aleksandar Beserminji via llvm-commits llvm-commits at lists.llvm.org
Mon May 21 04:38:52 PDT 2018


Author: abeserminji
Date: Mon May 21 04:38:52 2018
New Revision: 332837

URL: http://llvm.org/viewvc/llvm-project?rev=332837&view=rev
Log:
[mips] Revert Merge MipsLongBranch and MipsHazardSchedule passes

Revert this patch due buildbot failure.

Differential Revision: https://reviews.llvm.org/D46641


Added:
    llvm/trunk/lib/Target/Mips/MipsHazardSchedule.cpp
    llvm/trunk/lib/Target/Mips/MipsLongBranch.cpp
Removed:
    llvm/trunk/lib/Target/Mips/MipsBranchExpansion.cpp
    llvm/trunk/test/CodeGen/Mips/branch-relaxation-with-hazard.ll
Modified:
    llvm/trunk/lib/Target/Mips/CMakeLists.txt
    llvm/trunk/lib/Target/Mips/Mips.h
    llvm/trunk/lib/Target/Mips/MipsTargetMachine.cpp
    llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-micromips.mir
    llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-micromipsr6.mir
    llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-mips.mir
    llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-mipsr6.mir
    llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-microMIPS.mir
    llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-micromipsr6.mir
    llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mips64.mir
    llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mips64r6.mir
    llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mipsr6.mir
    llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int.mir
    llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-msa.mir

Modified: llvm/trunk/lib/Target/Mips/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/CMakeLists.txt?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/CMakeLists.txt (original)
+++ llvm/trunk/lib/Target/Mips/CMakeLists.txt Mon May 21 04:38:52 2018
@@ -31,13 +31,14 @@ add_llvm_target(MipsCodeGen
   MipsConstantIslandPass.cpp
   MipsDelaySlotFiller.cpp
   MipsFastISel.cpp
+  MipsHazardSchedule.cpp
   MipsInstrInfo.cpp
   MipsInstructionSelector.cpp
   MipsISelDAGToDAG.cpp
   MipsISelLowering.cpp
   MipsFrameLowering.cpp
   MipsLegalizerInfo.cpp
-  MipsBranchExpansion.cpp
+  MipsLongBranch.cpp
   MipsMCInstLower.cpp
   MipsMachineFunction.cpp
   MipsModuleISelDAGToDAG.cpp

Modified: llvm/trunk/lib/Target/Mips/Mips.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/Mips.h?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/Mips.h (original)
+++ llvm/trunk/lib/Target/Mips/Mips.h Mon May 21 04:38:52 2018
@@ -33,7 +33,8 @@ namespace llvm {
   FunctionPass *createMipsModuleISelDagPass();
   FunctionPass *createMipsOptimizePICCallPass();
   FunctionPass *createMipsDelaySlotFillerPass();
-  FunctionPass *createMipsBranchExpansion();
+  FunctionPass *createMipsHazardSchedule();
+  FunctionPass *createMipsLongBranchPass();
   FunctionPass *createMipsConstantIslandPass();
   FunctionPass *createMicroMipsSizeReductionPass();
 
@@ -42,7 +43,7 @@ namespace llvm {
                                                      MipsRegisterBankInfo &);
 
   void initializeMipsDelaySlotFillerPass(PassRegistry &);
-  void initializeMipsBranchExpansionPass(PassRegistry &);
+  void initializeMipsLongBranchPass(PassRegistry &);
 } // end namespace llvm;
 
 #endif

Removed: llvm/trunk/lib/Target/Mips/MipsBranchExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsBranchExpansion.cpp?rev=332836&view=auto
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsBranchExpansion.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsBranchExpansion.cpp (removed)
@@ -1,794 +0,0 @@
-//===----------------------- MipsBranchExpansion.cpp ----------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-/// \file
-///
-/// This pass do two things:
-/// - it expands a branch or jump instruction into a long branch if its offset
-///   is too large to fit into its immediate field,
-/// - it inserts nops to prevent forbidden slot hazards.
-///
-/// The reason why this pass combines these two tasks is that one of these two
-/// tasks can break the result of the previous one.
-///
-/// Example of that is a situation where at first, no branch should be expanded,
-/// but after adding at least one nop somewhere in the code to prevent a
-/// forbidden slot hazard, offset of some branches may go out of range. In that
-/// case it is necessary to check again if there is some branch that needs
-/// expansion. On the other hand, expanding some branch may cause a control
-/// transfer instruction to appear in the forbidden slot, which is a hazard that
-/// should be fixed. This pass alternates between this two tasks untill no
-/// changes are made. Only then we can be sure that all branches are expanded
-/// properly, and no hazard situations exist.
-///
-/// Regarding branch expanding:
-///
-/// When branch instruction like beqzc or bnezc has offset that is too large
-/// to fit into its immediate field, it has to be expanded to another
-/// instruction or series of instructions.
-///
-/// FIXME: Fix pc-region jump instructions which cross 256MB segment boundaries.
-/// TODO: Handle out of range bc, b (pseudo) instructions.
-///
-/// Regarding compact branch hazard prevention:
-///
-/// Hazards handled: forbidden slots for MIPSR6.
-///
-/// A forbidden slot hazard occurs when a compact branch instruction is executed
-/// and the adjacent instruction in memory is a control transfer instruction
-/// such as a branch or jump, ERET, ERETNC, DERET, WAIT and PAUSE.
-///
-/// For example:
-///
-/// 0x8004      bnec    a1,v0,<P+0x18>
-/// 0x8008      beqc    a1,a2,<P+0x54>
-///
-/// In such cases, the processor is required to signal a Reserved Instruction
-/// exception.
-///
-/// Here, if the instruction at 0x8004 is executed, the processor will raise an
-/// exception as there is a control transfer instruction at 0x8008.
-///
-/// There are two sources of forbidden slot hazards:
-///
-/// A) A previous pass has created a compact branch directly.
-/// B) Transforming a delay slot branch into compact branch. This case can be
-///    difficult to process as lookahead for hazards is insufficient, as
-///    backwards delay slot fillling can also produce hazards in previously
-///    processed instuctions.
-///
-/// In future this pass can be extended (or new pass can be created) to handle
-/// other pipeline hazards, such as various MIPS1 hazards, processor errata that
-/// require instruction reorganization, etc.
-///
-/// This pass has to run after the delay slot filler as that pass can introduce
-/// pipeline hazards such as compact branch hazard, hence the existing hazard
-/// recognizer is not suitable.
-///
-//===----------------------------------------------------------------------===//
-
-#include "MCTargetDesc/MipsABIInfo.h"
-#include "MCTargetDesc/MipsBaseInfo.h"
-#include "MCTargetDesc/MipsMCNaCl.h"
-#include "MCTargetDesc/MipsMCTargetDesc.h"
-#include "Mips.h"
-#include "MipsInstrInfo.h"
-#include "MipsMachineFunction.h"
-#include "MipsSubtarget.h"
-#include "MipsTargetMachine.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/CodeGen/MachineBasicBlock.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/MachineOperand.h"
-#include "llvm/CodeGen/TargetSubtargetInfo.h"
-#include "llvm/IR/DebugLoc.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Target/TargetMachine.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <iterator>
-#include <utility>
-
-using namespace llvm;
-
-#define DEBUG_TYPE "mips-branch-expansion"
-
-STATISTIC(NumInsertedNops, "Number of nops inserted");
-STATISTIC(LongBranches, "Number of long branches.");
-
-static cl::opt<bool>
-    SkipLongBranch("skip-mips-long-branch", cl::init(false),
-                   cl::desc("MIPS: Skip branch expansion pass."), cl::Hidden);
-
-static cl::opt<bool>
-    ForceLongBranch("force-mips-long-branch", cl::init(false),
-                    cl::desc("MIPS: Expand all branches to long format."),
-                    cl::Hidden);
-
-namespace {
-
-using Iter = MachineBasicBlock::iterator;
-using ReverseIter = MachineBasicBlock::reverse_iterator;
-
-struct MBBInfo {
-  uint64_t Size = 0;
-  bool HasLongBranch = false;
-  MachineInstr *Br = nullptr;
-  MBBInfo() = default;
-};
-
-class MipsBranchExpansion : public MachineFunctionPass {
-public:
-  static char ID;
-
-  MipsBranchExpansion() : MachineFunctionPass(ID), ABI(MipsABIInfo::Unknown()) {
-    initializeMipsBranchExpansionPass(*PassRegistry::getPassRegistry());
-  }
-
-  StringRef getPassName() const override {
-    return "Mips Branch Expansion Pass";
-  }
-
-  bool runOnMachineFunction(MachineFunction &F) override;
-
-  MachineFunctionProperties getRequiredProperties() const override {
-    return MachineFunctionProperties().set(
-        MachineFunctionProperties::Property::NoVRegs);
-  }
-
-private:
-  void splitMBB(MachineBasicBlock *MBB);
-  void initMBBInfo();
-  int64_t computeOffset(const MachineInstr *Br);
-  void replaceBranch(MachineBasicBlock &MBB, Iter Br, const DebugLoc &DL,
-                     MachineBasicBlock *MBBOpnd);
-  void expandToLongBranch(MBBInfo &Info);
-  bool handleForbiddenSlot();
-  bool handlePossibleLongBranch();
-
-  const MipsSubtarget *STI;
-  const MipsInstrInfo *TII;
-
-  MachineFunction *MFp;
-  SmallVector<MBBInfo, 16> MBBInfos;
-  bool IsPIC;
-  MipsABIInfo ABI;
-  unsigned LongBranchSeqSize;
-};
-
-} // end of anonymous namespace
-
-char MipsBranchExpansion::ID = 0;
-
-INITIALIZE_PASS(MipsBranchExpansion, DEBUG_TYPE,
-                "Expand out of range branch instructions and prevent forbidden"
-                " slot hazards",
-                false, false)
-
-/// Returns a pass that clears pipeline hazards.
-FunctionPass *llvm::createMipsBranchExpansion() {
-  return new MipsBranchExpansion();
-}
-
-// Find the next real instruction from the current position in current basic
-// block.
-static Iter getNextMachineInstrInBB(Iter Position) {
-  Iter I = Position, E = Position->getParent()->end();
-  I = std::find_if_not(I, E,
-                       [](const Iter &Insn) { return Insn->isTransient(); });
-
-  return I;
-}
-
-// Find the next real instruction from the current position, looking through
-// basic block boundaries.
-static std::pair<Iter, bool> getNextMachineInstr(Iter Position,
-                                                 MachineBasicBlock *Parent) {
-  if (Position == Parent->end()) {
-    do {
-      MachineBasicBlock *Succ = Parent->getNextNode();
-      if (Succ != nullptr && Parent->isSuccessor(Succ)) {
-        Position = Succ->begin();
-        Parent = Succ;
-      } else {
-        return std::make_pair(Position, true);
-      }
-    } while (Parent->empty());
-  }
-
-  Iter Instr = getNextMachineInstrInBB(Position);
-  if (Instr == Parent->end()) {
-    return getNextMachineInstr(Instr, Parent);
-  }
-  return std::make_pair(Instr, false);
-}
-
-/// Iterate over list of Br's operands and search for a MachineBasicBlock
-/// operand.
-static MachineBasicBlock *getTargetMBB(const MachineInstr &Br) {
-  for (unsigned I = 0, E = Br.getDesc().getNumOperands(); I < E; ++I) {
-    const MachineOperand &MO = Br.getOperand(I);
-
-    if (MO.isMBB())
-      return MO.getMBB();
-  }
-
-  llvm_unreachable("This instruction does not have an MBB operand.");
-}
-
-// Traverse the list of instructions backwards until a non-debug instruction is
-// found or it reaches E.
-static ReverseIter getNonDebugInstr(ReverseIter B, const ReverseIter &E) {
-  for (; B != E; ++B)
-    if (!B->isDebugInstr())
-      return B;
-
-  return E;
-}
-
-// Split MBB if it has two direct jumps/branches.
-void MipsBranchExpansion::splitMBB(MachineBasicBlock *MBB) {
-  ReverseIter End = MBB->rend();
-  ReverseIter LastBr = getNonDebugInstr(MBB->rbegin(), End);
-
-  // Return if MBB has no branch instructions.
-  if ((LastBr == End) ||
-      (!LastBr->isConditionalBranch() && !LastBr->isUnconditionalBranch()))
-    return;
-
-  ReverseIter FirstBr = getNonDebugInstr(std::next(LastBr), End);
-
-  // MBB has only one branch instruction if FirstBr is not a branch
-  // instruction.
-  if ((FirstBr == End) ||
-      (!FirstBr->isConditionalBranch() && !FirstBr->isUnconditionalBranch()))
-    return;
-
-  assert(!FirstBr->isIndirectBranch() && "Unexpected indirect branch found.");
-
-  // Create a new MBB. Move instructions in MBB to the newly created MBB.
-  MachineBasicBlock *NewMBB =
-      MFp->CreateMachineBasicBlock(MBB->getBasicBlock());
-
-  // Insert NewMBB and fix control flow.
-  MachineBasicBlock *Tgt = getTargetMBB(*FirstBr);
-  NewMBB->transferSuccessors(MBB);
-  NewMBB->removeSuccessor(Tgt, true);
-  MBB->addSuccessor(NewMBB);
-  MBB->addSuccessor(Tgt);
-  MFp->insert(std::next(MachineFunction::iterator(MBB)), NewMBB);
-
-  NewMBB->splice(NewMBB->end(), MBB, LastBr.getReverse(), MBB->end());
-}
-
-// Fill MBBInfos.
-void MipsBranchExpansion::initMBBInfo() {
-  // Split the MBBs if they have two branches. Each basic block should have at
-  // most one branch after this loop is executed.
-  for (auto &MBB : *MFp)
-    splitMBB(&MBB);
-
-  MFp->RenumberBlocks();
-  MBBInfos.clear();
-  MBBInfos.resize(MFp->size());
-
-  for (unsigned I = 0, E = MBBInfos.size(); I < E; ++I) {
-    MachineBasicBlock *MBB = MFp->getBlockNumbered(I);
-
-    // Compute size of MBB.
-    for (MachineBasicBlock::instr_iterator MI = MBB->instr_begin();
-         MI != MBB->instr_end(); ++MI)
-      MBBInfos[I].Size += TII->getInstSizeInBytes(*MI);
-
-    // Search for MBB's branch instruction.
-    ReverseIter End = MBB->rend();
-    ReverseIter Br = getNonDebugInstr(MBB->rbegin(), End);
-
-    if ((Br != End) && !Br->isIndirectBranch() &&
-        (Br->isConditionalBranch() || (Br->isUnconditionalBranch() && IsPIC)))
-      MBBInfos[I].Br = &*Br;
-  }
-}
-
-// Compute offset of branch in number of bytes.
-int64_t MipsBranchExpansion::computeOffset(const MachineInstr *Br) {
-  int64_t Offset = 0;
-  int ThisMBB = Br->getParent()->getNumber();
-  int TargetMBB = getTargetMBB(*Br)->getNumber();
-
-  // Compute offset of a forward branch.
-  if (ThisMBB < TargetMBB) {
-    for (int N = ThisMBB + 1; N < TargetMBB; ++N)
-      Offset += MBBInfos[N].Size;
-
-    return Offset + 4;
-  }
-
-  // Compute offset of a backward branch.
-  for (int N = ThisMBB; N >= TargetMBB; --N)
-    Offset += MBBInfos[N].Size;
-
-  return -Offset + 4;
-}
-
-// Replace Br with a branch which has the opposite condition code and a
-// MachineBasicBlock operand MBBOpnd.
-void MipsBranchExpansion::replaceBranch(MachineBasicBlock &MBB, Iter Br,
-                                        const DebugLoc &DL,
-                                        MachineBasicBlock *MBBOpnd) {
-  unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode());
-  const MCInstrDesc &NewDesc = TII->get(NewOpc);
-
-  MachineInstrBuilder MIB = BuildMI(MBB, Br, DL, NewDesc);
-
-  for (unsigned I = 0, E = Br->getDesc().getNumOperands(); I < E; ++I) {
-    MachineOperand &MO = Br->getOperand(I);
-
-    if (!MO.isReg()) {
-      assert(MO.isMBB() && "MBB operand expected.");
-      break;
-    }
-
-    MIB.addReg(MO.getReg());
-  }
-
-  MIB.addMBB(MBBOpnd);
-
-  if (Br->hasDelaySlot()) {
-    // Bundle the instruction in the delay slot to the newly created branch
-    // and erase the original branch.
-    assert(Br->isBundledWithSucc());
-    MachineBasicBlock::instr_iterator II = Br.getInstrIterator();
-    MIBundleBuilder(&*MIB).append((++II)->removeFromBundle());
-  }
-  Br->eraseFromParent();
-}
-
-// Expand branch instructions to long branches.
-// TODO: This function has to be fixed for beqz16 and bnez16, because it
-// currently assumes that all branches have 16-bit offsets, and will produce
-// wrong code if branches whose allowed offsets are [-128, -126, ..., 126]
-// are present.
-void MipsBranchExpansion::expandToLongBranch(MBBInfo &I) {
-  MachineBasicBlock::iterator Pos;
-  MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br);
-  DebugLoc DL = I.Br->getDebugLoc();
-  const BasicBlock *BB = MBB->getBasicBlock();
-  MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB);
-  MachineBasicBlock *LongBrMBB = MFp->CreateMachineBasicBlock(BB);
-
-  MFp->insert(FallThroughMBB, LongBrMBB);
-  MBB->replaceSuccessor(TgtMBB, LongBrMBB);
-
-  if (IsPIC) {
-    MachineBasicBlock *BalTgtMBB = MFp->CreateMachineBasicBlock(BB);
-    MFp->insert(FallThroughMBB, BalTgtMBB);
-    LongBrMBB->addSuccessor(BalTgtMBB);
-    BalTgtMBB->addSuccessor(TgtMBB);
-
-    // We must select between the MIPS32r6/MIPS64r6 BALC (which is a normal
-    // instruction) and the pre-MIPS32r6/MIPS64r6 definition (which is an
-    // pseudo-instruction wrapping BGEZAL).
-    const unsigned BalOp =
-        STI->hasMips32r6()
-            ? STI->inMicroMipsMode() ? Mips::BALC_MMR6 : Mips::BALC
-            : STI->inMicroMipsMode() ? Mips::BAL_BR_MM : Mips::BAL_BR;
-
-    if (!ABI.IsN64()) {
-      // Pre R6:
-      // $longbr:
-      //  addiu $sp, $sp, -8
-      //  sw $ra, 0($sp)
-      //  lui $at, %hi($tgt - $baltgt)
-      //  bal $baltgt
-      //  addiu $at, $at, %lo($tgt - $baltgt)
-      // $baltgt:
-      //  addu $at, $ra, $at
-      //  lw $ra, 0($sp)
-      //  jr $at
-      //  addiu $sp, $sp, 8
-      // $fallthrough:
-      //
-
-      // R6:
-      // $longbr:
-      //  addiu $sp, $sp, -8
-      //  sw $ra, 0($sp)
-      //  lui $at, %hi($tgt - $baltgt)
-      //  addiu $at, $at, %lo($tgt - $baltgt)
-      //  balc $baltgt
-      // $baltgt:
-      //  addu $at, $ra, $at
-      //  lw $ra, 0($sp)
-      //  addiu $sp, $sp, 8
-      //  jic $at, 0
-      // $fallthrough:
-
-      Pos = LongBrMBB->begin();
-
-      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP)
-          .addReg(Mips::SP)
-          .addImm(-8);
-      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SW))
-          .addReg(Mips::RA)
-          .addReg(Mips::SP)
-          .addImm(0);
-
-      // LUi and ADDiu instructions create 32-bit offset of the target basic
-      // block from the target of BAL(C) instruction.  We cannot use immediate
-      // value for this offset because it cannot be determined accurately when
-      // the program has inline assembly statements.  We therefore use the
-      // relocation expressions %hi($tgt-$baltgt) and %lo($tgt-$baltgt) which
-      // are resolved during the fixup, so the values will always be correct.
-      //
-      // Since we cannot create %hi($tgt-$baltgt) and %lo($tgt-$baltgt)
-      // expressions at this point (it is possible only at the MC layer),
-      // we replace LUi and ADDiu with pseudo instructions
-      // LONG_BRANCH_LUi and LONG_BRANCH_ADDiu, and add both basic
-      // blocks as operands to these instructions.  When lowering these pseudo
-      // instructions to LUi and ADDiu in the MC layer, we will create
-      // %hi($tgt-$baltgt) and %lo($tgt-$baltgt) expressions and add them as
-      // operands to lowered instructions.
-
-      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi), Mips::AT)
-          .addMBB(TgtMBB)
-          .addMBB(BalTgtMBB);
-
-      MachineInstrBuilder BalInstr =
-          BuildMI(*MFp, DL, TII->get(BalOp)).addMBB(BalTgtMBB);
-      MachineInstrBuilder ADDiuInstr =
-          BuildMI(*MFp, DL, TII->get(Mips::LONG_BRANCH_ADDiu), Mips::AT)
-              .addReg(Mips::AT)
-              .addMBB(TgtMBB)
-              .addMBB(BalTgtMBB);
-      if (STI->hasMips32r6()) {
-        LongBrMBB->insert(Pos, ADDiuInstr);
-        LongBrMBB->insert(Pos, BalInstr);
-      } else {
-        LongBrMBB->insert(Pos, BalInstr);
-        LongBrMBB->insert(Pos, ADDiuInstr);
-        LongBrMBB->rbegin()->bundleWithPred();
-      }
-
-      Pos = BalTgtMBB->begin();
-
-      BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT)
-          .addReg(Mips::RA)
-          .addReg(Mips::AT);
-      BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA)
-          .addReg(Mips::SP)
-          .addImm(0);
-      if (STI->isTargetNaCl())
-        // Bundle-align the target of indirect branch JR.
-        TgtMBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN);
-
-      // In NaCl, modifying the sp is not allowed in branch delay slot.
-      // For MIPS32R6, we can skip using a delay slot branch.
-      if (STI->isTargetNaCl() ||
-          (STI->hasMips32r6() && !STI->useIndirectJumpsHazard()))
-        BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP)
-            .addReg(Mips::SP)
-            .addImm(8);
-
-      if (STI->hasMips32r6() && !STI->useIndirectJumpsHazard()) {
-        const unsigned JICOp =
-            STI->inMicroMipsMode() ? Mips::JIC_MMR6 : Mips::JIC;
-        BuildMI(*BalTgtMBB, Pos, DL, TII->get(JICOp))
-            .addReg(Mips::AT)
-            .addImm(0);
-
-      } else {
-        unsigned JROp =
-            STI->useIndirectJumpsHazard()
-                ? (STI->hasMips32r6() ? Mips::JR_HB_R6 : Mips::JR_HB)
-                : Mips::JR;
-        BuildMI(*BalTgtMBB, Pos, DL, TII->get(JROp)).addReg(Mips::AT);
-
-        if (STI->isTargetNaCl()) {
-          BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::NOP));
-        } else
-          BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP)
-              .addReg(Mips::SP)
-              .addImm(8);
-
-        BalTgtMBB->rbegin()->bundleWithPred();
-      }
-    } else {
-      // Pre R6:
-      // $longbr:
-      //  daddiu $sp, $sp, -16
-      //  sd $ra, 0($sp)
-      //  daddiu $at, $zero, %hi($tgt - $baltgt)
-      //  dsll $at, $at, 16
-      //  bal $baltgt
-      //  daddiu $at, $at, %lo($tgt - $baltgt)
-      // $baltgt:
-      //  daddu $at, $ra, $at
-      //  ld $ra, 0($sp)
-      //  jr64 $at
-      //  daddiu $sp, $sp, 16
-      // $fallthrough:
-
-      // R6:
-      // $longbr:
-      //  daddiu $sp, $sp, -16
-      //  sd $ra, 0($sp)
-      //  daddiu $at, $zero, %hi($tgt - $baltgt)
-      //  dsll $at, $at, 16
-      //  daddiu $at, $at, %lo($tgt - $baltgt)
-      //  balc $baltgt
-      // $baltgt:
-      //  daddu $at, $ra, $at
-      //  ld $ra, 0($sp)
-      //  daddiu $sp, $sp, 16
-      //  jic $at, 0
-      // $fallthrough:
-
-      // We assume the branch is within-function, and that offset is within
-      // +/- 2GB.  High 32 bits will therefore always be zero.
-
-      // Note that this will work even if the offset is negative, because
-      // of the +1 modification that's added in that case.  For example, if the
-      // offset is -1MB (0xFFFFFFFFFFF00000), the computation for %higher is
-      //
-      // 0xFFFFFFFFFFF00000 + 0x80008000 = 0x000000007FF08000
-      //
-      // and the bits [47:32] are zero.  For %highest
-      //
-      // 0xFFFFFFFFFFF00000 + 0x800080008000 = 0x000080007FF08000
-      //
-      // and the bits [63:48] are zero.
-
-      Pos = LongBrMBB->begin();
-
-      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64)
-          .addReg(Mips::SP_64)
-          .addImm(-16);
-      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SD))
-          .addReg(Mips::RA_64)
-          .addReg(Mips::SP_64)
-          .addImm(0);
-      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu),
-              Mips::AT_64)
-          .addReg(Mips::ZERO_64)
-          .addMBB(TgtMBB, MipsII::MO_ABS_HI)
-          .addMBB(BalTgtMBB);
-      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64)
-          .addReg(Mips::AT_64)
-          .addImm(16);
-
-      MachineInstrBuilder BalInstr =
-          BuildMI(*MFp, DL, TII->get(BalOp)).addMBB(BalTgtMBB);
-      MachineInstrBuilder DADDiuInstr =
-          BuildMI(*MFp, DL, TII->get(Mips::LONG_BRANCH_DADDiu), Mips::AT_64)
-              .addReg(Mips::AT_64)
-              .addMBB(TgtMBB, MipsII::MO_ABS_LO)
-              .addMBB(BalTgtMBB);
-      if (STI->hasMips32r6()) {
-        LongBrMBB->insert(Pos, DADDiuInstr);
-        LongBrMBB->insert(Pos, BalInstr);
-      } else {
-        LongBrMBB->insert(Pos, BalInstr);
-        LongBrMBB->insert(Pos, DADDiuInstr);
-        LongBrMBB->rbegin()->bundleWithPred();
-      }
-
-      Pos = BalTgtMBB->begin();
-
-      BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDu), Mips::AT_64)
-          .addReg(Mips::RA_64)
-          .addReg(Mips::AT_64);
-      BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64)
-          .addReg(Mips::SP_64)
-          .addImm(0);
-
-      if (STI->hasMips64r6() && !STI->useIndirectJumpsHazard()) {
-        BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64)
-            .addReg(Mips::SP_64)
-            .addImm(16);
-        BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JIC64))
-            .addReg(Mips::AT_64)
-            .addImm(0);
-      } else {
-        unsigned JROp =
-            STI->useIndirectJumpsHazard()
-                ? (STI->hasMips32r6() ? Mips::JR_HB64_R6 : Mips::JR_HB64)
-                : Mips::JR64;
-        BuildMI(*BalTgtMBB, Pos, DL, TII->get(JROp)).addReg(Mips::AT_64);
-        BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64)
-            .addReg(Mips::SP_64)
-            .addImm(16);
-        BalTgtMBB->rbegin()->bundleWithPred();
-      }
-    }
-
-    assert(LongBrMBB->size() + BalTgtMBB->size() == LongBranchSeqSize);
-  } else {
-    // Pre R6:                  R6:
-    // $longbr:                 $longbr:
-    //  j $tgt                   bc $tgt
-    //  nop                     $fallthrough
-    // $fallthrough:
-    //
-    Pos = LongBrMBB->begin();
-    LongBrMBB->addSuccessor(TgtMBB);
-    if (STI->hasMips32r6())
-      BuildMI(*LongBrMBB, Pos, DL,
-              TII->get(STI->inMicroMipsMode() ? Mips::BC_MMR6 : Mips::BC))
-          .addMBB(TgtMBB);
-    else
-      MIBundleBuilder(*LongBrMBB, Pos)
-          .append(BuildMI(*MFp, DL, TII->get(Mips::J)).addMBB(TgtMBB))
-          .append(BuildMI(*MFp, DL, TII->get(Mips::NOP)));
-
-    assert(LongBrMBB->size() == LongBranchSeqSize);
-  }
-
-  if (I.Br->isUnconditionalBranch()) {
-    // Change branch destination.
-    assert(I.Br->getDesc().getNumOperands() == 1);
-    I.Br->RemoveOperand(0);
-    I.Br->addOperand(MachineOperand::CreateMBB(LongBrMBB));
-  } else
-    // Change branch destination and reverse condition.
-    replaceBranch(*MBB, I.Br, DL, &*FallThroughMBB);
-}
-
-static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) {
-  MachineBasicBlock &MBB = F.front();
-  MachineBasicBlock::iterator I = MBB.begin();
-  DebugLoc DL = MBB.findDebugLoc(MBB.begin());
-  BuildMI(MBB, I, DL, TII->get(Mips::LUi), Mips::V0)
-      .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI);
-  BuildMI(MBB, I, DL, TII->get(Mips::ADDiu), Mips::V0)
-      .addReg(Mips::V0)
-      .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO);
-  MBB.removeLiveIn(Mips::V0);
-}
-
-bool MipsBranchExpansion::handleForbiddenSlot() {
-  // Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6.
-  if (!STI->hasMips32r6() || STI->inMicroMipsMode())
-    return false;
-
-  const MipsInstrInfo *TII = STI->getInstrInfo();
-
-  bool Changed = false;
-
-  for (MachineFunction::iterator FI = MFp->begin(); FI != MFp->end(); ++FI) {
-    for (Iter I = FI->begin(); I != FI->end(); ++I) {
-
-      // Forbidden slot hazard handling. Use lookahead over state.
-      if (!TII->HasForbiddenSlot(*I))
-        continue;
-
-      Iter Inst;
-      bool LastInstInFunction =
-          std::next(I) == FI->end() && std::next(FI) == MFp->end();
-      if (!LastInstInFunction) {
-        std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI);
-        LastInstInFunction |= Res.second;
-        Inst = Res.first;
-      }
-
-      if (LastInstInFunction || !TII->SafeInForbiddenSlot(*Inst)) {
-
-        MachineBasicBlock::instr_iterator Iit = I->getIterator();
-        if (std::next(Iit) == FI->end() ||
-            std::next(Iit)->getOpcode() != Mips::NOP) {
-          Changed = true;
-          MIBundleBuilder(&*I).append(
-              BuildMI(*MFp, I->getDebugLoc(), TII->get(Mips::NOP)));
-          NumInsertedNops++;
-        }
-      }
-    }
-  }
-
-  return Changed;
-}
-
-bool MipsBranchExpansion::handlePossibleLongBranch() {
-
-  LongBranchSeqSize = IsPIC ? ((ABI.IsN64() || STI->isTargetNaCl()) ? 10 : 9)
-                            : (STI->hasMips32r6() ? 1 : 2);
-
-  if (STI->inMips16Mode() || !STI->enableLongBranchPass())
-    return false;
-
-  if (SkipLongBranch)
-    return false;
-
-  initMBBInfo();
-
-  SmallVectorImpl<MBBInfo>::iterator I, E = MBBInfos.end();
-  bool EverMadeChange = false, MadeChange = true;
-
-  while (MadeChange) {
-    MadeChange = false;
-
-    for (I = MBBInfos.begin(); I != E; ++I) {
-      // Skip if this MBB doesn't have a branch or the branch has already been
-      // converted to a long branch.
-      if (!I->Br || I->HasLongBranch)
-        continue;
-
-      int64_t Offset = computeOffset(I->Br);
-
-      if (STI->isTargetNaCl()) {
-        // The offset calculation does not include sandboxing instructions
-        // that will be added later in the MC layer.  Since at this point we
-        // don't know the exact amount of code that "sandboxing" will add, we
-        // conservatively estimate that code will not grow more than 100%.
-        Offset *= 2;
-      }
-
-      // Check if offset fits into the immediate field of the branch.
-      if (!ForceLongBranch &&
-          TII->isBranchOffsetInRange(I->Br->getOpcode(), Offset))
-        continue;
-
-      I->HasLongBranch = true;
-      I->Size += LongBranchSeqSize * 4;
-      ++LongBranches;
-      EverMadeChange = MadeChange = true;
-    }
-  }
-
-  if (!EverMadeChange)
-    return false;
-
-  // Do the expansion.
-  for (I = MBBInfos.begin(); I != E; ++I)
-    if (I->HasLongBranch) {
-      expandToLongBranch(*I);
-    }
-
-  MFp->RenumberBlocks();
-
-  return true;
-}
-
-bool MipsBranchExpansion::runOnMachineFunction(MachineFunction &MF) {
-  const TargetMachine &TM = MF.getTarget();
-  IsPIC = TM.isPositionIndependent();
-  ABI = static_cast<const MipsTargetMachine &>(TM).getABI();
-  STI = &static_cast<const MipsSubtarget &>(MF.getSubtarget());
-  TII = static_cast<const MipsInstrInfo *>(STI->getInstrInfo());
-
-  if (IsPIC && ABI.IsO32() &&
-      MF.getInfo<MipsFunctionInfo>()->globalBaseRegSet())
-    emitGPDisp(MF, TII);
-
-  MFp = &MF;
-
-  // Run these two at least once
-  bool longBranchChanged = handlePossibleLongBranch();
-  bool forbiddenSlotChanged = handleForbiddenSlot();
-
-  bool Changed = longBranchChanged || forbiddenSlotChanged;
-
-  // Then run them alternatively while there are changes
-  while (forbiddenSlotChanged) {
-    longBranchChanged = handlePossibleLongBranch();
-    if (!longBranchChanged)
-      break;
-    forbiddenSlotChanged = handleForbiddenSlot();
-  }
-
-  return Changed;
-}

Added: llvm/trunk/lib/Target/Mips/MipsHazardSchedule.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsHazardSchedule.cpp?rev=332837&view=auto
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsHazardSchedule.cpp (added)
+++ llvm/trunk/lib/Target/Mips/MipsHazardSchedule.cpp Mon May 21 04:38:52 2018
@@ -0,0 +1,163 @@
+//===- MipsHazardSchedule.cpp - Workaround pipeline hazards ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This pass is used to workaround certain pipeline hazards. For now, this
+/// covers compact branch hazards. In future this pass can be extended to other
+/// pipeline hazards, such as various MIPS1 hazards, processor errata that
+/// require instruction reorganization, etc.
+///
+/// This pass has to run after the delay slot filler as that pass can introduce
+/// pipeline hazards, hence the existing hazard recognizer is not suitable.
+///
+/// Hazards handled: forbidden slots for MIPSR6.
+///
+/// A forbidden slot hazard occurs when a compact branch instruction is executed
+/// and the adjacent instruction in memory is a control transfer instruction
+/// such as a branch or jump, ERET, ERETNC, DERET, WAIT and PAUSE.
+///
+/// For example:
+///
+/// 0x8004      bnec    a1,v0,<P+0x18>
+/// 0x8008      beqc    a1,a2,<P+0x54>
+///
+/// In such cases, the processor is required to signal a Reserved Instruction
+/// exception.
+///
+/// Here, if the instruction at 0x8004 is executed, the processor will raise an
+/// exception as there is a control transfer instruction at 0x8008.
+///
+/// There are two sources of forbidden slot hazards:
+///
+/// A) A previous pass has created a compact branch directly.
+/// B) Transforming a delay slot branch into compact branch. This case can be
+///    difficult to process as lookahead for hazards is insufficient, as
+///    backwards delay slot fillling can also produce hazards in previously
+///    processed instuctions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Mips.h"
+#include "MipsInstrInfo.h"
+#include "MipsSubtarget.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include <algorithm>
+#include <iterator>
+#include <utility>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "mips-hazard-schedule"
+
+STATISTIC(NumInsertedNops, "Number of nops inserted");
+
+namespace {
+
+using Iter = MachineBasicBlock::iterator;
+using ReverseIter = MachineBasicBlock::reverse_iterator;
+
+class MipsHazardSchedule : public MachineFunctionPass {
+public:
+  MipsHazardSchedule() : MachineFunctionPass(ID) {}
+
+  StringRef getPassName() const override { return "Mips Hazard Schedule"; }
+
+  bool runOnMachineFunction(MachineFunction &F) override;
+
+  MachineFunctionProperties getRequiredProperties() const override {
+    return MachineFunctionProperties().set(
+        MachineFunctionProperties::Property::NoVRegs);
+  }
+
+private:
+  static char ID;
+};
+
+} // end of anonymous namespace
+
+char MipsHazardSchedule::ID = 0;
+
+/// Returns a pass that clears pipeline hazards.
+FunctionPass *llvm::createMipsHazardSchedule() {
+  return new MipsHazardSchedule();
+}
+
+// Find the next real instruction from the current position in current basic
+// block.
+static Iter getNextMachineInstrInBB(Iter Position) {
+  Iter I = Position, E = Position->getParent()->end();
+  I = std::find_if_not(I, E,
+                       [](const Iter &Insn) { return Insn->isTransient(); });
+
+  return I;
+}
+
+// Find the next real instruction from the current position, looking through
+// basic block boundaries.
+static std::pair<Iter, bool> getNextMachineInstr(Iter Position, MachineBasicBlock * Parent) {
+  if (Position == Parent->end()) {
+    do {
+      MachineBasicBlock *Succ = Parent->getNextNode();
+      if (Succ != nullptr && Parent->isSuccessor(Succ)) {
+        Position = Succ->begin();
+        Parent = Succ;
+      } else {
+        return std::make_pair(Position, true);
+      }
+    } while (Parent->empty());
+  }
+
+  Iter Instr = getNextMachineInstrInBB(Position);
+  if (Instr == Parent->end()) {
+    return getNextMachineInstr(Instr, Parent);
+  }
+  return std::make_pair(Instr, false);
+}
+
+bool MipsHazardSchedule::runOnMachineFunction(MachineFunction &MF) {
+
+  const MipsSubtarget *STI =
+      &static_cast<const MipsSubtarget &>(MF.getSubtarget());
+
+  // Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6.
+  if (!STI->hasMips32r6() || STI->inMicroMipsMode())
+    return false;
+
+  bool Changed = false;
+  const MipsInstrInfo *TII = STI->getInstrInfo();
+
+  for (MachineFunction::iterator FI = MF.begin(); FI != MF.end(); ++FI) {
+    for (Iter I = FI->begin(); I != FI->end(); ++I) {
+
+      // Forbidden slot hazard handling. Use lookahead over state.
+      if (!TII->HasForbiddenSlot(*I))
+        continue;
+
+      Iter Inst;
+      bool LastInstInFunction =
+          std::next(I) == FI->end() && std::next(FI) == MF.end();
+      if (!LastInstInFunction) {
+        std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI);
+        LastInstInFunction |= Res.second;
+        Inst = Res.first;
+      }
+
+      if (LastInstInFunction || !TII->SafeInForbiddenSlot(*Inst)) {
+        Changed = true;
+        MIBundleBuilder(&*I)
+            .append(BuildMI(MF, I->getDebugLoc(), TII->get(Mips::NOP)));
+        NumInsertedNops++;
+      }
+    }
+  }
+  return Changed;
+}

Added: llvm/trunk/lib/Target/Mips/MipsLongBranch.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsLongBranch.cpp?rev=332837&view=auto
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsLongBranch.cpp (added)
+++ llvm/trunk/lib/Target/Mips/MipsLongBranch.cpp Mon May 21 04:38:52 2018
@@ -0,0 +1,632 @@
+//===- MipsLongBranch.cpp - Emit long branches ----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass expands a branch or jump instruction into a long branch if its
+// offset is too large to fit into its immediate field.
+//
+// FIXME: Fix pc-region jump instructions which cross 256MB segment boundaries.
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/MipsABIInfo.h"
+#include "MCTargetDesc/MipsBaseInfo.h"
+#include "MCTargetDesc/MipsMCNaCl.h"
+#include "MCTargetDesc/MipsMCTargetDesc.h"
+#include "Mips.h"
+#include "MipsInstrInfo.h"
+#include "MipsMachineFunction.h"
+#include "MipsSubtarget.h"
+#include "MipsTargetMachine.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Target/TargetMachine.h"
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "mips-long-branch"
+
+STATISTIC(LongBranches, "Number of long branches.");
+
+static cl::opt<bool> SkipLongBranch(
+  "skip-mips-long-branch",
+  cl::init(false),
+  cl::desc("MIPS: Skip long branch pass."),
+  cl::Hidden);
+
+static cl::opt<bool> ForceLongBranch(
+  "force-mips-long-branch",
+  cl::init(false),
+  cl::desc("MIPS: Expand all branches to long format."),
+  cl::Hidden);
+
+namespace {
+
+  using Iter = MachineBasicBlock::iterator;
+  using ReverseIter = MachineBasicBlock::reverse_iterator;
+
+  struct MBBInfo {
+    uint64_t Size = 0;
+    uint64_t Address;
+    bool HasLongBranch = false;
+    MachineInstr *Br = nullptr;
+
+    MBBInfo() = default;
+  };
+
+  class MipsLongBranch : public MachineFunctionPass {
+  public:
+    static char ID;
+
+    MipsLongBranch() : MachineFunctionPass(ID), ABI(MipsABIInfo::Unknown()) {
+      initializeMipsLongBranchPass(*PassRegistry::getPassRegistry());
+    }
+
+    StringRef getPassName() const override { return "Mips Long Branch"; }
+
+    bool runOnMachineFunction(MachineFunction &F) override;
+
+    MachineFunctionProperties getRequiredProperties() const override {
+      return MachineFunctionProperties().set(
+          MachineFunctionProperties::Property::NoVRegs);
+    }
+
+  private:
+    void splitMBB(MachineBasicBlock *MBB);
+    void initMBBInfo();
+    int64_t computeOffset(const MachineInstr *Br);
+    void replaceBranch(MachineBasicBlock &MBB, Iter Br, const DebugLoc &DL,
+                       MachineBasicBlock *MBBOpnd);
+    void expandToLongBranch(MBBInfo &Info);
+
+    MachineFunction *MF;
+    SmallVector<MBBInfo, 16> MBBInfos;
+    bool IsPIC;
+    MipsABIInfo ABI;
+    unsigned LongBranchSeqSize;
+  };
+
+} // end anonymous namespace
+
+char MipsLongBranch::ID = 0;
+
+INITIALIZE_PASS(MipsLongBranch, DEBUG_TYPE,
+                "Expand out of range branch instructions", false, false)
+
+/// Iterate over list of Br's operands and search for a MachineBasicBlock
+/// operand.
+static MachineBasicBlock *getTargetMBB(const MachineInstr &Br) {
+  for (unsigned I = 0, E = Br.getDesc().getNumOperands(); I < E; ++I) {
+    const MachineOperand &MO = Br.getOperand(I);
+
+    if (MO.isMBB())
+      return MO.getMBB();
+  }
+
+  llvm_unreachable("This instruction does not have an MBB operand.");
+}
+
+// Traverse the list of instructions backwards until a non-debug instruction is
+// found or it reaches E.
+static ReverseIter getNonDebugInstr(ReverseIter B, const ReverseIter &E) {
+  for (; B != E; ++B)
+    if (!B->isDebugInstr())
+      return B;
+
+  return E;
+}
+
+// Split MBB if it has two direct jumps/branches.
+void MipsLongBranch::splitMBB(MachineBasicBlock *MBB) {
+  ReverseIter End = MBB->rend();
+  ReverseIter LastBr = getNonDebugInstr(MBB->rbegin(), End);
+
+  // Return if MBB has no branch instructions.
+  if ((LastBr == End) ||
+      (!LastBr->isConditionalBranch() && !LastBr->isUnconditionalBranch()))
+    return;
+
+  ReverseIter FirstBr = getNonDebugInstr(std::next(LastBr), End);
+
+  // MBB has only one branch instruction if FirstBr is not a branch
+  // instruction.
+  if ((FirstBr == End) ||
+      (!FirstBr->isConditionalBranch() && !FirstBr->isUnconditionalBranch()))
+    return;
+
+  assert(!FirstBr->isIndirectBranch() && "Unexpected indirect branch found.");
+
+  // Create a new MBB. Move instructions in MBB to the newly created MBB.
+  MachineBasicBlock *NewMBB =
+    MF->CreateMachineBasicBlock(MBB->getBasicBlock());
+
+  // Insert NewMBB and fix control flow.
+  MachineBasicBlock *Tgt = getTargetMBB(*FirstBr);
+  NewMBB->transferSuccessors(MBB);
+  NewMBB->removeSuccessor(Tgt, true);
+  MBB->addSuccessor(NewMBB);
+  MBB->addSuccessor(Tgt);
+  MF->insert(std::next(MachineFunction::iterator(MBB)), NewMBB);
+
+  NewMBB->splice(NewMBB->end(), MBB, LastBr.getReverse(), MBB->end());
+}
+
+// Fill MBBInfos.
+void MipsLongBranch::initMBBInfo() {
+  // Split the MBBs if they have two branches. Each basic block should have at
+  // most one branch after this loop is executed.
+  for (auto &MBB : *MF)
+    splitMBB(&MBB);
+
+  MF->RenumberBlocks();
+  MBBInfos.clear();
+  MBBInfos.resize(MF->size());
+
+  const MipsInstrInfo *TII =
+      static_cast<const MipsInstrInfo *>(MF->getSubtarget().getInstrInfo());
+  for (unsigned I = 0, E = MBBInfos.size(); I < E; ++I) {
+    MachineBasicBlock *MBB = MF->getBlockNumbered(I);
+
+    // Compute size of MBB.
+    for (MachineBasicBlock::instr_iterator MI = MBB->instr_begin();
+         MI != MBB->instr_end(); ++MI)
+      MBBInfos[I].Size += TII->getInstSizeInBytes(*MI);
+
+    // Search for MBB's branch instruction.
+    ReverseIter End = MBB->rend();
+    ReverseIter Br = getNonDebugInstr(MBB->rbegin(), End);
+
+    if ((Br != End) && !Br->isIndirectBranch() &&
+        (Br->isConditionalBranch() || (Br->isUnconditionalBranch() && IsPIC)))
+      MBBInfos[I].Br = &*Br;
+  }
+}
+
+// Compute offset of branch in number of bytes.
+int64_t MipsLongBranch::computeOffset(const MachineInstr *Br) {
+  int64_t Offset = 0;
+  int ThisMBB = Br->getParent()->getNumber();
+  int TargetMBB = getTargetMBB(*Br)->getNumber();
+
+  // Compute offset of a forward branch.
+  if (ThisMBB < TargetMBB) {
+    for (int N = ThisMBB + 1; N < TargetMBB; ++N)
+      Offset += MBBInfos[N].Size;
+
+    return Offset + 4;
+  }
+
+  // Compute offset of a backward branch.
+  for (int N = ThisMBB; N >= TargetMBB; --N)
+    Offset += MBBInfos[N].Size;
+
+  return -Offset + 4;
+}
+
+// Replace Br with a branch which has the opposite condition code and a
+// MachineBasicBlock operand MBBOpnd.
+void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br,
+                                   const DebugLoc &DL,
+                                   MachineBasicBlock *MBBOpnd) {
+  const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>(
+      MBB.getParent()->getSubtarget().getInstrInfo());
+  unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode());
+  const MCInstrDesc &NewDesc = TII->get(NewOpc);
+
+  MachineInstrBuilder MIB = BuildMI(MBB, Br, DL, NewDesc);
+
+  for (unsigned I = 0, E = Br->getDesc().getNumOperands(); I < E; ++I) {
+    MachineOperand &MO = Br->getOperand(I);
+
+    if (!MO.isReg()) {
+      assert(MO.isMBB() && "MBB operand expected.");
+      break;
+    }
+
+    MIB.addReg(MO.getReg());
+  }
+
+  MIB.addMBB(MBBOpnd);
+
+  if (Br->hasDelaySlot()) {
+    // Bundle the instruction in the delay slot to the newly created branch
+    // and erase the original branch.
+    assert(Br->isBundledWithSucc());
+    MachineBasicBlock::instr_iterator II = Br.getInstrIterator();
+    MIBundleBuilder(&*MIB).append((++II)->removeFromBundle());
+  }
+  Br->eraseFromParent();
+}
+
+// Expand branch instructions to long branches.
+// TODO: This function has to be fixed for beqz16 and bnez16, because it
+// currently assumes that all branches have 16-bit offsets, and will produce
+// wrong code if branches whose allowed offsets are [-128, -126, ..., 126]
+// are present.
+void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
+  MachineBasicBlock::iterator Pos;
+  MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br);
+  DebugLoc DL = I.Br->getDebugLoc();
+  const BasicBlock *BB = MBB->getBasicBlock();
+  MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB);
+  MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB);
+  const MipsSubtarget &Subtarget =
+      static_cast<const MipsSubtarget &>(MF->getSubtarget());
+  const MipsInstrInfo *TII =
+      static_cast<const MipsInstrInfo *>(Subtarget.getInstrInfo());
+
+  MF->insert(FallThroughMBB, LongBrMBB);
+  MBB->replaceSuccessor(TgtMBB, LongBrMBB);
+
+  if (IsPIC) {
+    MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB);
+    MF->insert(FallThroughMBB, BalTgtMBB);
+    LongBrMBB->addSuccessor(BalTgtMBB);
+    BalTgtMBB->addSuccessor(TgtMBB);
+
+    // We must select between the MIPS32r6/MIPS64r6 BALC (which is a normal
+    // instruction) and the pre-MIPS32r6/MIPS64r6 definition (which is an
+    // pseudo-instruction wrapping BGEZAL).
+    const unsigned BalOp =
+        Subtarget.hasMips32r6()
+            ? Subtarget.inMicroMipsMode() ? Mips::BALC_MMR6 : Mips::BALC
+            : Subtarget.inMicroMipsMode() ? Mips::BAL_BR_MM : Mips::BAL_BR;
+
+    if (!ABI.IsN64()) {
+      // Pre R6:
+      // $longbr:
+      //  addiu $sp, $sp, -8
+      //  sw $ra, 0($sp)
+      //  lui $at, %hi($tgt - $baltgt)
+      //  bal $baltgt
+      //  addiu $at, $at, %lo($tgt - $baltgt)
+      // $baltgt:
+      //  addu $at, $ra, $at
+      //  lw $ra, 0($sp)
+      //  jr $at
+      //  addiu $sp, $sp, 8
+      // $fallthrough:
+      //
+
+      // R6:
+      // $longbr:
+      //  addiu $sp, $sp, -8
+      //  sw $ra, 0($sp)
+      //  lui $at, %hi($tgt - $baltgt)
+      //  addiu $at, $at, %lo($tgt - $baltgt)
+      //  balc $baltgt
+      // $baltgt:
+      //  addu $at, $ra, $at
+      //  lw $ra, 0($sp)
+      //  addiu $sp, $sp, 8
+      //  jic $at, 0
+      // $fallthrough:
+
+      Pos = LongBrMBB->begin();
+
+      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP)
+        .addReg(Mips::SP).addImm(-8);
+      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SW)).addReg(Mips::RA)
+        .addReg(Mips::SP).addImm(0);
+
+      // LUi and ADDiu instructions create 32-bit offset of the target basic
+      // block from the target of BAL(C) instruction.  We cannot use immediate
+      // value for this offset because it cannot be determined accurately when
+      // the program has inline assembly statements.  We therefore use the
+      // relocation expressions %hi($tgt-$baltgt) and %lo($tgt-$baltgt) which
+      // are resolved during the fixup, so the values will always be correct.
+      //
+      // Since we cannot create %hi($tgt-$baltgt) and %lo($tgt-$baltgt)
+      // expressions at this point (it is possible only at the MC layer),
+      // we replace LUi and ADDiu with pseudo instructions
+      // LONG_BRANCH_LUi and LONG_BRANCH_ADDiu, and add both basic
+      // blocks as operands to these instructions.  When lowering these pseudo
+      // instructions to LUi and ADDiu in the MC layer, we will create
+      // %hi($tgt-$baltgt) and %lo($tgt-$baltgt) expressions and add them as
+      // operands to lowered instructions.
+
+      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi), Mips::AT)
+        .addMBB(TgtMBB).addMBB(BalTgtMBB);
+
+      MachineInstrBuilder BalInstr =
+          BuildMI(*MF, DL, TII->get(BalOp)).addMBB(BalTgtMBB);
+      MachineInstrBuilder ADDiuInstr =
+          BuildMI(*MF, DL, TII->get(Mips::LONG_BRANCH_ADDiu), Mips::AT)
+              .addReg(Mips::AT)
+              .addMBB(TgtMBB)
+              .addMBB(BalTgtMBB);
+      if (Subtarget.hasMips32r6()) {
+        LongBrMBB->insert(Pos, ADDiuInstr);
+        LongBrMBB->insert(Pos, BalInstr);
+      } else {
+        LongBrMBB->insert(Pos, BalInstr);
+        LongBrMBB->insert(Pos, ADDiuInstr);
+        LongBrMBB->rbegin()->bundleWithPred();
+      }
+
+      Pos = BalTgtMBB->begin();
+
+      BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT)
+        .addReg(Mips::RA).addReg(Mips::AT);
+      BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA)
+        .addReg(Mips::SP).addImm(0);
+      if (Subtarget.isTargetNaCl())
+        // Bundle-align the target of indirect branch JR.
+        TgtMBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN);
+
+      // In NaCl, modifying the sp is not allowed in branch delay slot.
+      // For MIPS32R6, we can skip using a delay slot branch.
+      if (Subtarget.isTargetNaCl() ||
+          (Subtarget.hasMips32r6() && !Subtarget.useIndirectJumpsHazard()))
+        BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP)
+          .addReg(Mips::SP).addImm(8);
+
+      if (Subtarget.hasMips32r6() && !Subtarget.useIndirectJumpsHazard()) {
+        const unsigned JICOp =
+            Subtarget.inMicroMipsMode() ? Mips::JIC_MMR6 : Mips::JIC;
+        BuildMI(*BalTgtMBB, Pos, DL, TII->get(JICOp))
+            .addReg(Mips::AT)
+            .addImm(0);
+
+      } else {
+        unsigned JROp =
+            Subtarget.useIndirectJumpsHazard()
+                ? (Subtarget.hasMips32r6() ? Mips::JR_HB_R6 : Mips::JR_HB)
+                : Mips::JR;
+        BuildMI(*BalTgtMBB, Pos, DL, TII->get(JROp)).addReg(Mips::AT);
+
+        if (Subtarget.isTargetNaCl()) {
+          BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::NOP));
+        } else
+          BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP)
+              .addReg(Mips::SP)
+              .addImm(8);
+
+        BalTgtMBB->rbegin()->bundleWithPred();
+      }
+    } else {
+      // Pre R6:
+      // $longbr:
+      //  daddiu $sp, $sp, -16
+      //  sd $ra, 0($sp)
+      //  daddiu $at, $zero, %hi($tgt - $baltgt)
+      //  dsll $at, $at, 16
+      //  bal $baltgt
+      //  daddiu $at, $at, %lo($tgt - $baltgt)
+      // $baltgt:
+      //  daddu $at, $ra, $at
+      //  ld $ra, 0($sp)
+      //  jr64 $at
+      //  daddiu $sp, $sp, 16
+      // $fallthrough:
+
+      // R6:
+      // $longbr:
+      //  daddiu $sp, $sp, -16
+      //  sd $ra, 0($sp)
+      //  daddiu $at, $zero, %hi($tgt - $baltgt)
+      //  dsll $at, $at, 16
+      //  daddiu $at, $at, %lo($tgt - $baltgt)
+      //  balc $baltgt
+      // $baltgt:
+      //  daddu $at, $ra, $at
+      //  ld $ra, 0($sp)
+      //  daddiu $sp, $sp, 16
+      //  jic $at, 0
+      // $fallthrough:
+
+      // We assume the branch is within-function, and that offset is within
+      // +/- 2GB.  High 32 bits will therefore always be zero.
+
+      // Note that this will work even if the offset is negative, because
+      // of the +1 modification that's added in that case.  For example, if the
+      // offset is -1MB (0xFFFFFFFFFFF00000), the computation for %higher is
+      //
+      // 0xFFFFFFFFFFF00000 + 0x80008000 = 0x000000007FF08000
+      //
+      // and the bits [47:32] are zero.  For %highest
+      //
+      // 0xFFFFFFFFFFF00000 + 0x800080008000 = 0x000080007FF08000
+      //
+      // and the bits [63:48] are zero.
+
+      Pos = LongBrMBB->begin();
+
+      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64)
+        .addReg(Mips::SP_64).addImm(-16);
+      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SD)).addReg(Mips::RA_64)
+        .addReg(Mips::SP_64).addImm(0);
+      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu),
+              Mips::AT_64).addReg(Mips::ZERO_64)
+                          .addMBB(TgtMBB, MipsII::MO_ABS_HI).addMBB(BalTgtMBB);
+      BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64)
+        .addReg(Mips::AT_64).addImm(16);
+
+      MachineInstrBuilder BalInstr =
+          BuildMI(*MF, DL, TII->get(BalOp)).addMBB(BalTgtMBB);
+      MachineInstrBuilder DADDiuInstr =
+          BuildMI(*MF, DL, TII->get(Mips::LONG_BRANCH_DADDiu), Mips::AT_64)
+              .addReg(Mips::AT_64)
+              .addMBB(TgtMBB, MipsII::MO_ABS_LO)
+              .addMBB(BalTgtMBB);
+      if (Subtarget.hasMips32r6()) {
+        LongBrMBB->insert(Pos, DADDiuInstr);
+        LongBrMBB->insert(Pos, BalInstr);
+      } else {
+        LongBrMBB->insert(Pos, BalInstr);
+        LongBrMBB->insert(Pos, DADDiuInstr);
+        LongBrMBB->rbegin()->bundleWithPred();
+      }
+
+      Pos = BalTgtMBB->begin();
+
+      BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDu), Mips::AT_64)
+        .addReg(Mips::RA_64).addReg(Mips::AT_64);
+      BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64)
+        .addReg(Mips::SP_64).addImm(0);
+
+      if (Subtarget.hasMips64r6() && !Subtarget.useIndirectJumpsHazard()) {
+        BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64)
+            .addReg(Mips::SP_64)
+            .addImm(16);
+        BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JIC64))
+            .addReg(Mips::AT_64)
+            .addImm(0);
+      } else {
+        unsigned JROp =
+            Subtarget.useIndirectJumpsHazard()
+                ? (Subtarget.hasMips32r6() ? Mips::JR_HB64_R6 : Mips::JR_HB64)
+                : Mips::JR64;
+        BuildMI(*BalTgtMBB, Pos, DL, TII->get(JROp)).addReg(Mips::AT_64);
+        BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64)
+            .addReg(Mips::SP_64)
+            .addImm(16);
+        BalTgtMBB->rbegin()->bundleWithPred();
+      }
+    }
+
+    assert(LongBrMBB->size() + BalTgtMBB->size() == LongBranchSeqSize);
+  } else {
+    // Pre R6:                  R6:
+    // $longbr:                 $longbr:
+    //  j $tgt                   bc $tgt
+    //  nop                     $fallthrough
+    // $fallthrough:
+    //
+    Pos = LongBrMBB->begin();
+    LongBrMBB->addSuccessor(TgtMBB);
+    if (Subtarget.hasMips32r6())
+      BuildMI(*LongBrMBB, Pos, DL,
+              TII->get(Subtarget.inMicroMipsMode() ? Mips::BC_MMR6 : Mips::BC))
+          .addMBB(TgtMBB);
+    else
+      MIBundleBuilder(*LongBrMBB, Pos)
+        .append(BuildMI(*MF, DL, TII->get(Mips::J)).addMBB(TgtMBB))
+        .append(BuildMI(*MF, DL, TII->get(Mips::NOP)));
+
+    assert(LongBrMBB->size() == LongBranchSeqSize);
+  }
+
+  if (I.Br->isUnconditionalBranch()) {
+    // Change branch destination.
+    assert(I.Br->getDesc().getNumOperands() == 1);
+    I.Br->RemoveOperand(0);
+    I.Br->addOperand(MachineOperand::CreateMBB(LongBrMBB));
+  } else
+    // Change branch destination and reverse condition.
+    replaceBranch(*MBB, I.Br, DL, &*FallThroughMBB);
+}
+
+static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) {
+  MachineBasicBlock &MBB = F.front();
+  MachineBasicBlock::iterator I = MBB.begin();
+  DebugLoc DL = MBB.findDebugLoc(MBB.begin());
+  BuildMI(MBB, I, DL, TII->get(Mips::LUi), Mips::V0)
+    .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI);
+  BuildMI(MBB, I, DL, TII->get(Mips::ADDiu), Mips::V0)
+    .addReg(Mips::V0).addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO);
+  MBB.removeLiveIn(Mips::V0);
+}
+
+bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) {
+  const MipsSubtarget &STI =
+      static_cast<const MipsSubtarget &>(F.getSubtarget());
+  const MipsInstrInfo *TII =
+      static_cast<const MipsInstrInfo *>(STI.getInstrInfo());
+
+  const TargetMachine& TM = F.getTarget();
+  IsPIC = TM.isPositionIndependent();
+  ABI = static_cast<const MipsTargetMachine &>(TM).getABI();
+
+  LongBranchSeqSize = IsPIC ? ((ABI.IsN64() || STI.isTargetNaCl()) ? 10 : 9)
+                          : (STI.hasMips32r6() ? 1 : 2);
+
+  if (STI.inMips16Mode() || !STI.enableLongBranchPass())
+    return false;
+  if (IsPIC && static_cast<const MipsTargetMachine &>(TM).getABI().IsO32() &&
+      F.getInfo<MipsFunctionInfo>()->globalBaseRegSet())
+    emitGPDisp(F, TII);
+
+  if (SkipLongBranch)
+    return true;
+
+  MF = &F;
+  initMBBInfo();
+
+  SmallVectorImpl<MBBInfo>::iterator I, E = MBBInfos.end();
+  bool EverMadeChange = false, MadeChange = true;
+
+  while (MadeChange) {
+    MadeChange = false;
+
+    for (I = MBBInfos.begin(); I != E; ++I) {
+      // Skip if this MBB doesn't have a branch or the branch has already been
+      // converted to a long branch.
+      if (!I->Br || I->HasLongBranch)
+        continue;
+
+      int64_t Offset = computeOffset(I->Br);
+
+      if (STI.isTargetNaCl()) {
+        // The offset calculation does not include sandboxing instructions
+        // that will be added later in the MC layer.  Since at this point we
+        // don't know the exact amount of code that "sandboxing" will add, we
+        // conservatively estimate that code will not grow more than 100%.
+        Offset *= 2;
+      }
+
+      // Check if offset fits into the immediate field of the branch.
+      if (!ForceLongBranch &&
+          TII->isBranchOffsetInRange(I->Br->getOpcode(), Offset))
+        continue;
+
+      I->HasLongBranch = true;
+      I->Size += LongBranchSeqSize * 4;
+      ++LongBranches;
+      EverMadeChange = MadeChange = true;
+    }
+  }
+
+  if (!EverMadeChange)
+    return true;
+
+  // Compute basic block addresses.
+  if (IsPIC) {
+    uint64_t Address = 0;
+
+    for (I = MBBInfos.begin(); I != E; Address += I->Size, ++I)
+      I->Address = Address;
+  }
+
+  // Do the expansion.
+  for (I = MBBInfos.begin(); I != E; ++I)
+    if (I->HasLongBranch)
+      expandToLongBranch(*I);
+
+  MF->RenumberBlocks();
+
+  return true;
+}
+
+/// createMipsLongBranchPass - Returns a pass that converts branches to long
+/// branches.
+FunctionPass *llvm::createMipsLongBranchPass() { return new MipsLongBranch(); }

Modified: llvm/trunk/lib/Target/Mips/MipsTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsTargetMachine.cpp?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsTargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsTargetMachine.cpp Mon May 21 04:38:52 2018
@@ -54,7 +54,7 @@ extern "C" void LLVMInitializeMipsTarget
   PassRegistry *PR = PassRegistry::getPassRegistry();
   initializeGlobalISel(*PR);
   initializeMipsDelaySlotFillerPass(*PR);
-  initializeMipsBranchExpansionPass(*PR);
+  initializeMipsLongBranchPass(*PR);
 }
 
 static std::string computeDataLayout(const Triple &TT, StringRef CPU,
@@ -290,20 +290,12 @@ MipsTargetMachine::getTargetTransformInf
 void MipsPassConfig::addPreEmitPass() {
   addPass(createMicroMipsSizeReductionPass());
 
-  // The delay slot filler pass can potientially create forbidden slot hazards
-  // for MIPSR6 and therefore it should go before MipsBranchExpansion pass.
+  // The delay slot filler and the long branch passes can potientially create
+  // forbidden slot/ hazards for MIPSR6 which the hazard schedule pass will
+  // fix. Any new pass must come before the hazard schedule pass.
   addPass(createMipsDelaySlotFillerPass());
-
-  // This pass expands branches and takes care about the forbidden slot hazards.
-  // Expanding branches may potentially create forbidden slot hazards for
-  // MIPSR6, and fixing such hazard may potentially break a branch by extending
-  // its offset out of range. That's why this pass combine these two tasks, and
-  // runs them alternately until one of them finishes without any changes. Only
-  // then we can be sure that all branches are expanded properly and no hazards
-  // exists.
-  // Any new pass should go before this pass.
-  addPass(createMipsBranchExpansion());
-
+  addPass(createMipsLongBranchPass());
+  addPass(createMipsHazardSchedule());
   addPass(createMipsConstantIslandPass());
 }
 

Removed: llvm/trunk/test/CodeGen/Mips/branch-relaxation-with-hazard.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/branch-relaxation-with-hazard.ll?rev=332836&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/branch-relaxation-with-hazard.ll (original)
+++ llvm/trunk/test/CodeGen/Mips/branch-relaxation-with-hazard.ll (removed)
@@ -1,64 +0,0 @@
-; RUN: llc -O0 -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -relocation-model=pic < %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-PIC
-; RUN: llc -O0 -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -relocation-model=static < %s -o - | FileCheck %s --check-prefixes=CHECK-STATIC
-
-declare i32 @boo(...)
-declare i32 @foo(...)
-
-define i32 @main(i32 signext %argc, i8** %argv) {
-; CHECK: main:
-; CHECK: # %bb.1:
-; CHECK-PIC: addiu
-; CHECK-PIC: sw
-; CHECK-PIC: lui
-; CHECK-PIC: addiu
-; CHECK-PIC: balc
-; CHECK-PIC: addu
-; CHECK-PIC: lw
-; CHECK-PIC: addiu
-; CHECK-PIC: jrc
-; CHECK-PIC: bc
-; CHECK-PIC: bnezc
-; CHECK-PIC: nop
-; CHECK-PIC: bc
-
-; CHECK-STATIC: bc
-; CHECK-STATIC: j
-; CHECK-STATIC: bnezc
-; CHECK-STATIC: nop
-; CHECK-STATIC: j
-entry:
-  %retval = alloca i32, align 4
-  %argc.addr = alloca i32, align 4
-  %argv.addr = alloca i8**, align 4
-  store i32 0, i32* %retval, align 4
-  store i32 %argc, i32* %argc.addr, align 4
-  store i8** %argv, i8*** %argv.addr, align 4
-  %0 = load i32, i32* %argc.addr, align 4
-  %cmp = icmp sgt i32 %0, 1
-  br i1 %cmp, label %if.then, label %if.end4
-
-if.then:
-  %1 = load i32, i32* %argc.addr, align 4
-  %cmp1 = icmp sgt i32 %1, 3
-  br i1 %cmp1, label %if.then2, label %if.end
-
-if.then2:
-  %call = call i32 bitcast (i32 (...)* @boo to i32 ()*)()
-  store i32 %call, i32* %retval, align 4
-  br label %return
-
-if.end:
-  call void asm sideeffect ".space 4194228", "~{$1}"()
-  %call3 = call i32 bitcast (i32 (...)* @foo to i32 ()*)()
-  store i32 %call3, i32* %retval, align 4
-  br label %return
-
-if.end4:
-  store i32 0, i32* %retval, align 4
-  br label %return
-
-return:
-  %2 = load i32, i32* %retval, align 4
-  ret i32 %2
-
-}

Modified: llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-micromips.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-micromips.mir?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-micromips.mir (original)
+++ llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-micromips.mir Mon May 21 04:38:52 2018
@@ -1,6 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=mips-mti-linux-gnu -mattr=+micromips %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion | FileCheck %s --check-prefix=MM
-# RUN: llc -mtriple=mips-mti-linux-gnu -mattr=+micromips %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion -relocation-model=pic | FileCheck %s --check-prefix=PIC
+# RUN: llc -mtriple=mips-mti-linux-gnu -mattr=+micromips %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch | FileCheck %s --check-prefix=MM
+# RUN: llc -mtriple=mips-mti-linux-gnu -mattr=+micromips %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch -relocation-model=pic | FileCheck %s --check-prefix=PIC
 
 # Test the long branch expansion of various branches
 

Modified: llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-micromipsr6.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-micromipsr6.mir?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-micromipsr6.mir (original)
+++ llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-micromipsr6.mir Mon May 21 04:38:52 2018
@@ -1,6 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -mattr=+micromips %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion | FileCheck %s --check-prefix=MM
-# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -mattr=+micromips %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion -relocation-model=pic | FileCheck %s --check-prefix=PIC
+# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -mattr=+micromips %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch | FileCheck %s --check-prefix=MM
+# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -mattr=+micromips %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch -relocation-model=pic | FileCheck %s --check-prefix=PIC
 
 # Test the long branch expansion of various branches
 

Modified: llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-mips.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-mips.mir?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-mips.mir (original)
+++ llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-mips.mir Mon May 21 04:38:52 2018
@@ -1,6 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=mips-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion | FileCheck %s --check-prefix=MIPS
-# RUN: llc -mtriple=mips-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion -relocation-model=pic | FileCheck %s --check-prefix=PIC
+# RUN: llc -mtriple=mips-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch | FileCheck %s --check-prefix=MIPS
+# RUN: llc -mtriple=mips-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch -relocation-model=pic | FileCheck %s --check-prefix=PIC
 # Test the long branch expansion of various branches
 
 --- |

Modified: llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-mipsr6.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-mipsr6.mir?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-mipsr6.mir (original)
+++ llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-fp-mipsr6.mir Mon May 21 04:38:52 2018
@@ -1,6 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion | FileCheck %s --check-prefix=R6
-# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion -relocation-model=pic | FileCheck %s --check-prefix=PIC
+# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch | FileCheck %s --check-prefix=R6
+# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch -relocation-model=pic | FileCheck %s --check-prefix=PIC
 
 # Test the long branch expansion of various branches
 

Modified: llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-microMIPS.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-microMIPS.mir?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-microMIPS.mir (original)
+++ llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-microMIPS.mir Mon May 21 04:38:52 2018
@@ -1,6 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=mips-mti-linux-gnu -mattr=+micromips -o - %s -start-before mips-delay-slot-filler -stop-after mips-branch-expansion | FileCheck %s --check-prefix=MM
-# RUN: llc -mtriple=mips-mti-linux-gnu -mattr=+micromips -o - %s -start-before mips-delay-slot-filler -stop-after mips-branch-expansion -relocation-model=pic | FileCheck %s --check-prefix=PIC
+# RUN: llc -mtriple=mips-mti-linux-gnu -mattr=+micromips -o - %s -start-before mips-delay-slot-filler -stop-after mips-long-branch | FileCheck %s --check-prefix=MM
+# RUN: llc -mtriple=mips-mti-linux-gnu -mattr=+micromips -o - %s -start-before mips-delay-slot-filler -stop-after mips-long-branch -relocation-model=pic | FileCheck %s --check-prefix=PIC
 
 # Test the long branch expansion of various branches
 

Modified: llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-micromipsr6.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-micromipsr6.mir?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-micromipsr6.mir (original)
+++ llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-micromipsr6.mir Mon May 21 04:38:52 2018
@@ -1,6 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -mattr=+micromips -o - %s -start-before mips-delay-slot-filler -stop-after mips-branch-expansion | FileCheck %s --check-prefix=MMR6
-# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -mattr=+micromips -o - %s -start-before mips-delay-slot-filler -stop-after mips-branch-expansion -relocation-model=pic | FileCheck %s --check-prefix=PIC
+# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -mattr=+micromips -o - %s -start-before mips-delay-slot-filler -stop-after mips-long-branch | FileCheck %s --check-prefix=MMR6
+# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -mattr=+micromips -o - %s -start-before mips-delay-slot-filler -stop-after mips-long-branch -relocation-model=pic | FileCheck %s --check-prefix=PIC
 
 # Test the long branch expansion of various branches
 

Modified: llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mips64.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mips64.mir?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mips64.mir (original)
+++ llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mips64.mir Mon May 21 04:38:52 2018
@@ -1,6 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=mips64-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion | FileCheck %s --check-prefix=MIPS64
-# RUN: llc -mtriple=mips64-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion -relocation-model=pic | FileCheck %s --check-prefix=PIC
+# RUN: llc -mtriple=mips64-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch | FileCheck %s --check-prefix=MIPS64
+# RUN: llc -mtriple=mips64-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch -relocation-model=pic | FileCheck %s --check-prefix=PIC
 
 # Test the long branch expansion of various branches
 

Modified: llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mips64r6.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mips64r6.mir?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mips64r6.mir (original)
+++ llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mips64r6.mir Mon May 21 04:38:52 2018
@@ -1,6 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=mips64-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion | FileCheck %s --check-prefix=MIPS64
-# RUN: llc -mtriple=mips64-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion -relocation-model=pic | FileCheck %s --check-prefix=PIC
+# RUN: llc -mtriple=mips64-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch | FileCheck %s --check-prefix=MIPS64
+# RUN: llc -mtriple=mips64-mti-linux-gnu %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch -relocation-model=pic | FileCheck %s --check-prefix=PIC
 
 # Test the long branch expansion of various branches
 

Modified: llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mipsr6.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mipsr6.mir?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mipsr6.mir (original)
+++ llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int-mipsr6.mir Mon May 21 04:38:52 2018
@@ -1,6 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -o - %s -start-before mips-delay-slot-filler -stop-after mips-branch-expansion | FileCheck %s --check-prefix=R6
-# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -o - %s -start-before mips-delay-slot-filler -stop-after mips-branch-expansion -relocation-model=pic | FileCheck %s --check-prefix=PIC
+# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -o - %s -start-before mips-delay-slot-filler -stop-after mips-long-branch | FileCheck %s --check-prefix=R6
+# RUN: llc -mtriple=mips-img-linux-gnu -mcpu=mips32r6 -o - %s -start-before mips-delay-slot-filler -stop-after mips-long-branch -relocation-model=pic | FileCheck %s --check-prefix=PIC
 
 # Test the long branch expansion of various branches
 

Modified: llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int.mir?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int.mir (original)
+++ llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-int.mir Mon May 21 04:38:52 2018
@@ -1,6 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=mips-mti-linux-gnu -o - %s -start-before mips-delay-slot-filler -stop-after mips-branch-expansion | FileCheck %s --check-prefix=MIPS
-# RUN: llc -mtriple=mips-mti-linux-gnu -o - %s -start-before mips-delay-slot-filler -stop-after mips-branch-expansion -relocation-model=pic | FileCheck %s --check-prefix=PIC
+# RUN: llc -mtriple=mips-mti-linux-gnu -o - %s -start-before mips-delay-slot-filler -stop-after mips-long-branch | FileCheck %s --check-prefix=MIPS
+# RUN: llc -mtriple=mips-mti-linux-gnu -o - %s -start-before mips-delay-slot-filler -stop-after mips-long-branch -relocation-model=pic | FileCheck %s --check-prefix=PIC
 
 # Test the long branch expansion of various branches
 

Modified: llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-msa.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-msa.mir?rev=332837&r1=332836&r2=332837&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-msa.mir (original)
+++ llvm/trunk/test/CodeGen/Mips/longbranch/branch-limits-msa.mir Mon May 21 04:38:52 2018
@@ -1,6 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=mips64-mti-linux-gnu -mcpu=mips64r5 -mattr=+fp64,+msa %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion | FileCheck %s --check-prefix=MSA
-# RUN: llc -mtriple=mips64-mti-linux-gnu -mcpu=mips64r5 -mattr=+fp64,+msa %s -o - -start-before mips-delay-slot-filler -stop-after mips-branch-expansion -relocation-model=pic | FileCheck %s --check-prefix=PIC
+# RUN: llc -mtriple=mips64-mti-linux-gnu -mcpu=mips64r5 -mattr=+fp64,+msa %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch | FileCheck %s --check-prefix=MSA
+# RUN: llc -mtriple=mips64-mti-linux-gnu -mcpu=mips64r5 -mattr=+fp64,+msa %s -o - -start-before mips-delay-slot-filler -stop-after mips-long-branch -relocation-model=pic | FileCheck %s --check-prefix=PIC
 
 # Test the long branch expansion of various branches
 




More information about the llvm-commits mailing list