diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h --- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -595,6 +595,11 @@ llvm_unreachable("target did not implement"); } + /// \returns the cross section branch distance needed for the architecture. + virtual unsigned getCrossSectionBranchDistance() const { + llvm_unreachable("target did not implement"); + } + /// \returns The block that branch instruction \p MI jumps to. virtual MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const { llvm_unreachable("target did not implement"); diff --git a/llvm/lib/CodeGen/BranchRelaxation.cpp b/llvm/lib/CodeGen/BranchRelaxation.cpp --- a/llvm/lib/CodeGen/BranchRelaxation.cpp +++ b/llvm/lib/CodeGen/BranchRelaxation.cpp @@ -43,6 +43,11 @@ namespace { +cl::opt CrossSection("cross-section-branch-relaxation", + cl::init(false), cl::Hidden, + cl::desc("Use maximum distance when considering cross-section + jumps during branch relaxation.")); + class BranchRelaxation : public MachineFunctionPass { /// BasicBlockInfo - Information about the offset and size of a single /// basic block. @@ -77,6 +82,9 @@ } }; + // Consider cross section distances + bool CrossSection; + SmallVector BlockInfo; std::unique_ptr RS; LivePhysRegs LiveRegs; @@ -242,7 +250,7 @@ /// an unconditional branch. Update data structures and renumber blocks to /// account for this change and returns the newly created block. MachineBasicBlock *BranchRelaxation::splitBlockBeforeInstr(MachineInstr &MI, - MachineBasicBlock *DestBB) { + MachineBasicBlock *DestBB) { MachineBasicBlock *OrigBB = MI.getParent(); // Create a new MBB for the code after the OrigBB. @@ -300,7 +308,13 @@ int64_t BrOffset = getInstrOffset(MI); int64_t DestOffset = BlockInfo[DestBB.getNumber()].Offset; - if (TII->isBranchOffsetInRange(MI.getOpcode(), DestOffset - BrOffset)) + const MachineBasicBlock *SrcBB = MI.getParent(); + bool CSPlacement = + CrossSection && (SrcBB->getSectionID() != DestBB.getSectionID()); + + if (TII->isBranchOffsetInRange( + MI.getOpcode(), CSPlacement ? TII->getCrossSectionBranchDistance() + : DestOffset - BrOffset)) return true; LLVM_DEBUG(dbgs() << "Out of range branch to destination " @@ -493,8 +507,13 @@ MachineBasicBlock *RestoreBB = createNewBlockAfter(MF->back(), DestBB->getBasicBlock()); + bool CSPlacement = + CrossSection && (BranchBB->getSectionID() != DestBB->getSectionID()); TII->insertIndirectBranch(*BranchBB, *DestBB, *RestoreBB, DL, - DestOffset - SrcOffset, RS.get()); + CSPlacement ? TII->getCrossSectionBranchDistance() + : DestOffset - SrcOffset, + RS.get()); +\ BlockInfo[BranchBB->getNumber()].Size = computeBlockSize(*BranchBB); adjustBlockOffsets(*MBB); diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h @@ -207,6 +207,8 @@ bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override; + unsigned getCrossSectionBranchDistance() const override; + MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override; bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -208,6 +208,10 @@ return isIntN(Bits, BrOffset / 4); } +unsigned AArch64InstrInfo::getCrossSectionBranchDistance() const { + return 128*1024*1024-1; +} + MachineBasicBlock * AArch64InstrInfo::getBranchDestBlock(const MachineInstr &MI) const { switch (MI.getOpcode()) {