forked from OSchip/llvm-project
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:
parent
43acb6a28a
commit
c27a6a5c63
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue