diff --git a/bolt/lib/Passes/LongJmp.cpp b/bolt/lib/Passes/LongJmp.cpp index c483f70a836ee..0b2d00300f46b 100644 --- a/bolt/lib/Passes/LongJmp.cpp +++ b/bolt/lib/Passes/LongJmp.cpp @@ -324,9 +324,8 @@ uint64_t LongJmpPass::tentativeLayoutRelocColdPart( uint64_t LongJmpPass::tentativeLayoutRelocMode( const BinaryContext &BC, std::vector &SortedFunctions, uint64_t DotAddress) { - // Compute hot cold frontier - uint32_t LastHotIndex = -1u; + int64_t LastHotIndex = -1u; uint32_t CurrentIndex = 0; if (opts::HotFunctionsAtEnd) { for (BinaryFunction *BF : SortedFunctions) { @@ -351,19 +350,20 @@ uint64_t LongJmpPass::tentativeLayoutRelocMode( // Hot CurrentIndex = 0; bool ColdLayoutDone = false; + auto runColdLayout = [&]() { + DotAddress = tentativeLayoutRelocColdPart(BC, SortedFunctions, DotAddress); + ColdLayoutDone = true; + if (opts::HotFunctionsAtEnd) + DotAddress = alignTo(DotAddress, opts::AlignText); + }; for (BinaryFunction *Func : SortedFunctions) { if (!BC.shouldEmit(*Func)) { HotAddresses[Func] = Func->getAddress(); continue; } - if (!ColdLayoutDone && CurrentIndex >= LastHotIndex) { - DotAddress = - tentativeLayoutRelocColdPart(BC, SortedFunctions, DotAddress); - ColdLayoutDone = true; - if (opts::HotFunctionsAtEnd) - DotAddress = alignTo(DotAddress, opts::AlignText); - } + if (!ColdLayoutDone && CurrentIndex >= LastHotIndex) + runColdLayout(); DotAddress = alignTo(DotAddress, Func->getMinAlignment()); uint64_t Pad = @@ -382,6 +382,11 @@ uint64_t LongJmpPass::tentativeLayoutRelocMode( DotAddress += Func->estimateConstantIslandSize(); ++CurrentIndex; } + + // Ensure that tentative code layout always runs for cold blocks. + if (!ColdLayoutDone) + runColdLayout(); + // BBs for (BinaryFunction *Func : SortedFunctions) tentativeBBLayout(*Func); diff --git a/bolt/test/AArch64/split-funcs-lite.s b/bolt/test/AArch64/split-funcs-lite.s new file mode 100644 index 0000000000000..5f95eea17ae75 --- /dev/null +++ b/bolt/test/AArch64/split-funcs-lite.s @@ -0,0 +1,27 @@ +# This test checks that tentative code layout for cold blocks always runs. +# It commonly happens when using lite mode with split functions. + +# REQUIRES: system-linux, asserts + +# RUN: %clang %cflags -o %t %s +# RUN: %clang %s %cflags -Wl,-q -o %t +# RUN: link_fdata --no-lbr %s %t %t.fdata +# RUN: llvm-bolt %t -o %t.bolt --data %t.fdata -split-functions \ +# RUN: -debug 2>&1 | FileCheck %s + + .text + .globl foo + .type foo, %function +foo: +.entry_bb: +# FDATA: 1 foo #.entry_bb# 10 + cmp x0, #0 + b.eq .Lcold_bb1 + ret +.Lcold_bb1: + ret + +## Force relocation mode. +.reloc 0, R_AARCH64_NONE + +# CHECK: foo{{.*}} cold tentative: {{.*}}