diff --git a/llvm/lib/CodeGen/BasicBlockSections.cpp b/llvm/lib/CodeGen/BasicBlockSections.cpp --- a/llvm/lib/CodeGen/BasicBlockSections.cpp +++ b/llvm/lib/CodeGen/BasicBlockSections.cpp @@ -128,6 +128,24 @@ "into clusters of basic blocks.", false, false) +/// Basic blocks with an explicit unconditional branch to its fallthrough block +/// do not need an extra unconditional branch. +static bool needInsertUncondBranch(const MachineBasicBlock &MBB) { + auto B = MBB.terminators().begin(), E = MBB.end(), I = B; + if (I == E) + return true; + + if (I->isUnconditionalBranch()) + return false; + + while (I != E) { + if (I->isUnconditionalBranch()) + return false; + I++; + } + return true; +} + // This function updates and optimizes the branching instructions of every basic // block in a given function to account for changes in the layout. static void updateBranches( @@ -141,10 +159,13 @@ // If this block had a fallthrough before we need an explicit unconditional // branch to that block if either // 1- the block ends a section, which means its next block may be - // reorderd by the linker, or + // reorderd by the linker, // 2- the fallthrough block is not adjacent to the block in the new - // order. - if (FTMBB && (MBB.isEndSection() || &*NextMBBI != FTMBB)) + // order, or + // 3- the terminator of the block is an unconditional branch to its + // fallthrough. + if (FTMBB && (MBB.isEndSection() || &*NextMBBI != FTMBB) && + needInsertUncondBranch(MBB)) TII->insertUnconditionalBranch(MBB, FTMBB, MBB.findBranchDebugLoc()); // We do not optimize branches for machine basic blocks ending sections, as diff --git a/llvm/test/CodeGen/X86/basic-block-sections_2.ll b/llvm/test/CodeGen/X86/basic-block-sections_2.ll --- a/llvm/test/CodeGen/X86/basic-block-sections_2.ll +++ b/llvm/test/CodeGen/X86/basic-block-sections_2.ll @@ -12,11 +12,18 @@ ;; ; __cxx_global_var_init has multiple basic blocks which will produce many sections. ; RUN: llc < %s -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=all -unique-basic-block-section-names | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=all -O0 -unique-basic-block-section-names | FileCheck %s --check-prefix=REDUNDANT ; CHECK-LABEL: __cxx_global_var_init: ; CHECK-LABEL: __cxx_global_var_init.__part.1: ; CHECK-LABEL: __cxx_global_var_init.1: +; REDUNDANT-LABEL: __cxx_global_var_init: +; REDUNDANT: jmp __cxx_global_var_init.__part.2 +; REDUNDANT-NOT: jmp __cxx_global_var_init.__part.1 +; REDUNDANT-LABEL: __cxx_global_var_init.__part.1: +; REDUNDANT-LABEL: __cxx_global_var_init.1: + %class.A = type { i8 } $_ZN1AC2Eb = comdat any