From 82095bd5ed504fe26553b337d15131db530e768b Mon Sep 17 00:00:00 2001 From: Huan Nguyen Date: Fri, 10 Jun 2022 15:48:13 -0700 Subject: [PATCH] [BOLT] Mark fragments related to split jump table as non-simple Mark fragments related to split jump table as non-simple. A function could be splitted into hot and cold fragments. A split jump table is challenging for correctly reconstructing control flow graphs, so it was marked as ignored. This update marks those fragments as non-simple, allowing them to be printed and partial control flow graph construction. Test Plan: ``` llvm-lit -a tools/bolt/test/X86/split-func-icf.s ``` This test has two functions (main, main2), each has a jump table target to the same cold portion main2.cold.1(*2). We try to print out only this cold portion. If it is ignored, it cannot be printed. If it is non-simple, it can be printed. We verify that it can be printed. Reviewed By: Amir Differential Revision: https://reviews.llvm.org/D127464 --- bolt/lib/Core/BinaryContext.cpp | 6 ++++-- bolt/lib/Rewrite/RewriteInstance.cpp | 3 ++- bolt/test/X86/split-func-icf.s | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index f5fc26da95d3..db66a73dfa05 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -715,13 +715,15 @@ void BinaryContext::skipMarkedFragments() { "internal error in traversing function fragments"); if (opts::Verbosity >= 1) errs() << "BOLT-WARNING: Ignoring " << BF->getPrintName() << '\n'; - BF->setIgnored(); + BF->setSimple(false); + BF->setHasSplitJumpTable(true); + std::for_each(BF->Fragments.begin(), BF->Fragments.end(), addToWorklist); std::for_each(BF->ParentFragments.begin(), BF->ParentFragments.end(), addToWorklist); } if (!FragmentsToSkip.empty()) - errs() << "BOLT-WARNING: ignored " << FragmentsToSkip.size() << " function" + errs() << "BOLT-WARNING: skipped " << FragmentsToSkip.size() << " function" << (FragmentsToSkip.size() == 1 ? "" : "s") << " due to cold fragments\n"; FragmentsToSkip.clear(); diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index b4e961306423..41055d23ff65 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -2925,7 +2925,8 @@ void RewriteInstance::disassembleFunctions() { continue; if (!Function.isSimple()) { - assert((!BC->HasRelocations || Function.getSize() == 0) && + assert((!BC->HasRelocations || Function.getSize() == 0 || + Function.hasSplitJumpTable()) && "unexpected non-simple function in relocation mode"); continue; } diff --git a/bolt/test/X86/split-func-icf.s b/bolt/test/X86/split-func-icf.s index 00fe62860d46..eac4174fefd5 100644 --- a/bolt/test/X86/split-func-icf.s +++ b/bolt/test/X86/split-func-icf.s @@ -8,15 +8,17 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: llvm-strip --strip-unneeded %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -# RUN: llvm-bolt %t.exe -o %t.out -lite=0 -v=1 2>&1 | FileCheck %s +# RUN: llvm-bolt %t.exe -o %t.out -v=1 --print-only=main2.cold.1 --print-disasm 2>&1 | FileCheck %s # CHECK-NOT: unclaimed PC-relative relocations left in data # CHECK-DAG: BOLT-INFO: marking main2.cold.1(*2) as a fragment of main # CHECK-DAG: BOLT-INFO: marking main2.cold.1(*2) as a fragment of main2 +# CHECK: Binary Function "main2.cold.1(*2)" after disassembly +# CHECK: End of Function "main2.cold.1(*2)" # CHECK-DAG: BOLT-WARNING: Ignoring main2 # CHECK-DAG: BOLT-WARNING: Ignoring main # CHECK-DAG: BOLT-WARNING: Ignoring main2.cold.1(*2) -# CHECK: BOLT-WARNING: ignored 3 functions due to cold fragments +# CHECK: BOLT-WARNING: skipped 3 functions due to cold fragments .text .globl main .type main, %function