Add verbosity level and clean up stream usage.

Summary:
I've added a verbosity level to help keep the BOLT spewage to a minimum.
The default level is pretty terse now, level 1 is closer to the original,
I've saved level 2 for the noisiest of messages.  Error messages should
never be suppressed by the verbosity level only warnings and info messages.

The rational behind stream usage is as follows:
outs() for info and debugging controlled by command line flags.
errs() for errors and warnings.
dbgs() for output within DEBUG().

With the exception of a few of the level 2 messages I don't have any strong feelings about the others.

(cherry picked from FBD3814259)
This commit is contained in:
Bill Nell 2016-09-02 14:15:29 -07:00 committed by Maksim Panchenko
parent 43acb6a28a
commit c27a6a5c63
7 changed files with 329 additions and 208 deletions

View File

@ -95,17 +95,17 @@ bool BinaryBasicBlock::analyzeBranch(const MCInstrAnalysis &MIA,
}
void BinaryBasicBlock::dump(BinaryContext& BC) const {
if (Label) dbgs() << Label->getName() << ":\n";
BC.printInstructions(dbgs(), Instructions.begin(), Instructions.end(), Offset);
dbgs() << "preds:";
if (Label) outs() << Label->getName() << ":\n";
BC.printInstructions(outs(), Instructions.begin(), Instructions.end(), Offset);
outs() << "preds:";
for (auto itr = pred_begin(); itr != pred_end(); ++itr) {
dbgs() << " " << (*itr)->getName();
outs() << " " << (*itr)->getName();
}
dbgs() << "\nsuccs:";
outs() << "\nsuccs:";
for (auto itr = succ_begin(); itr != succ_end(); ++itr) {
dbgs() << " " << (*itr)->getName();
outs() << " " << (*itr)->getName();
}
dbgs() << "\n";
outs() << "\n";
}
} // namespace bolt

View File

@ -34,12 +34,12 @@
#undef DEBUG_TYPE
#define DEBUG_TYPE "bolt"
namespace llvm {
namespace bolt {
using namespace llvm;
namespace opts {
extern cl::opt<unsigned> Verbosity;
static cl::opt<bool>
AgressiveSplitting("split-all-cold",
cl::desc("outline as many cold basic blocks as possible"),
@ -53,6 +53,9 @@ DotToolTipCode("dot-tooltip-code",
} // namespace opts
namespace llvm {
namespace bolt {
// Temporary constant.
//
// TODO: move to architecture-specific file together with the code that is
@ -380,8 +383,10 @@ bool BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
return false;
}
if (TargetAddress == 0) {
errs() << "BOLT-WARNING: rip-relative operand is zero in function "
<< *this << ". Ignoring function.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: rip-relative operand is zero in function "
<< *this << ". Ignoring function.\n";
}
return false;
}
@ -477,9 +482,11 @@ bool BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
// No section - possibly an absolute address. Since we don't allow
// internal function addresses to escape the function scope - we
// consider it a tail call.
errs() << "BOLT-WARNING: no section for address 0x"
<< Twine::utohexstr(ArrayStart) << " referenced from function "
<< *this << '\n';
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: no section for address 0x"
<< Twine::utohexstr(ArrayStart) << " referenced from function "
<< *this << '\n';
}
return IndirectBranchType::POSSIBLE_TAIL_CALL;
}
auto &Section = *SectionOrError;
@ -515,10 +522,12 @@ bool BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
nulls(),
nulls())) {
// Ignore this function. Skip to the next one.
errs() << "BOLT-WARNING: unable to disassemble instruction at offset 0x"
<< Twine::utohexstr(Offset) << " (address 0x"
<< Twine::utohexstr(AbsoluteInstrAddr) << ") in function "
<< *this << '\n';
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: unable to disassemble instruction at offset 0x"
<< Twine::utohexstr(Offset) << " (address 0x"
<< Twine::utohexstr(AbsoluteInstrAddr) << ") in function "
<< *this << '\n';
}
IsSimple = false;
break;
}
@ -547,9 +556,11 @@ bool BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
TargetSymbol = getSymbol();
} else {
// Possibly an old-style PIC code
errs() << "BOLT: internal call detected at 0x"
<< Twine::utohexstr(AbsoluteInstrAddr)
<< " in function " << *this << ". Skipping.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: internal call detected at 0x"
<< Twine::utohexstr(AbsoluteInstrAddr)
<< " in function " << *this << ". Skipping.\n";
}
IsSimple = false;
}
}
@ -560,7 +571,7 @@ bool BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
TargetSymbol = getOrCreateLocalLabel(TargetAddress);
} else {
BC.InterproceduralReferences.insert(TargetAddress);
if (!IsCall && Size == 2) {
if (opts::Verbosity >= 2 && !IsCall && Size == 2) {
errs() << "BOLT-WARNING: relaxed tail call detected at 0x"
<< Twine::utohexstr(AbsoluteInstrAddr)
<< " in function " << *this
@ -574,7 +585,8 @@ bool BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
// Assign proper opcode for tail calls, so that they could be
// treated as calls.
if (!IsCall) {
if (!MIA->convertJmpToTailCall(Instruction)) {
if (opts::Verbosity >= 2 &&
!MIA->convertJmpToTailCall(Instruction)) {
assert(IsCondBranch && "unknown tail call instruction");
errs() << "BOLT-WARNING: conditional tail call detected in "
<< "function " << *this << " at 0x"
@ -594,8 +606,10 @@ bool BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
// from the libraries. In reality more often than not it is
// unreachable code, but we don't know it and have to emit calls
// to 0 which make LLVM JIT unhappy.
errs() << "BOLT-WARNING: Function " << *this
<< " has a call to address zero. Ignoring function.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: Function " << *this
<< " has a call to address zero. Ignoring function.\n";
}
IsSimple = false;
}
}
@ -638,9 +652,11 @@ bool BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
// Indirect call. We only need to fix it if the operand is RIP-relative
if (IsSimple && MIA->hasRIPOperand(Instruction)) {
if (!handleRIPOperand(Instruction, AbsoluteInstrAddr, Size)) {
errs() << "BOLT-WARNING: cannot handle RIP operand at 0x"
<< Twine::utohexstr(AbsoluteInstrAddr)
<< ". Skipping function " << *this << ".\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: cannot handle RIP operand at 0x"
<< Twine::utohexstr(AbsoluteInstrAddr)
<< ". Skipping function " << *this << ".\n";
}
IsSimple = false;
}
}
@ -648,9 +664,11 @@ bool BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
} else {
if (MIA->hasRIPOperand(Instruction)) {
if (!handleRIPOperand(Instruction, AbsoluteInstrAddr, Size)) {
errs() << "BOLT-WARNING: cannot handle RIP operand at 0x"
<< Twine::utohexstr(AbsoluteInstrAddr)
<< ". Skipping function " << *this << ".\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: cannot handle RIP operand at 0x"
<< Twine::utohexstr(AbsoluteInstrAddr)
<< ". Skipping function " << *this << ".\n";
}
IsSimple = false;
}
}
@ -1217,7 +1235,7 @@ void BinaryFunction::evaluateProfileData(const FuncBranchData &BranchData) {
(float) (LocalProfileBranches.size() - OrphanBranches.size()) /
(float) LocalProfileBranches.size();
if (!OrphanBranches.empty()) {
if (opts::Verbosity >= 2 && !OrphanBranches.empty()) {
errs() << "BOLT-WARNING: profile branches match only "
<< format("%.1f%%", ProfileMatchRatio * 100.0f) << " ("
<< (LocalProfileBranches.size() - OrphanBranches.size()) << '/'
@ -1317,8 +1335,8 @@ void BinaryFunction::inferFallThroughCounts() {
Inferred = BBExecCount - TotalReportedJumps;
DEBUG({
if (BBExecCount < TotalReportedJumps)
dbgs()
if (opts::Verbosity >= 1 && BBExecCount < TotalReportedJumps)
errs()
<< "BOLT-WARNING: Fall-through inference is slightly inconsistent. "
"exec frequency is less than the outgoing edges frequency ("
<< BBExecCount << " < " << ReportedBranches
@ -1521,9 +1539,11 @@ bool BinaryFunction::fixCFIState() {
// without using the state stack. Not sure if it is worth the effort
// because this happens rarely.
if (NestedLevel != 0) {
errs() << "BOLT-WARNING: CFI rewriter detected nested CFI state while"
<< " replaying CFI instructions for BB " << InBB->getName()
<< " in function " << *this << '\n';
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: CFI rewriter detected nested CFI state while"
<< " replaying CFI instructions for BB " << InBB->getName()
<< " in function " << *this << '\n';
}
return false;
}
@ -1601,9 +1621,11 @@ bool BinaryFunction::fixCFIState() {
}
if (StackOffset != 0) {
errs() << " BOLT-WARNING: not possible to remember/recover state"
<< " without corrupting CFI state stack in function "
<< *this << "\n";
if (opts::Verbosity >= 1) {
errs() << " BOLT-WARNING: not possible to remember/recover state"
<< " without corrupting CFI state stack in function "
<< *this << "\n";
}
return false;
}
} else if (BBCFIState[BBIndex] > State) {
@ -1694,8 +1716,10 @@ std::string constructFilename(std::string Filename,
}
if (Filename.size() + Annotation.size() + Suffix.size() > MAX_PATH) {
assert(Suffix.size() + Annotation.size() <= MAX_PATH);
dbgs() << "BOLT-WARNING: Filename \"" << Filename << Annotation << Suffix
<< "\" exceeds the " << MAX_PATH << " size limit, truncating.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: Filename \"" << Filename << Annotation << Suffix
<< "\" exceeds the " << MAX_PATH << " size limit, truncating.\n";
}
Filename.resize(MAX_PATH - (Suffix.size() + Annotation.size()));
}
Filename += Annotation;
@ -1799,24 +1823,23 @@ void BinaryFunction::dumpGraph(raw_ostream& OS) const {
void BinaryFunction::viewGraph() const {
SmallString<MAX_PATH> Filename;
if (auto EC = sys::fs::createTemporaryFile("bolt-cfg", "dot", Filename)) {
dbgs() << "BOLT-WARNING: " << EC.message() << ", unable to create "
errs() << "BOLT-ERROR: " << EC.message() << ", unable to create "
<< " bolt-cfg-XXXXX.dot temporary file.\n";
return;
}
dumpGraphToFile(Filename.str());
if (DisplayGraph(Filename)) {
dbgs() << "BOLT-WARNING: Can't display " << Filename
<< " with graphviz.\n";
errs() << "BOLT-ERROR: Can't display " << Filename << " with graphviz.\n";
}
if (auto EC = sys::fs::remove(Filename)) {
dbgs() << "BOLT-WARNING: " << EC.message() << ", failed to remove "
<< Filename.str() << "\n";
errs() << "BOLT-WARNING: " << EC.message() << ", failed to remove "
<< Filename << "\n";
}
}
void BinaryFunction::dumpGraphForPass(std::string Annotation) const {
auto Filename = constructFilename(getPrintName(), Annotation, ".dot");
dbgs() << "BOLT-DEBUG: Dumping CFG to " << Filename << "\n";
outs() << "BOLT-DEBUG: Dumping CFG to " << Filename << "\n";
dumpGraphToFile(Filename);
}
@ -1824,8 +1847,10 @@ void BinaryFunction::dumpGraphToFile(std::string Filename) const {
std::error_code EC;
raw_fd_ostream of(Filename, EC, sys::fs::F_None);
if (EC) {
dbgs() << "BOLT-WARNING: " << EC.message() << ", unable to open "
<< Filename << " for output.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: " << EC.message() << ", unable to open "
<< Filename << " for output.\n";
}
return;
}
dumpGraph(of);
@ -2439,10 +2464,10 @@ bool BinaryFunction::isIdenticalWith(const BinaryFunction &BF) const {
++BBI;
}
if (PseudosDiffer) {
errs() << "BOLT-WARNING: functions " << *this << " and ";
errs() << BF << " are identical, but have different";
errs() << " pseudo instruction sequences.\n";
if (opts::Verbosity >= 1 && PseudosDiffer) {
errs() << "BOLT-WARNING: functions " << *this << " and "
<< BF << " are identical, but have different"
<< " pseudo instruction sequences.\n";
}
return true;

View File

@ -17,6 +17,7 @@
namespace opts {
extern llvm::cl::opt<unsigned> Verbosity;
extern llvm::cl::opt<bool> PrintAll;
extern llvm::cl::opt<bool> DumpDotAll;
extern llvm::cl::opt<bool> PrintReordered;
@ -112,7 +113,7 @@ void OptimizeBodylessFunctions::optimizeCalls(BinaryFunction &BF,
}
if (Target == OriginalTarget)
continue;
DEBUG(errs() << "BOLT-DEBUG: Optimizing " << (*BBIt).getName()
DEBUG(dbgs() << "BOLT-DEBUG: Optimizing " << (*BBIt).getName()
<< " in " << BF
<< ": replacing call to " << OriginalTarget->getName()
<< " by call to " << Target->getName() << "\n");
@ -161,7 +162,7 @@ void InlineSmallFunctions::findInliningCandidates(
}
}
DEBUG(errs() << "BOLT-DEBUG: " << InliningCandidates.size()
DEBUG(dbgs() << "BOLT-DEBUG: " << InliningCandidates.size()
<< " inlineable functions.\n");
}
@ -202,7 +203,7 @@ void InlineSmallFunctions::findInliningCandidatesAggressive(
InliningCandidates.insert(&Function);
}
DEBUG(errs() << "BOLT-DEBUG: " << InliningCandidates.size()
DEBUG(dbgs() << "BOLT-DEBUG: " << InliningCandidates.size()
<< " inlineable functions.\n");
}
@ -577,7 +578,7 @@ bool InlineSmallFunctions::inlineCallsInFunction(
auto NextInstIt = std::next(InstIt);
inlineCall(BC, *BB, &Inst, *TargetFunction->begin());
DidInlining = true;
DEBUG(errs() << "BOLT-DEBUG: Inlining call to "
DEBUG(dbgs() << "BOLT-DEBUG: Inlining call to "
<< *TargetFunction << " in "
<< Function << "\n");
InstIt = NextInstIt;
@ -648,7 +649,7 @@ bool InlineSmallFunctions::inlineCallsInFunctionAggressive(
std::tie(NextBB, NextInstIndex) =
inlineCall(BC, Function, BB, InstIndex, *TargetFunction);
DidInlining = true;
DEBUG(errs() << "BOLT-DEBUG: Inlining call to "
DEBUG(dbgs() << "BOLT-DEBUG: Inlining call to "
<< *TargetFunction << " in "
<< Function << "\n");
InstIndex = NextBB == BB ? NextInstIndex : BB->size();
@ -695,9 +696,9 @@ void InlineSmallFunctions::runOnFunctions(
++ModifiedFunctions;
}
DEBUG(errs() << "BOLT-DEBUG: Inlined " << inlinedDynamicCalls << " of "
DEBUG(dbgs() << "BOLT-DEBUG: Inlined " << inlinedDynamicCalls << " of "
<< totalDynamicCalls << " function calls in the profile.\n");
DEBUG(errs() << "BOLT-DEBUG: Inlined calls represent "
DEBUG(dbgs() << "BOLT-DEBUG: Inlined calls represent "
<< (100.0 * inlinedDynamicCalls / totalInlineableCalls)
<< "% of all inlineable calls in the profile.\n");
}
@ -710,9 +711,11 @@ void EliminateUnreachableBlocks::runOnFunction(BinaryFunction& Function) {
// in the graph.
if (Function.layout_size() > 0) {
if (NagUser) {
outs()
<< "BOLT-WARNING: Using -eliminate-unreachable is experimental and "
"unsafe for exceptions\n";
if (opts::Verbosity >= 1) {
errs()
<< "BOLT-WARNING: Using -eliminate-unreachable is experimental and "
"unsafe for exceptions\n";
}
NagUser = false;
}
@ -742,7 +745,7 @@ void EliminateUnreachableBlocks::runOnFunction(BinaryFunction& Function) {
}
if (opts::PrintAll || opts::PrintUCE)
Function.print(errs(), "after unreachable code elimination", true);
Function.print(outs(), "after unreachable code elimination", true);
if (opts::DumpDotAll)
Function.dumpGraphForPass("unreachable-code");
@ -781,7 +784,7 @@ void ReorderBasicBlocks::runOnFunctions(
Function.modifyLayout(opts::ReorderBlocks, opts::MinBranchClusters,
ShouldSplit);
if (opts::PrintAll || opts::PrintReordered)
Function.print(errs(), "after reordering blocks", true);
Function.print(outs(), "after reordering blocks", true);
if (opts::DumpDotAll)
Function.dumpGraphForPass("reordering");
}
@ -804,8 +807,10 @@ void FixupFunctions::runOnFunctions(
// Fix the CFI state.
if (!Function.fixCFIState()) {
errs() << "BOLT-WARNING: unable to fix CFI state for function "
<< Function << ". Skipping.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: unable to fix CFI state for function "
<< Function << ". Skipping.\n";
}
Function.setSimple(false);
continue;
}
@ -813,7 +818,7 @@ void FixupFunctions::runOnFunctions(
// Update exception handling information.
Function.updateEHRanges();
if (opts::PrintAll || opts::PrintEHRanges)
Function.print(errs(), "after updating EH ranges", true);
Function.print(outs(), "after updating EH ranges", true);
if (opts::DumpDotAll)
Function.dumpGraphForPass("update-EH-ranges");
}
@ -920,7 +925,7 @@ void SimplifyConditionalTailCalls::runOnFunctions(
// Fix tail calls to reduce branch mispredictions.
if (fixTailCalls(BC, Function)) {
if (opts::PrintAll || opts::PrintReordered) {
Function.print(errs(), "after tail call patching", true);
Function.print(outs(), "after tail call patching", true);
}
if (opts::DumpDotAll) {
Function.dumpGraphForPass("tail-call-patching");
@ -928,7 +933,7 @@ void SimplifyConditionalTailCalls::runOnFunctions(
}
}
outs() << "BOLT: patched " << NumTailCallsPatched
outs() << "BOLT-INFO: patched " << NumTailCallsPatched
<< " tail calls (" << NumOrigForwardBranches << " forward)"
<< " from a total of " << NumTailCallCandidates << "\n";
}
@ -951,7 +956,7 @@ void Peepholes::runOnFunctions(BinaryContext &BC,
shortenInstructions(BC, Function);
if (opts::PrintAll || opts::PrintPeepholes) {
Function.print(errs(), "after peepholes", true);
Function.print(outs(), "after peepholes", true);
}
if (opts::DumpDotAll) {
@ -1058,7 +1063,7 @@ void SimplifyRODataLoads::runOnFunctions(
if (simplifyRODataLoads(BC, Function)) {
if (opts::PrintAll || opts::PrintSimplifyROLoads) {
Function.print(errs(),
Function.print(outs(),
"after simplifying read-only section loads",
true);
}
@ -1068,11 +1073,11 @@ void SimplifyRODataLoads::runOnFunctions(
}
}
outs() << "BOLT: simplified " << NumLoadsSimplified << " out of ";
outs() << NumLoadsFound << " loads from a statically computed address.\n";
outs() << "BOLT: dynamic loads simplified: " << NumDynamicLoadsSimplified;
outs() << "\n";
outs() << "BOLT: dynamic loads found: " << NumDynamicLoadsFound << "\n";
outs() << "BOLT-INFO: simplified " << NumLoadsSimplified << " out of "
<< NumLoadsFound << " loads from a statically computed address.\n"
<< "BOLT-INFO: dynamic loads simplified: " << NumDynamicLoadsSimplified
<< "\n"
<< "BOLT-INFO: dynamic loads found: " << NumDynamicLoadsFound << "\n";
}
void IdenticalCodeFolding::discoverCallers(
@ -1221,7 +1226,9 @@ void IdenticalCodeFolding::runOnFunctions(
Buckets.clear();
Mod.clear();
errs() << "BOLT-INFO: icf pass " << Iter << "...\n";
if (opts::Verbosity >= 1) {
outs() << "BOLT-INFO: icf pass " << Iter << "...\n";
}
uint64_t NumIdenticalFunctions = 0;
@ -1267,28 +1274,30 @@ void IdenticalCodeFolding::runOnFunctions(
}
}
errs() << "BOLT-INFO: found " << NumIdenticalFunctions;
errs() << " identical functions.\n";
errs() << "BOLT-INFO: modified " << Mod.size() << " functions.\n";
if (opts::Verbosity >= 1) {
outs() << "BOLT-INFO: found " << NumIdenticalFunctions
<< " identical functions.\n"
<< "BOLT-INFO: modified " << Mod.size() << " functions.\n";
}
NumIdenticalFunctionsFound += NumIdenticalFunctions;
++Iter;
} while (!Mod.empty());
outs() << "BOLT: ICF pass found " << NumIdenticalFunctionsFound;
outs() << " functions identical to some other function.\n";
outs() << "BOLT: ICF pass folded references to " << NumFunctionsFolded;
outs() << " functions.\n";
outs() << "BOLT: ICF pass folded " << NumDynamicCallsFolded << " dynamic";
outs() << " function calls.\n";
outs() << "BOLT: Removing all identical functions could save ";
outs() << format("%.2lf", (double) BytesSavedEstimate / 1024);
outs() << " KB of code space.\n";
outs() << "BOLT-INFO: ICF pass found " << NumIdenticalFunctionsFound
<< " functions identical to some other function.\n"
<< "BOLT-INFO: ICF pass folded references to " << NumFunctionsFolded
<< " functions.\n"
<< "BOLT-INFO: ICF pass folded " << NumDynamicCallsFolded << " dynamic"
<< " function calls.\n"
<< "BOLT-INFO: Removing all identical functions could save "
<< format("%.2lf", (double) BytesSavedEstimate / 1024)
<< " KB of code space.\n";
if (opts::PrintAll || opts::PrintICF) {
for (auto &I : BFs) {
I.second.print(errs(), "after identical code folding", true);
I.second.print(outs(), "after identical code folding", true);
}
}
}

View File

@ -27,6 +27,7 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Errc.h"
@ -42,6 +43,10 @@ using namespace llvm;
using namespace object;
using namespace bolt;
namespace opts {
extern cl::opt<unsigned> Verbosity;
}
void RewriteInstance::updateDebugInfo() {
SectionPatchers[".debug_abbrev"] = llvm::make_unique<DebugAbbrevPatcher>();
SectionPatchers[".debug_info"] = llvm::make_unique<SimpleBinaryPatcher>();
@ -123,7 +128,7 @@ void RewriteInstance::updateDWARFObjectAddressRanges(
return;
}
if (DebugRangesOffset == -1U) {
if (opts::Verbosity >= 2 && DebugRangesOffset == -1U) {
errs() << "BOLT-WARNING: using invalid DW_AT_range for DIE at offset 0x"
<< Twine::utohexstr(DIE->getOffset()) << '\n';
}
@ -137,9 +142,11 @@ void RewriteInstance::updateDWARFObjectAddressRanges(
const auto *AbbreviationDecl = DIE->getAbbreviationDeclarationPtr();
if (!AbbreviationDecl) {
errs() << "BOLT-WARNING: object's DIE doesn't have an abbreviation: "
<< "skipping update. DIE at offset 0x"
<< Twine::utohexstr(DIE->getOffset()) << '\n';
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: object's DIE doesn't have an abbreviation: "
<< "skipping update. DIE at offset 0x"
<< Twine::utohexstr(DIE->getOffset()) << '\n';
}
return;
}
@ -176,14 +183,19 @@ void RewriteInstance::updateDWARFObjectAddressRanges(
(HighPCFormValue.getForm() != dwarf::DW_FORM_addr &&
HighPCFormValue.getForm() != dwarf::DW_FORM_data8 &&
HighPCFormValue.getForm() != dwarf::DW_FORM_data4)) {
errs() << "BOLT-WARNING: unexpected form value. Cannot update DIE "
"at offset 0x" << Twine::utohexstr(DIE->getOffset()) << '\n';
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: unexpected form value. Cannot update DIE "
<< "at offset 0x" << Twine::utohexstr(DIE->getOffset())
<< "\n";
}
return;
}
if (LowPCOffset == -1U || (LowPCOffset + 8 != HighPCOffset)) {
errs() << "BOLT-WARNING: high_pc expected immediately after low_pc. "
"Cannot update DIE at offset 0x"
<< Twine::utohexstr(DIE->getOffset()) << '\n';
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: high_pc expected immediately after low_pc. "
<< "Cannot update DIE at offset 0x"
<< Twine::utohexstr(DIE->getOffset()) << '\n';
}
return;
}
@ -213,8 +225,10 @@ void RewriteInstance::updateDWARFObjectAddressRanges(
ProducerString.back() = '\0';
DebugInfoPatcher->addBinaryPatch(LowPCOffset + 4, ProducerString);
} else {
errs() << "BOLT-WARNING: Cannot update ranges for DIE at offset 0x"
<< Twine::utohexstr(DIE->getOffset()) << '\n';
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: Cannot update ranges for DIE at offset 0x"
<< Twine::utohexstr(DIE->getOffset()) << '\n';
}
}
}
}
@ -271,7 +285,7 @@ void RewriteInstance::updateDebugLineInfoForNonSimpleFunctions() {
OutputLineTable.addLineEntry(MCLineEntry{nullptr, Loc},
FunctionSection);
} else {
DEBUG(errs() << "BOLT-DEBUG: Function " << Function
DEBUG(dbgs() << "BOLT-DEBUG: Function " << Function
<< " has no associated line number information.\n");
}
}

View File

@ -14,9 +14,14 @@
#include "BinaryFunction.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/Support/CommandLine.h"
#include <algorithm>
#include <cassert>
namespace opts {
extern llvm::cl::opt<unsigned> Verbosity;
}
namespace llvm {
namespace bolt {
@ -29,10 +34,12 @@ void BasicBlockOffsetRanges::addAddressRange(BinaryFunction &Function,
auto FirstBB = Function.getBasicBlockContainingOffset(
BeginAddress - Function.getAddress());
if (!FirstBB) {
errs() << "BOLT-WARNING: no basic blocks in function "
<< Function << " intersect with debug range [0x"
<< Twine::utohexstr(BeginAddress) << ", 0x"
<< Twine::utohexstr(EndAddress) << ")\n";
if (opts::Verbosity >= 2) {
errs() << "BOLT-WARNING: no basic blocks in function "
<< Function << " intersect with debug range [0x"
<< Twine::utohexstr(BeginAddress) << ", 0x"
<< Twine::utohexstr(EndAddress) << ")\n";
}
return;
}

View File

@ -32,18 +32,20 @@
using namespace llvm::dwarf;
namespace llvm {
namespace bolt {
namespace opts {
static cl::opt<bool>
extern llvm::cl::opt<unsigned> Verbosity;
static llvm::cl::opt<bool>
PrintExceptions("print-exceptions",
cl::desc("print exception handling data"),
cl::Hidden);
llvm::cl::desc("print exception handling data"),
llvm::cl::Hidden);
} // namespace opts
namespace llvm {
namespace bolt {
// Read and dump the .gcc_exception_table section entry.
//
// .gcc_except_table section contains a set of Language-Specific Data Areas -
@ -121,12 +123,12 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
}
if (opts::PrintExceptions) {
errs() << "[LSDA at 0x" << Twine::utohexstr(getLSDAAddress())
outs() << "[LSDA at 0x" << Twine::utohexstr(getLSDAAddress())
<< " for function " << *this << "]:\n";
errs() << "LPStart Encoding = " << (unsigned)LPStartEncoding << '\n';
errs() << "LPStart = 0x" << Twine::utohexstr(LPStart) << '\n';
errs() << "TType Encoding = " << (unsigned)TTypeEncoding << '\n';
errs() << "TType End = " << TTypeEnd << '\n';
outs() << "LPStart Encoding = " << (unsigned)LPStartEncoding << '\n';
outs() << "LPStart = 0x" << Twine::utohexstr(LPStart) << '\n';
outs() << "TType Encoding = " << (unsigned)TTypeEncoding << '\n';
outs() << "TType End = " << TTypeEnd << '\n';
}
// Table to store list of indices in type table. Entries are uleb128 values.
@ -147,9 +149,9 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
const uint8_t *ActionTableStart = CallSiteTableEnd;
if (opts::PrintExceptions) {
errs() << "CallSite Encoding = " << (unsigned)CallSiteEncoding << '\n';
errs() << "CallSite table length = " << CallSiteTableLength << '\n';
errs() << '\n';
outs() << "CallSite Encoding = " << (unsigned)CallSiteEncoding << '\n';
outs() << "CallSite table length = " << CallSiteTableLength << '\n';
outs() << '\n';
}
HasEHRanges = CallSitePtr < CallSiteTableEnd;
@ -161,7 +163,7 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
uintptr_t ActionEntry = readULEB128(CallSitePtr);
if (opts::PrintExceptions) {
errs() << "Call Site: [0x" << Twine::utohexstr(RangeBase + Start)
outs() << "Call Site: [0x" << Twine::utohexstr(RangeBase + Start)
<< ", 0x" << Twine::utohexstr(RangeBase + Start + Length)
<< "); landing pad: 0x" << Twine::utohexstr(LPStart + LandingPad)
<< "; action entry: 0x" << Twine::utohexstr(ActionEntry) << "\n";
@ -171,9 +173,11 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
MCSymbol *LPSymbol{nullptr};
if (LandingPad) {
if (Instructions.find(LandingPad) == Instructions.end()) {
errs() << "BOLT-WARNING: landing pad " << Twine::utohexstr(LandingPad)
<< " not pointing to an instruction in function "
<< *this << " - ignoring.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: landing pad " << Twine::utohexstr(LandingPad)
<< " not pointing to an instruction in function "
<< *this << " - ignoring.\n";
}
} else {
auto Label = Labels.find(LandingPad);
if (Label != Labels.end()) {
@ -222,7 +226,7 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
}
};
if (opts::PrintExceptions)
errs() << " actions: ";
outs() << " actions: ";
const uint8_t *ActionPtr = ActionTableStart + ActionEntry - 1;
long long ActionType;
long long ActionNext;
@ -232,19 +236,19 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
auto Self = ActionPtr;
ActionNext = readSLEB128(ActionPtr);
if (opts::PrintExceptions)
errs() << Sep << "(" << ActionType << ", " << ActionNext << ") ";
outs() << Sep << "(" << ActionType << ", " << ActionNext << ") ";
if (ActionType == 0) {
if (opts::PrintExceptions)
errs() << "cleanup";
outs() << "cleanup";
} else if (ActionType > 0) {
// It's an index into a type table.
if (opts::PrintExceptions) {
errs() << "catch type ";
printType(ActionType, errs());
outs() << "catch type ";
printType(ActionType, outs());
}
} else { // ActionType < 0
if (opts::PrintExceptions)
errs() << "filter exception types ";
outs() << "filter exception types ";
auto TSep = "";
// ActionType is a negative *byte* offset into *uleb128-encoded* table
// of indices with base 1.
@ -253,8 +257,8 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
auto TypeIndexTablePtr = TypeIndexTableStart - ActionType - 1;
while (auto Index = readULEB128(TypeIndexTablePtr)) {
if (opts::PrintExceptions) {
errs() << TSep;
printType(Index, errs());
outs() << TSep;
printType(Index, outs());
TSep = ", ";
}
}
@ -268,11 +272,11 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
ActionPtr = Self + ActionNext;
} while (ActionNext);
if (opts::PrintExceptions)
errs() << '\n';
outs() << '\n';
}
}
if (opts::PrintExceptions)
errs() << '\n';
outs() << '\n';
assert(TypeIndexTableStart + MaxTypeIndexTableOffset <=
LSDASectionData.data() + LSDASectionData.size() &&
@ -494,11 +498,13 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
const FDE &CurFDE = *I->second;
if (Function.getSize() != CurFDE.getAddressRange()) {
errs() << "BOLT-WARNING: CFI information size mismatch for function \""
<< Function << "\""
<< format(": Function size is %dB, CFI covers "
"%dB\n",
Function.getSize(), CurFDE.getAddressRange());
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: CFI information size mismatch for function \""
<< Function << "\""
<< format(": Function size is %dB, CFI covers "
"%dB\n",
Function.getSize(), CurFDE.getAddressRange());
}
return false;
}
@ -609,24 +615,34 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
break;
case DW_CFA_val_offset_sf:
case DW_CFA_val_offset:
errs() << "BOLT-WARNING: DWARF val_offset() unimplemented\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: DWARF val_offset() unimplemented\n";
}
return false;
case DW_CFA_expression:
case DW_CFA_def_cfa_expression:
case DW_CFA_val_expression:
errs() << "BOLT-WARNING: DWARF CFA expressions unimplemented\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: DWARF CFA expressions unimplemented\n";
}
return false;
case DW_CFA_MIPS_advance_loc8:
errs() << "BOLT-WARNING: DW_CFA_MIPS_advance_loc unimplemented\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: DW_CFA_MIPS_advance_loc unimplemented\n";
}
return false;
case DW_CFA_GNU_window_save:
case DW_CFA_lo_user:
case DW_CFA_hi_user:
errs() <<
"BOLT-WARNING: DW_CFA_GNU_* and DW_CFA_*_user unimplemented\n";
if (opts::Verbosity >= 1) {
errs() <<
"BOLT-WARNING: DW_CFA_GNU_* and DW_CFA_*_user unimplemented\n";
}
return false;
default:
errs() << "BOLT-WARNING: Unrecognized CFI instruction\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: Unrecognized CFI instruction\n";
}
return false;
}

View File

@ -66,6 +66,22 @@ namespace opts {
static cl::opt<std::string>
OutputFilename("o", cl::desc("<output file>"), cl::Required);
// The default verbosity level (0) is pretty terse, level 1 is fairly
// verbose and usually prints some informational message for every
// function processed. Level 2 is for the noisiest of messages and
// often prints a message per basic block.
// Error messages should never be suppressed by the verbosity level.
// Only warnings and info messages should be affected.
//
// The rational behind stream usage is as follows:
// outs() for info and debugging controlled by command line flags.
// errs() for errors and warnings.
// dbgs() for output within DEBUG().
cl::opt<unsigned>
Verbosity("v",
cl::desc("set verbosity level for diagnostic output"),
cl::init(0));
static cl::list<std::string>
BreakFunctionNames("break-funcs",
cl::CommaSeparated,
@ -360,14 +376,14 @@ std::unique_ptr<BinaryContext> createBinaryContext(
*TheTriple,
Error);
if (!TheTarget) {
errs() << "BOLT: " << Error;
errs() << "BOLT-ERROR: " << Error;
return nullptr;
}
std::unique_ptr<const MCRegisterInfo> MRI(
TheTarget->createMCRegInfo(TripleName));
if (!MRI) {
errs() << "error: no register info for target " << TripleName << "\n";
errs() << "BOLT-ERROR: no register info for target " << TripleName << "\n";
return nullptr;
}
@ -375,20 +391,20 @@ std::unique_ptr<BinaryContext> createBinaryContext(
std::unique_ptr<const MCAsmInfo> AsmInfo(
TheTarget->createMCAsmInfo(*MRI, TripleName));
if (!AsmInfo) {
errs() << "error: no assembly info for target " << TripleName << "\n";
errs() << "BOLT-ERROR: no assembly info for target " << TripleName << "\n";
return nullptr;
}
std::unique_ptr<const MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(TripleName, "", ""));
if (!STI) {
errs() << "error: no subtarget info for target " << TripleName << "\n";
errs() << "BOLT-ERROR: no subtarget info for target " << TripleName << "\n";
return nullptr;
}
std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
if (!MII) {
errs() << "error: no instruction info for target " << TripleName << "\n";
errs() << "BOLT-ERROR: no instruction info for target " << TripleName << "\n";
return nullptr;
}
@ -403,14 +419,14 @@ std::unique_ptr<BinaryContext> createBinaryContext(
TheTarget->createMCDisassembler(*STI, *Ctx));
if (!DisAsm) {
errs() << "error: no disassembler for target " << TripleName << "\n";
errs() << "BOLT-ERROR: no disassembler for target " << TripleName << "\n";
return nullptr;
}
std::unique_ptr<const MCInstrAnalysis> MIA(
TheTarget->createMCInstrAnalysis(MII.get()));
if (!MIA) {
errs() << "error: failed to create instruction analysis for target"
errs() << "BOLT-ERROR: failed to create instruction analysis for target"
<< TripleName << "\n";
return nullptr;
}
@ -420,7 +436,7 @@ std::unique_ptr<BinaryContext> createBinaryContext(
TheTarget->createMCInstPrinter(Triple(TripleName), AsmPrinterVariant,
*AsmInfo, *MII, *MRI));
if (!InstructionPrinter) {
errs() << "error: no instruction printer for target " << TripleName
errs() << "BOLT-ERROR: no instruction printer for target " << TripleName
<< '\n';
return nullptr;
}
@ -507,7 +523,7 @@ void RewriteInstance::discoverStorage() {
assert(NextAvailableAddress && NextAvailableOffset &&
"no PT_LOAD pheader seen");
errs() << "BOLT-INFO: first alloc address is 0x"
outs() << "BOLT-INFO: first alloc address is 0x"
<< Twine::utohexstr(FirstAllocAddress) << '\n';
FirstNonAllocatableOffset = NextAvailableOffset;
@ -534,7 +550,7 @@ void RewriteInstance::discoverStorage() {
assert(NextAvailableOffset == NextAvailableAddress - FirstAllocAddress &&
"PHDR table address calculation error");
errs() << "BOLT-INFO: creating new program header table at address 0x"
outs() << "BOLT-INFO: creating new program header table at address 0x"
<< Twine::utohexstr(NextAvailableAddress) << ", offset 0x"
<< Twine::utohexstr(NextAvailableOffset) << '\n';
@ -559,7 +575,7 @@ void RewriteInstance::discoverStorage() {
void RewriteInstance::run() {
if (!BC) {
errs() << "failed to create a binary context\n";
errs() << "BOLT-ERROR: failed to create a binary context\n";
return;
}
@ -610,9 +626,11 @@ void RewriteInstance::run() {
auto FunctionIt = BinaryFunctions.find(Address);
assert(FunctionIt != BinaryFunctions.end() &&
"Invalid large function address.");
errs() << "BOLT-WARNING: Function " << FunctionIt->second
<< " is larger than its orginal size: emitting again marking it "
<< "as not simple.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: Function " << FunctionIt->second
<< " is larger than its orginal size: emitting again marking it "
<< "as not simple.\n";
}
FunctionIt->second.setSimple(false);
}
@ -664,7 +682,7 @@ void RewriteInstance::discoverFileObjects() {
check_error(AddressOrErr.getError(), "cannot get symbol address");
uint64_t Address = *AddressOrErr;
if (Address == 0) {
if (Symbol.getType() == SymbolRef::ST_Function)
if (opts::Verbosity >= 1 && Symbol.getType() == SymbolRef::ST_Function)
errs() << "BOLT-WARNING: function with 0 address seen\n";
continue;
}
@ -764,7 +782,8 @@ void RewriteInstance::discoverFileObjects() {
auto &PrevFDE = *FDEI->second;
auto PrevStart = PrevFDE.getInitialLocation();
auto PrevLength = PrevFDE.getAddressRange();
if (Address > PrevStart && Address < PrevStart + PrevLength) {
if (opts::Verbosity >= 1 &&
Address > PrevStart && Address < PrevStart + PrevLength) {
errs() << "BOLT-WARNING: function " << UniqueName
<< " is in conflict with FDE ["
<< Twine::utohexstr(PrevStart) << ", "
@ -775,9 +794,11 @@ void RewriteInstance::discoverFileObjects() {
}
} else if (FDE.getAddressRange() != SymbolSize) {
// Function addresses match but sizes differ.
errs() << "BOLT-WARNING: sizes differ for function " << UniqueName
<< ". FDE : " << FDE.getAddressRange()
<< "; symbol table : " << SymbolSize << ". Skipping.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: sizes differ for function " << UniqueName
<< ". FDE : " << FDE.getAddressRange()
<< "; symbol table : " << SymbolSize << ". Skipping.\n";
}
// Create maximum size non-simple function.
IsSimple = false;
@ -791,7 +812,7 @@ void RewriteInstance::discoverFileObjects() {
BF = &BFI->second;
// Duplicate function name. Make sure everything matches before we add
// an alternative name.
if (SymbolSize != BF->getSize()) {
if (opts::Verbosity >= 1 && SymbolSize != BF->getSize()) {
errs() << "BOLT-WARNING: size mismatch for duplicate entries "
<< UniqueName << ':' << SymbolSize << " and "
<< *BF << ':' << BF->getSize() << '\n';
@ -906,8 +927,10 @@ void RewriteInstance::disassembleFunctions() {
"wrong section for function");
if (!Section.isText() || Section.isVirtual() || !Section.getSize()) {
// When could it happen?
errs() << "BOLT: corresponding section is non-executable or empty "
<< "for function " << Function;
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: corresponding section is non-executable or empty "
<< "for function " << Function;
}
continue;
}
@ -926,8 +949,10 @@ void RewriteInstance::disassembleFunctions() {
uint64_t SectionEnd = Function.getSection().getAddress() +
Function.getSection().getSize();
if (SectionEnd > SymRefI->first) {
errs() << "BOLT-WARNING: symbol after " << Function
<< " should not be in the same section.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: symbol after " << Function
<< " should not be in the same section.\n";
}
MaxSize = 0;
} else {
MaxSize = SectionEnd - Function.getAddress();
@ -935,8 +960,10 @@ void RewriteInstance::disassembleFunctions() {
}
if (MaxSize < Function.getSize()) {
errs() << "BOLT-WARNING: symbol seen in the middle of the function "
<< Function << ". Skipping.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: symbol seen in the middle of the function "
<< Function << ". Skipping.\n";
}
Function.setSimple(false);
continue;
}
@ -966,7 +993,7 @@ void RewriteInstance::disassembleFunctions() {
continue;
if (opts::PrintAll || opts::PrintDisasm)
Function.print(errs(), "after disassembly", true);
Function.print(outs(), "after disassembly", true);
if (!Function.isSimple())
continue;
@ -974,8 +1001,10 @@ void RewriteInstance::disassembleFunctions() {
// Fill in CFI information for this function
if (EHFrame->ParseError.empty()) {
if (!CFIRdWrt->fillCFIInfoFor(Function)) {
errs() << "BOLT-WARNING: unable to fill CFI for function "
<< Function << '\n';
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: unable to fill CFI for function "
<< Function << '\n';
}
Function.setSimple(false);
continue;
}
@ -989,14 +1018,14 @@ void RewriteInstance::disassembleFunctions() {
continue;
if (opts::PrintAll || opts::PrintCFG)
Function.print(errs(), "after building cfg", true);
Function.print(outs(), "after building cfg", true);
if (opts::DumpDotAll)
Function.dumpGraphForPass("build-cfg");
if (opts::PrintLoopInfo) {
Function.calculateLoopInfo();
Function.printLoopInfo(errs());
Function.printLoopInfo(outs());
}
TotalScore += Function.getFunctionScore();
@ -1009,9 +1038,11 @@ void RewriteInstance::disassembleFunctions() {
for (auto Addr : BC->InterproceduralReferences) {
auto *ContainingFunction = getBinaryFunctionContainingAddress(Addr);
if (ContainingFunction && ContainingFunction->getAddress() != Addr) {
errs() << "BOLT-WARNING: Function " << ContainingFunction
<< " has internal BBs that are target of a reference located in "
"another function. Skipping the function.\n";
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: Function " << ContainingFunction
<< " has internal BBs that are target of a reference located in "
<< "another function. Skipping the function.\n";
}
ContainingFunction->setSimple(false);
}
}
@ -1032,7 +1063,7 @@ void RewriteInstance::disassembleFunctions() {
++NumStaleProfileFunctions;
}
errs() << "BOLT-INFO: "
outs() << "BOLT-INFO: "
<< ProfiledFunctions.size() + NumStaleProfileFunctions
<< " functions out of " << NumSimpleFunctions << " simple functions ("
<< format("%.1f",
@ -1040,7 +1071,7 @@ void RewriteInstance::disassembleFunctions() {
(float) NumSimpleFunctions * 100.0f)
<< "%) have non-empty execution profile.\n";
if (NumStaleProfileFunctions) {
errs() << "BOLT-INFO: " << NumStaleProfileFunctions
outs() << "BOLT-INFO: " << NumStaleProfileFunctions
<< format(" (%.1f%) ", NumStaleProfileFunctions /
(float) NumSimpleFunctions * 100.0f)
<< " function" << (NumStaleProfileFunctions == 1 ? "" : "s")
@ -1048,16 +1079,18 @@ void RewriteInstance::disassembleFunctions() {
}
if (ProfiledFunctions.size() > 10) {
errs() << "BOLT-INFO: top called functions are:\n";
std::sort(ProfiledFunctions.begin(), ProfiledFunctions.end(),
[](BinaryFunction *A, BinaryFunction *B) {
return B->getExecutionCount() < A->getExecutionCount();
}
);
auto SFI = ProfiledFunctions.begin();
for (int i = 0; i < 100 && SFI != ProfiledFunctions.end(); ++SFI, ++i) {
errs() << " " << *SFI << " : "
<< (*SFI)->getExecutionCount() << '\n';
if (opts::Verbosity >= 1) {
outs() << "BOLT-INFO: top called functions are:\n";
std::sort(ProfiledFunctions.begin(), ProfiledFunctions.end(),
[](BinaryFunction *A, BinaryFunction *B) {
return B->getExecutionCount() < A->getExecutionCount();
}
);
auto SFI = ProfiledFunctions.begin();
for (int i = 0; i < 100 && SFI != ProfiledFunctions.end(); ++SFI, ++i) {
outs() << " " << **SFI << " : "
<< (*SFI)->getExecutionCount() << '\n';
}
}
}
}
@ -1426,7 +1459,9 @@ void RewriteInstance::emitFunctions() {
FailedAddresses.emplace_back(Function.getAddress());
}
} else {
errs() << "BOLT: cannot remap function " << Function << "\n";
if (opts::Verbosity >= 2) {
errs() << "BOLT-WARNING: cannot remap function " << Function << "\n";
}
FailedAddresses.emplace_back(Function.getAddress());
}
@ -1453,7 +1488,9 @@ void RewriteInstance::emitFunctions() {
NextAvailableAddress += Function.cold().getImageSize();
} else {
errs() << "BOLT: cannot remap function " << Function << "\n";
if (opts::Verbosity >= 2) {
errs() << "BOLT-WARNING: cannot remap function " << Function << "\n";
}
FailedAddresses.emplace_back(Function.getAddress());
}
}
@ -1494,7 +1531,9 @@ void RewriteInstance::emitFunctions() {
NextAvailableAddress += SI.Size;
} else {
errs() << "BOLT: cannot remap " << SectionName << '\n';
if (opts::Verbosity >= 2) {
errs() << "BOLT-WARNING: cannot remap " << SectionName << '\n';
}
}
}
@ -1794,8 +1833,9 @@ void RewriteInstance::patchELFSectionHeaderTable() {
// Ignore function sections.
if (SI.IsCode && SMII.first != ".bolt.text")
continue;
errs() << "BOLT-INFO: writing section header for "
<< SMII.first << '\n';
if (opts::Verbosity >= 1) {
outs() << "BOLT-INFO: writing section header for " << SMII.first << '\n';
}
Elf_Shdr NewSection;
NewSection.sh_name = SI.ShName;
NewSection.sh_type = ELF::SHT_PROGBITS;
@ -1905,18 +1945,22 @@ void RewriteInstance::rewriteFile() {
continue;
if (Function.getImageSize() > Function.getMaxSize()) {
errs() << "BOLT-WARNING: new function size (0x"
<< Twine::utohexstr(Function.getImageSize())
<< ") is larger than maximum allowed size (0x"
<< Twine::utohexstr(Function.getMaxSize())
<< ") for function " << Function << '\n';
if (opts::Verbosity >= 1) {
errs() << "BOLT-WARNING: new function size (0x"
<< Twine::utohexstr(Function.getImageSize())
<< ") is larger than maximum allowed size (0x"
<< Twine::utohexstr(Function.getMaxSize())
<< ") for function " << Function << '\n';
}
FailedAddresses.emplace_back(Function.getAddress());
continue;
}
OverwrittenScore += Function.getFunctionScore();
// Overwrite function in the output file.
outs() << "BOLT: rewriting function \"" << Function << "\"\n";
if (opts::Verbosity >= 2) {
outs() << "BOLT: rewriting function \"" << Function << "\"\n";
}
Out->os().pwrite(reinterpret_cast<char *>(Function.getImageAddress()),
Function.getImageSize(), Function.getFileOffset());
@ -1938,7 +1982,9 @@ void RewriteInstance::rewriteFile() {
}
// Write cold part
outs() << "BOLT: rewriting function \"" << Function << "\" (cold part)\n";
if (opts::Verbosity >= 2) {
outs() << "BOLT: rewriting function \"" << Function << "\" (cold part)\n";
}
Out->os().pwrite(reinterpret_cast<char*>(Function.cold().getImageAddress()),
Function.cold().getImageSize(),
Function.cold().getFileOffset());
@ -1967,7 +2013,9 @@ void RewriteInstance::rewriteFile() {
SectionInfo &SI = SMII.second;
if (SI.IsCode)
continue;
outs() << "BOLT: writing new section " << SMII.first << '\n';
if (opts::Verbosity >= 1) {
outs() << "BOLT: writing new section " << SMII.first << '\n';
}
Out->os().pwrite(reinterpret_cast<const char *>(SI.AllocAddress),
SI.Size,
SI.FileOffset);
@ -1977,7 +2025,9 @@ void RewriteInstance::rewriteFile() {
auto SMII = SectionMM->SectionMapInfo.find(".eh_frame");
if (SMII != SectionMM->SectionMapInfo.end()) {
auto &EHFrameSecInfo = SMII->second;
outs() << "BOLT: writing a new .eh_frame_hdr\n";
if (opts::Verbosity >= 1) {
outs() << "BOLT: writing a new .eh_frame_hdr\n";
}
if (FrameHdrAlign > 1) {
auto PaddingSize = OffsetToAlignment(NextAvailableAddress, FrameHdrAlign);
for (unsigned I = 0; I < PaddingSize; ++I)