diff --git a/bolt/include/bolt/Passes/ReorderFunctions.h b/bolt/include/bolt/Passes/ReorderFunctions.h --- a/bolt/include/bolt/Passes/ReorderFunctions.h +++ b/bolt/include/bolt/Passes/ReorderFunctions.h @@ -39,6 +39,8 @@ const char *getName() const override { return "reorder-functions"; } void runOnFunctions(BinaryContext &BC) override; + + static std::vector readFunctionOrderFile(); }; } // namespace bolt diff --git a/bolt/lib/Passes/ReorderFunctions.cpp b/bolt/lib/Passes/ReorderFunctions.cpp --- a/bolt/lib/Passes/ReorderFunctions.cpp +++ b/bolt/lib/Passes/ReorderFunctions.cpp @@ -243,9 +243,7 @@ TotalCalls2MB, 100 * TotalCalls2MB / TotalCalls); } -namespace { - -std::vector readFunctionOrderFile() { +std::vector ReorderFunctions::readFunctionOrderFile() { std::vector FunctionNames; std::ifstream FuncsFile(opts::FunctionOrderFile, std::ios::in); if (!FuncsFile) { @@ -259,8 +257,6 @@ return FunctionNames; } -} - void ReorderFunctions::runOnFunctions(BinaryContext &BC) { auto &BFs = BC.getBinaryFunctions(); if (opts::ReorderFunctions != RT_NONE && diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -2756,6 +2756,13 @@ LiteThresholdExecCount = std::max( LiteThresholdExecCount, static_cast(opts::LiteThresholdCount)); + StringSet<> ReorderFunctionsUserSet; + if (opts::ReorderFunctions == ReorderFunctions::RT_USER) { + for (const std::string &Function : + ReorderFunctions::readFunctionOrderFile()) + ReorderFunctionsUserSet.insert(Function); + } + uint64_t NumFunctionsToProcess = 0; auto shouldProcess = [&](const BinaryFunction &Function) { if (opts::MaxFunctions && NumFunctionsToProcess > opts::MaxFunctions) @@ -2781,6 +2788,15 @@ return false; if (opts::Lite) { + // Forcibly include functions specified in the -function-order file. + if (opts::ReorderFunctions == ReorderFunctions::RT_USER) { + Optional Match = Function.forEachName([&](StringRef Name) { + return ReorderFunctionsUserSet.contains(Name); + }); + if (Match.has_value()) + return true; + } + if (ProfileReader && !ProfileReader->mayHaveProfileData(Function)) return false; diff --git a/bolt/test/X86/Inputs/order-lite.txt b/bolt/test/X86/Inputs/order-lite.txt new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/order-lite.txt @@ -0,0 +1 @@ +main diff --git a/bolt/test/X86/function-order-lite.s b/bolt/test/X86/function-order-lite.s new file mode 100644 --- /dev/null +++ b/bolt/test/X86/function-order-lite.s @@ -0,0 +1,35 @@ +# Check that functions listed in -function-order list take precedence over +# lite mode function filtering. + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: link_fdata %s %t.o %t.fdata +# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe --data %t.fdata --lite --reorder-functions=user \ +# RUN: --function-order=%p/Inputs/order-lite.txt -o %t -print-all 2>&1 \ +# RUN: | FileCheck %s + +# CHECK: 1 out of 2 functions in the binary (50.0%) have non-empty execution profile +# CHECK: Binary Function "main" after reorder-functions + + .globl main + .type main, %function +main: + .cfi_startproc +.LBB06: + callq testfunc + retq + .cfi_endproc +.size main, .-main + + .globl testfunc + .type testfunc, %function +testfunc: +# FDATA: 0 [unknown] 0 1 testfunc 0 1 0 + .cfi_startproc + pushq %rbp + movq %rsp, %rbp + movl $0x0, %eax + popq %rbp + retq + .cfi_endproc +.size testfunc, .-testfunc