[BOLT][NFC] Fix braces usage in Profile
Summary: Refactor bolt/*/Profile to follow the braces rule for if/else/loop from [LLVM Coding Standards](https://llvm.org/docs/CodingStandards.html). (cherry picked from FBD33345741)
This commit is contained in:
		
							parent
							
								
									89ceb77997
								
							
						
					
					
						commit
						def464aaae
					
				| 
						 | 
					@ -230,9 +230,8 @@ BoltAddressTranslation::getFallthroughsInTrace(const BinaryFunction &Func,
 | 
				
			||||||
  To -= Func.getAddress();
 | 
					  To -= Func.getAddress();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto Iter = Maps.find(Func.getAddress());
 | 
					  auto Iter = Maps.find(Func.getAddress());
 | 
				
			||||||
  if (Iter == Maps.end()) {
 | 
					  if (Iter == Maps.end())
 | 
				
			||||||
    return NoneType();
 | 
					    return NoneType();
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const MapTy &Map = Iter->second;
 | 
					  const MapTy &Map = Iter->second;
 | 
				
			||||||
  auto FromIter = Map.upper_bound(From);
 | 
					  auto FromIter = Map.upper_bound(From);
 | 
				
			||||||
| 
						 | 
					@ -261,9 +260,8 @@ BoltAddressTranslation::getFallthroughsInTrace(const BinaryFunction &Func,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ++Iter;
 | 
					    ++Iter;
 | 
				
			||||||
    while (Iter->second & BRANCHENTRY && Iter != ToIter) {
 | 
					    while (Iter->second & BRANCHENTRY && Iter != ToIter)
 | 
				
			||||||
      ++Iter;
 | 
					      ++Iter;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (Iter->second & BRANCHENTRY)
 | 
					    if (Iter->second & BRANCHENTRY)
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    Res.emplace_back(Src, Iter->first);
 | 
					    Res.emplace_back(Src, Iter->first);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -122,17 +122,15 @@ DataAggregator::~DataAggregator() { deleteTempFiles(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
void deleteTempFile(const std::string &FileName) {
 | 
					void deleteTempFile(const std::string &FileName) {
 | 
				
			||||||
  if (std::error_code Errc = sys::fs::remove(FileName.c_str())) {
 | 
					  if (std::error_code Errc = sys::fs::remove(FileName.c_str()))
 | 
				
			||||||
    errs() << "PERF2BOLT: failed to delete temporary file " << FileName
 | 
					    errs() << "PERF2BOLT: failed to delete temporary file " << FileName
 | 
				
			||||||
           << " with error " << Errc.message() << "\n";
 | 
					           << " with error " << Errc.message() << "\n";
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DataAggregator::deleteTempFiles() {
 | 
					void DataAggregator::deleteTempFiles() {
 | 
				
			||||||
  for (std::string &FileName : TempFiles) {
 | 
					  for (std::string &FileName : TempFiles)
 | 
				
			||||||
    deleteTempFile(FileName);
 | 
					    deleteTempFile(FileName);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  TempFiles.clear();
 | 
					  TempFiles.clear();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,17 +153,16 @@ void DataAggregator::start() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  findPerfExecutable();
 | 
					  findPerfExecutable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (opts::BasicAggregation) {
 | 
					  if (opts::BasicAggregation)
 | 
				
			||||||
    launchPerfProcess("events without LBR",
 | 
					    launchPerfProcess("events without LBR",
 | 
				
			||||||
                      MainEventsPPI,
 | 
					                      MainEventsPPI,
 | 
				
			||||||
                      "script -F pid,event,ip",
 | 
					                      "script -F pid,event,ip",
 | 
				
			||||||
                      /*Wait = */false);
 | 
					                      /*Wait = */false);
 | 
				
			||||||
  } else {
 | 
					  else
 | 
				
			||||||
    launchPerfProcess("branch events",
 | 
					    launchPerfProcess("branch events",
 | 
				
			||||||
                      MainEventsPPI,
 | 
					                      MainEventsPPI,
 | 
				
			||||||
                      "script -F pid,ip,brstack",
 | 
					                      "script -F pid,ip,brstack",
 | 
				
			||||||
                      /*Wait = */false);
 | 
					                      /*Wait = */false);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Note: we launch script for mem events regardless of the option, as the
 | 
					  // Note: we launch script for mem events regardless of the option, as the
 | 
				
			||||||
  //       command fails fairly fast if mem events were not collected.
 | 
					  //       command fails fairly fast if mem events were not collected.
 | 
				
			||||||
| 
						 | 
					@ -253,13 +250,12 @@ void DataAggregator::launchPerfProcess(StringRef Name, PerfProcessInfo &PPI,
 | 
				
			||||||
           << "\n";
 | 
					           << "\n";
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (Wait) {
 | 
					  if (Wait)
 | 
				
			||||||
    PPI.PI.ReturnCode = sys::ExecuteAndWait(PerfPath.data(), Argv,
 | 
					    PPI.PI.ReturnCode = sys::ExecuteAndWait(PerfPath.data(), Argv,
 | 
				
			||||||
                                            /*envp*/ llvm::None, Redirects);
 | 
					                                            /*envp*/ llvm::None, Redirects);
 | 
				
			||||||
  } else {
 | 
					  else
 | 
				
			||||||
    PPI.PI = sys::ExecuteNoWait(PerfPath.data(), Argv, /*envp*/ llvm::None,
 | 
					    PPI.PI = sys::ExecuteNoWait(PerfPath.data(), Argv, /*envp*/ llvm::None,
 | 
				
			||||||
                                Redirects);
 | 
					                                Redirects);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  free(WritableArgsString);
 | 
					  free(WritableArgsString);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -307,9 +303,8 @@ void DataAggregator::processFileBuildID(StringRef FileBuildID) {
 | 
				
			||||||
              "is not the same recorded by perf when collecting profiling "
 | 
					              "is not the same recorded by perf when collecting profiling "
 | 
				
			||||||
              "data, or there were no samples recorded for the binary. "
 | 
					              "data, or there were no samples recorded for the binary. "
 | 
				
			||||||
              "Use -ignore-build-id option to override.\n";
 | 
					              "Use -ignore-build-id option to override.\n";
 | 
				
			||||||
    if (!opts::IgnoreBuildID) {
 | 
					    if (!opts::IgnoreBuildID)
 | 
				
			||||||
      abort();
 | 
					      abort();
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  } else if (*FileName != llvm::sys::path::filename(BC->getFilename())) {
 | 
					  } else if (*FileName != llvm::sys::path::filename(BC->getFilename())) {
 | 
				
			||||||
    errs() << "PERF2BOLT-WARNING: build-id matched a different file name\n";
 | 
					    errs() << "PERF2BOLT-WARNING: build-id matched a different file name\n";
 | 
				
			||||||
    BuildIDBinaryName = std::string(*FileName);
 | 
					    BuildIDBinaryName = std::string(*FileName);
 | 
				
			||||||
| 
						 | 
					@ -446,10 +441,10 @@ void DataAggregator::filterBinaryMMapInfo() {
 | 
				
			||||||
             << " for binary \"" << BC->getFilename() << "\".";
 | 
					             << " for binary \"" << BC->getFilename() << "\".";
 | 
				
			||||||
      assert(!BinaryMMapInfo.empty() && "No memory map for matching binary");
 | 
					      assert(!BinaryMMapInfo.empty() && "No memory map for matching binary");
 | 
				
			||||||
      errs() << " Profile for the following process is available:\n";
 | 
					      errs() << " Profile for the following process is available:\n";
 | 
				
			||||||
      for (std::pair<const uint64_t, MMapInfo> &MMI : BinaryMMapInfo) {
 | 
					      for (std::pair<const uint64_t, MMapInfo> &MMI : BinaryMMapInfo)
 | 
				
			||||||
        outs() << "  " << MMI.second.PID
 | 
					        outs() << "  " << MMI.second.PID
 | 
				
			||||||
               << (MMI.second.Forked ? " (forked)\n" : "\n");
 | 
					               << (MMI.second.Forked ? " (forked)\n" : "\n");
 | 
				
			||||||
      }
 | 
					
 | 
				
			||||||
      if (errs().has_colors())
 | 
					      if (errs().has_colors())
 | 
				
			||||||
        errs().resetColor();
 | 
					        errs().resetColor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -529,15 +524,13 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
 | 
				
			||||||
    opts::IgnoreInterruptLBR = false;
 | 
					    opts::IgnoreInterruptLBR = false;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    prepareToParse("mmap events", MMapEventsPPI);
 | 
					    prepareToParse("mmap events", MMapEventsPPI);
 | 
				
			||||||
    if (parseMMapEvents()) {
 | 
					    if (parseMMapEvents())
 | 
				
			||||||
      errs() << "PERF2BOLT: failed to parse mmap events\n";
 | 
					      errs() << "PERF2BOLT: failed to parse mmap events\n";
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  prepareToParse("task events", TaskEventsPPI);
 | 
					  prepareToParse("task events", TaskEventsPPI);
 | 
				
			||||||
  if (parseTaskEvents()) {
 | 
					  if (parseTaskEvents())
 | 
				
			||||||
    errs() << "PERF2BOLT: failed to parse task events\n";
 | 
					    errs() << "PERF2BOLT: failed to parse task events\n";
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  filterBinaryMMapInfo();
 | 
					  filterBinaryMMapInfo();
 | 
				
			||||||
  prepareToParse("events", MainEventsPPI);
 | 
					  prepareToParse("events", MainEventsPPI);
 | 
				
			||||||
| 
						 | 
					@ -551,15 +544,14 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ((!opts::BasicAggregation && parseBranchEvents()) ||
 | 
					  if ((!opts::BasicAggregation && parseBranchEvents()) ||
 | 
				
			||||||
      (opts::BasicAggregation && parseBasicEvents())) {
 | 
					      (opts::BasicAggregation && parseBasicEvents()))
 | 
				
			||||||
    errs() << "PERF2BOLT: failed to parse samples\n";
 | 
					    errs() << "PERF2BOLT: failed to parse samples\n";
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // We can finish early if the goal is just to generate data for autofdo
 | 
					  // We can finish early if the goal is just to generate data for autofdo
 | 
				
			||||||
  if (opts::WriteAutoFDOData) {
 | 
					  if (opts::WriteAutoFDOData) {
 | 
				
			||||||
    if (std::error_code EC = writeAutoFDOData(opts::OutputFilename)) {
 | 
					    if (std::error_code EC = writeAutoFDOData(opts::OutputFilename))
 | 
				
			||||||
      errs() << "Error writing autofdo data to file: " << EC.message() << "\n";
 | 
					      errs() << "Error writing autofdo data to file: " << EC.message() << "\n";
 | 
				
			||||||
    }
 | 
					
 | 
				
			||||||
    deleteTempFiles();
 | 
					    deleteTempFiles();
 | 
				
			||||||
    exit(0);
 | 
					    exit(0);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -597,10 +589,9 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
 | 
				
			||||||
  ParsingBuf = FileBuf->getBuffer();
 | 
					  ParsingBuf = FileBuf->getBuffer();
 | 
				
			||||||
  Col = 0;
 | 
					  Col = 0;
 | 
				
			||||||
  Line = 1;
 | 
					  Line = 1;
 | 
				
			||||||
  if (const std::error_code EC = parseMemEvents()) {
 | 
					  if (const std::error_code EC = parseMemEvents())
 | 
				
			||||||
    errs() << "PERF2BOLT: failed to parse memory events: " << EC.message()
 | 
					    errs() << "PERF2BOLT: failed to parse memory events: " << EC.message()
 | 
				
			||||||
           << '\n';
 | 
					           << '\n';
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  deleteTempFiles();
 | 
					  deleteTempFiles();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -616,9 +607,8 @@ Error DataAggregator::readProfile(BinaryContext &BC) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (opts::AggregateOnly) {
 | 
					  if (opts::AggregateOnly) {
 | 
				
			||||||
    if (std::error_code EC = writeAggregatedFile(opts::OutputFilename)) {
 | 
					    if (std::error_code EC = writeAggregatedFile(opts::OutputFilename))
 | 
				
			||||||
      report_error("cannot create output data file", EC);
 | 
					      report_error("cannot create output data file", EC);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return Error::success();
 | 
					  return Error::success();
 | 
				
			||||||
| 
						 | 
					@ -844,10 +834,9 @@ bool DataAggregator::doTrace(const LBREntry &First, const LBREntry &Second,
 | 
				
			||||||
                    << FromFunc->getPrintName() << ":"
 | 
					                    << FromFunc->getPrintName() << ":"
 | 
				
			||||||
                    << Twine::utohexstr(First.To) << " to "
 | 
					                    << Twine::utohexstr(First.To) << " to "
 | 
				
			||||||
                    << Twine::utohexstr(Second.From) << ".\n");
 | 
					                    << Twine::utohexstr(Second.From) << ".\n");
 | 
				
			||||||
  for (const std::pair<uint64_t, uint64_t> &Pair : *FTs) {
 | 
					  for (const std::pair<uint64_t, uint64_t> &Pair : *FTs)
 | 
				
			||||||
    doIntraBranch(*FromFunc, Pair.first + FromFunc->getAddress(),
 | 
					    doIntraBranch(*FromFunc, Pair.first + FromFunc->getAddress(),
 | 
				
			||||||
                  Pair.second + FromFunc->getAddress(), Count, false);
 | 
					                  Pair.second + FromFunc->getAddress(), Count, false);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -885,12 +874,11 @@ bool DataAggregator::recordTrace(
 | 
				
			||||||
    BinaryBasicBlock *PrevBB = BF.BasicBlocksLayout[FromBB->getIndex() - 1];
 | 
					    BinaryBasicBlock *PrevBB = BF.BasicBlocksLayout[FromBB->getIndex() - 1];
 | 
				
			||||||
    if (PrevBB->getSuccessor(FromBB->getLabel())) {
 | 
					    if (PrevBB->getSuccessor(FromBB->getLabel())) {
 | 
				
			||||||
      const MCInst *Instr = PrevBB->getLastNonPseudoInstr();
 | 
					      const MCInst *Instr = PrevBB->getLastNonPseudoInstr();
 | 
				
			||||||
      if (Instr && BC.MIB->isCall(*Instr)) {
 | 
					      if (Instr && BC.MIB->isCall(*Instr))
 | 
				
			||||||
        FromBB = PrevBB;
 | 
					        FromBB = PrevBB;
 | 
				
			||||||
      } else {
 | 
					      else
 | 
				
			||||||
        LLVM_DEBUG(dbgs() << "invalid incoming LBR (no call): " << FirstLBR
 | 
					        LLVM_DEBUG(dbgs() << "invalid incoming LBR (no call): " << FirstLBR
 | 
				
			||||||
                          << '\n');
 | 
					                          << '\n');
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      LLVM_DEBUG(dbgs() << "invalid incoming LBR: " << FirstLBR << '\n');
 | 
					      LLVM_DEBUG(dbgs() << "invalid incoming LBR: " << FirstLBR << '\n');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -899,9 +887,8 @@ bool DataAggregator::recordTrace(
 | 
				
			||||||
  // Fill out information for fall-through edges. The From and To could be
 | 
					  // Fill out information for fall-through edges. The From and To could be
 | 
				
			||||||
  // within the same basic block, e.g. when two call instructions are in the
 | 
					  // within the same basic block, e.g. when two call instructions are in the
 | 
				
			||||||
  // same block. In this case we skip the processing.
 | 
					  // same block. In this case we skip the processing.
 | 
				
			||||||
  if (FromBB == ToBB) {
 | 
					  if (FromBB == ToBB)
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Process blocks in the original layout order.
 | 
					  // Process blocks in the original layout order.
 | 
				
			||||||
  BinaryBasicBlock *BB = BF.BasicBlocksLayout[FromBB->getIndex()];
 | 
					  BinaryBasicBlock *BB = BF.BasicBlocksLayout[FromBB->getIndex()];
 | 
				
			||||||
| 
						 | 
					@ -925,11 +912,11 @@ bool DataAggregator::recordTrace(
 | 
				
			||||||
    if (Branches) {
 | 
					    if (Branches) {
 | 
				
			||||||
      const MCInst *Instr = BB->getLastNonPseudoInstr();
 | 
					      const MCInst *Instr = BB->getLastNonPseudoInstr();
 | 
				
			||||||
      uint64_t Offset = 0;
 | 
					      uint64_t Offset = 0;
 | 
				
			||||||
      if (Instr) {
 | 
					      if (Instr)
 | 
				
			||||||
        Offset = BC.MIB->getAnnotationWithDefault<uint32_t>(*Instr, "Offset");
 | 
					        Offset = BC.MIB->getAnnotationWithDefault<uint32_t>(*Instr, "Offset");
 | 
				
			||||||
      } else {
 | 
					      else
 | 
				
			||||||
        Offset = BB->getOffset();
 | 
					        Offset = BB->getOffset();
 | 
				
			||||||
      }
 | 
					
 | 
				
			||||||
      Branches->emplace_back(Offset, NextBB->getOffset());
 | 
					      Branches->emplace_back(Offset, NextBB->getOffset());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1039,9 +1026,9 @@ ErrorOr<LBREntry> DataAggregator::parseLBREntry() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool DataAggregator::checkAndConsumeFS() {
 | 
					bool DataAggregator::checkAndConsumeFS() {
 | 
				
			||||||
  if (ParsingBuf[0] != FieldSeparator) {
 | 
					  if (ParsingBuf[0] != FieldSeparator)
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					
 | 
				
			||||||
  ParsingBuf = ParsingBuf.drop_front(1);
 | 
					  ParsingBuf = ParsingBuf.drop_front(1);
 | 
				
			||||||
  Col += 1;
 | 
					  Col += 1;
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
| 
						 | 
					@ -1128,9 +1115,8 @@ ErrorOr<DataAggregator::PerfBasicSample> DataAggregator::parseBasicSample() {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ErrorOr<uint64_t> AddrRes = parseHexField(FieldSeparator, true);
 | 
					  ErrorOr<uint64_t> AddrRes = parseHexField(FieldSeparator, true);
 | 
				
			||||||
  if (std::error_code EC = AddrRes.getError()) {
 | 
					  if (std::error_code EC = AddrRes.getError())
 | 
				
			||||||
    return EC;
 | 
					    return EC;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!checkAndConsumeNewLine()) {
 | 
					  if (!checkAndConsumeNewLine()) {
 | 
				
			||||||
    reportError("expected end of line");
 | 
					    reportError("expected end of line");
 | 
				
			||||||
| 
						 | 
					@ -1175,9 +1161,8 @@ ErrorOr<DataAggregator::PerfMemSample> DataAggregator::parseMemSample() {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ErrorOr<uint64_t> AddrRes = parseHexField(FieldSeparator);
 | 
					  ErrorOr<uint64_t> AddrRes = parseHexField(FieldSeparator);
 | 
				
			||||||
  if (std::error_code EC = AddrRes.getError()) {
 | 
					  if (std::error_code EC = AddrRes.getError())
 | 
				
			||||||
    return EC;
 | 
					    return EC;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  while (checkAndConsumeFS()) {
 | 
					  while (checkAndConsumeFS()) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -1363,11 +1348,10 @@ std::error_code DataAggregator::printLBRHeatMap() {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HM.print(opts::HeatmapFile);
 | 
					  HM.print(opts::HeatmapFile);
 | 
				
			||||||
  if (opts::HeatmapFile == "-") {
 | 
					  if (opts::HeatmapFile == "-")
 | 
				
			||||||
    HM.printCDF(opts::HeatmapFile);
 | 
					    HM.printCDF(opts::HeatmapFile);
 | 
				
			||||||
  } else {
 | 
					  else
 | 
				
			||||||
    HM.printCDF(opts::HeatmapFile + ".csv");
 | 
					    HM.printCDF(opts::HeatmapFile + ".csv");
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return std::error_code();
 | 
					  return std::error_code();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1432,11 +1416,10 @@ std::error_code DataAggregator::parseBranchEvents() {
 | 
				
			||||||
            getBinaryFunctionContainingAddress(TraceFrom);
 | 
					            getBinaryFunctionContainingAddress(TraceFrom);
 | 
				
			||||||
        if (TraceBF && TraceBF->containsAddress(TraceTo)) {
 | 
					        if (TraceBF && TraceBF->containsAddress(TraceTo)) {
 | 
				
			||||||
          FTInfo &Info = FallthroughLBRs[Trace(TraceFrom, TraceTo)];
 | 
					          FTInfo &Info = FallthroughLBRs[Trace(TraceFrom, TraceTo)];
 | 
				
			||||||
          if (TraceBF->containsAddress(LBR.From)) {
 | 
					          if (TraceBF->containsAddress(LBR.From))
 | 
				
			||||||
            ++Info.InternCount;
 | 
					            ++Info.InternCount;
 | 
				
			||||||
          } else {
 | 
					          else
 | 
				
			||||||
            ++Info.ExternCount;
 | 
					            ++Info.ExternCount;
 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          if (TraceBF && getBinaryFunctionContainingAddress(TraceTo)) {
 | 
					          if (TraceBF && getBinaryFunctionContainingAddress(TraceTo)) {
 | 
				
			||||||
            LLVM_DEBUG(dbgs()
 | 
					            LLVM_DEBUG(dbgs()
 | 
				
			||||||
| 
						 | 
					@ -1497,13 +1480,12 @@ std::error_code DataAggregator::parseBranchEvents() {
 | 
				
			||||||
  auto printColored = [](raw_ostream &OS, float Percent, float T1, float T2) {
 | 
					  auto printColored = [](raw_ostream &OS, float Percent, float T1, float T2) {
 | 
				
			||||||
    OS << " (";
 | 
					    OS << " (";
 | 
				
			||||||
    if (OS.has_colors()) {
 | 
					    if (OS.has_colors()) {
 | 
				
			||||||
      if (Percent > T2) {
 | 
					      if (Percent > T2)
 | 
				
			||||||
        OS.changeColor(raw_ostream::RED);
 | 
					        OS.changeColor(raw_ostream::RED);
 | 
				
			||||||
      } else if (Percent > T1) {
 | 
					      else if (Percent > T1)
 | 
				
			||||||
        OS.changeColor(raw_ostream::YELLOW);
 | 
					        OS.changeColor(raw_ostream::YELLOW);
 | 
				
			||||||
      } else {
 | 
					      else
 | 
				
			||||||
        OS.changeColor(raw_ostream::GREEN);
 | 
					        OS.changeColor(raw_ostream::GREEN);
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    OS << format("%.1f%%", Percent);
 | 
					    OS << format("%.1f%%", Percent);
 | 
				
			||||||
    if (OS.has_colors())
 | 
					    if (OS.has_colors())
 | 
				
			||||||
| 
						 | 
					@ -1527,10 +1509,9 @@ std::error_code DataAggregator::parseBranchEvents() {
 | 
				
			||||||
      outs() << "PERF2BOLT: " << IgnoredSamples << " samples";
 | 
					      outs() << "PERF2BOLT: " << IgnoredSamples << " samples";
 | 
				
			||||||
      printColored(outs(), PercentIgnored, 20, 50);
 | 
					      printColored(outs(), PercentIgnored, 20, 50);
 | 
				
			||||||
      outs() << " were ignored\n";
 | 
					      outs() << " were ignored\n";
 | 
				
			||||||
      if (PercentIgnored > 50.0f) {
 | 
					      if (PercentIgnored > 50.0f)
 | 
				
			||||||
        errs() << "PERF2BOLT-WARNING: less than 50% of all recorded samples "
 | 
					        errs() << "PERF2BOLT-WARNING: less than 50% of all recorded samples "
 | 
				
			||||||
                  "were attributed to the input binary\n";
 | 
					                  "were attributed to the input binary\n";
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  outs() << "PERF2BOLT: traces mismatching disassembled function contents: "
 | 
					  outs() << "PERF2BOLT: traces mismatching disassembled function contents: "
 | 
				
			||||||
| 
						 | 
					@ -1541,18 +1522,16 @@ std::error_code DataAggregator::parseBranchEvents() {
 | 
				
			||||||
    printColored(outs(), Perc, 5, 10);
 | 
					    printColored(outs(), Perc, 5, 10);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  outs() << "\n";
 | 
					  outs() << "\n";
 | 
				
			||||||
  if (Perc > 10.0f) {
 | 
					  if (Perc > 10.0f)
 | 
				
			||||||
    outs() << "\n !! WARNING !! This high mismatch ratio indicates the input "
 | 
					    outs() << "\n !! WARNING !! This high mismatch ratio indicates the input "
 | 
				
			||||||
              "binary is probably not the same binary used during profiling "
 | 
					              "binary is probably not the same binary used during profiling "
 | 
				
			||||||
              "collection. The generated data may be ineffective for improving "
 | 
					              "collection. The generated data may be ineffective for improving "
 | 
				
			||||||
              "performance.\n\n";
 | 
					              "performance.\n\n";
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  outs() << "PERF2BOLT: out of range traces involving unknown regions: "
 | 
					  outs() << "PERF2BOLT: out of range traces involving unknown regions: "
 | 
				
			||||||
         << NumLongRangeTraces;
 | 
					         << NumLongRangeTraces;
 | 
				
			||||||
  if (NumTraces > 0) {
 | 
					  if (NumTraces > 0)
 | 
				
			||||||
    outs() << format(" (%.1f%%)", NumLongRangeTraces * 100.0f / NumTraces);
 | 
					    outs() << format(" (%.1f%%)", NumLongRangeTraces * 100.0f / NumTraces);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  outs() << "\n";
 | 
					  outs() << "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (NumColdSamples > 0) {
 | 
					  if (NumColdSamples > 0) {
 | 
				
			||||||
| 
						 | 
					@ -1560,12 +1539,11 @@ std::error_code DataAggregator::parseBranchEvents() {
 | 
				
			||||||
    outs() << "PERF2BOLT: " << NumColdSamples
 | 
					    outs() << "PERF2BOLT: " << NumColdSamples
 | 
				
			||||||
           << format(" (%.1f%%)", ColdSamples)
 | 
					           << format(" (%.1f%%)", ColdSamples)
 | 
				
			||||||
           << " samples recorded in cold regions of split functions.\n";
 | 
					           << " samples recorded in cold regions of split functions.\n";
 | 
				
			||||||
    if (ColdSamples > 5.0f) {
 | 
					    if (ColdSamples > 5.0f)
 | 
				
			||||||
      outs()
 | 
					      outs()
 | 
				
			||||||
          << "WARNING: The BOLT-processed binary where samples were collected "
 | 
					          << "WARNING: The BOLT-processed binary where samples were collected "
 | 
				
			||||||
             "likely used bad data or your service observed a large shift in "
 | 
					             "likely used bad data or your service observed a large shift in "
 | 
				
			||||||
             "profile. You may want to audit this.\n";
 | 
					             "profile. You may want to audit this.\n";
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return std::error_code();
 | 
					  return std::error_code();
 | 
				
			||||||
| 
						 | 
					@ -1581,9 +1559,8 @@ void DataAggregator::processBranchEvents() {
 | 
				
			||||||
    const FTInfo &Info = AggrLBR.second;
 | 
					    const FTInfo &Info = AggrLBR.second;
 | 
				
			||||||
    LBREntry First{Loc.From, Loc.From, false};
 | 
					    LBREntry First{Loc.From, Loc.From, false};
 | 
				
			||||||
    LBREntry Second{Loc.To, Loc.To, false};
 | 
					    LBREntry Second{Loc.To, Loc.To, false};
 | 
				
			||||||
    if (Info.InternCount) {
 | 
					    if (Info.InternCount)
 | 
				
			||||||
      doTrace(First, Second, Info.InternCount);
 | 
					      doTrace(First, Second, Info.InternCount);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (Info.ExternCount) {
 | 
					    if (Info.ExternCount) {
 | 
				
			||||||
      First.From = 0;
 | 
					      First.From = 0;
 | 
				
			||||||
      doTrace(First, Second, Info.ExternCount);
 | 
					      doTrace(First, Second, Info.ExternCount);
 | 
				
			||||||
| 
						 | 
					@ -1646,13 +1623,12 @@ void DataAggregator::processBasicEvents() {
 | 
				
			||||||
    outs() << " (";
 | 
					    outs() << " (";
 | 
				
			||||||
    Perc = OutOfRangeSamples * 100.0f / NumSamples;
 | 
					    Perc = OutOfRangeSamples * 100.0f / NumSamples;
 | 
				
			||||||
    if (outs().has_colors()) {
 | 
					    if (outs().has_colors()) {
 | 
				
			||||||
      if (Perc > 60.0f) {
 | 
					      if (Perc > 60.0f)
 | 
				
			||||||
        outs().changeColor(raw_ostream::RED);
 | 
					        outs().changeColor(raw_ostream::RED);
 | 
				
			||||||
      } else if (Perc > 40.0f) {
 | 
					      else if (Perc > 40.0f)
 | 
				
			||||||
        outs().changeColor(raw_ostream::YELLOW);
 | 
					        outs().changeColor(raw_ostream::YELLOW);
 | 
				
			||||||
      } else {
 | 
					      else
 | 
				
			||||||
        outs().changeColor(raw_ostream::GREEN);
 | 
					        outs().changeColor(raw_ostream::GREEN);
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outs() << format("%.1f%%", Perc);
 | 
					    outs() << format("%.1f%%", Perc);
 | 
				
			||||||
    if (outs().has_colors())
 | 
					    if (outs().has_colors())
 | 
				
			||||||
| 
						 | 
					@ -1660,12 +1636,11 @@ void DataAggregator::processBasicEvents() {
 | 
				
			||||||
    outs() << ")";
 | 
					    outs() << ")";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  outs() << "\n";
 | 
					  outs() << "\n";
 | 
				
			||||||
  if (Perc > 80.0f) {
 | 
					  if (Perc > 80.0f)
 | 
				
			||||||
    outs() << "\n !! WARNING !! This high mismatch ratio indicates the input "
 | 
					    outs() << "\n !! WARNING !! This high mismatch ratio indicates the input "
 | 
				
			||||||
              "binary is probably not the same binary used during profiling "
 | 
					              "binary is probably not the same binary used during profiling "
 | 
				
			||||||
              "collection. The generated data may be ineffective for improving "
 | 
					              "collection. The generated data may be ineffective for improving "
 | 
				
			||||||
              "performance.\n\n";
 | 
					              "performance.\n\n";
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::error_code DataAggregator::parseMemEvents() {
 | 
					std::error_code DataAggregator::parseMemEvents() {
 | 
				
			||||||
| 
						 | 
					@ -1784,13 +1759,12 @@ void DataAggregator::processPreAggregated() {
 | 
				
			||||||
    outs() << " (";
 | 
					    outs() << " (";
 | 
				
			||||||
    Perc = NumInvalidTraces * 100.0f / NumTraces;
 | 
					    Perc = NumInvalidTraces * 100.0f / NumTraces;
 | 
				
			||||||
    if (outs().has_colors()) {
 | 
					    if (outs().has_colors()) {
 | 
				
			||||||
      if (Perc > 10.0f) {
 | 
					      if (Perc > 10.0f)
 | 
				
			||||||
        outs().changeColor(raw_ostream::RED);
 | 
					        outs().changeColor(raw_ostream::RED);
 | 
				
			||||||
      } else if (Perc > 5.0f) {
 | 
					      else if (Perc > 5.0f)
 | 
				
			||||||
        outs().changeColor(raw_ostream::YELLOW);
 | 
					        outs().changeColor(raw_ostream::YELLOW);
 | 
				
			||||||
      } else {
 | 
					      else
 | 
				
			||||||
        outs().changeColor(raw_ostream::GREEN);
 | 
					        outs().changeColor(raw_ostream::GREEN);
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    outs() << format("%.1f%%", Perc);
 | 
					    outs() << format("%.1f%%", Perc);
 | 
				
			||||||
    if (outs().has_colors())
 | 
					    if (outs().has_colors())
 | 
				
			||||||
| 
						 | 
					@ -1798,18 +1772,16 @@ void DataAggregator::processPreAggregated() {
 | 
				
			||||||
    outs() << ")";
 | 
					    outs() << ")";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  outs() << "\n";
 | 
					  outs() << "\n";
 | 
				
			||||||
  if (Perc > 10.0f) {
 | 
					  if (Perc > 10.0f)
 | 
				
			||||||
    outs() << "\n !! WARNING !! This high mismatch ratio indicates the input "
 | 
					    outs() << "\n !! WARNING !! This high mismatch ratio indicates the input "
 | 
				
			||||||
              "binary is probably not the same binary used during profiling "
 | 
					              "binary is probably not the same binary used during profiling "
 | 
				
			||||||
              "collection. The generated data may be ineffective for improving "
 | 
					              "collection. The generated data may be ineffective for improving "
 | 
				
			||||||
              "performance.\n\n";
 | 
					              "performance.\n\n";
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  outs() << "PERF2BOLT: Out of range traces involving unknown regions: "
 | 
					  outs() << "PERF2BOLT: Out of range traces involving unknown regions: "
 | 
				
			||||||
         << NumLongRangeTraces;
 | 
					         << NumLongRangeTraces;
 | 
				
			||||||
  if (NumTraces > 0) {
 | 
					  if (NumTraces > 0)
 | 
				
			||||||
    outs() << format(" (%.1f%%)", NumLongRangeTraces * 100.0f / NumTraces);
 | 
					    outs() << format(" (%.1f%%)", NumLongRangeTraces * 100.0f / NumTraces);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  outs() << "\n";
 | 
					  outs() << "\n";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1823,9 +1795,8 @@ Optional<int32_t> DataAggregator::parseCommExecEvent() {
 | 
				
			||||||
  StringRef Line = ParsingBuf.substr(0, LineEnd);
 | 
					  StringRef Line = ParsingBuf.substr(0, LineEnd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  size_t Pos = Line.find("PERF_RECORD_COMM exec");
 | 
					  size_t Pos = Line.find("PERF_RECORD_COMM exec");
 | 
				
			||||||
  if (Pos == StringRef::npos) {
 | 
					  if (Pos == StringRef::npos)
 | 
				
			||||||
    return NoneType();
 | 
					    return NoneType();
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  Line = Line.drop_front(Pos);
 | 
					  Line = Line.drop_front(Pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Line:
 | 
					  // Line:
 | 
				
			||||||
| 
						 | 
					@ -1848,9 +1819,8 @@ Optional<uint64_t> parsePerfTime(const StringRef TimeStr) {
 | 
				
			||||||
  uint64_t SecTime;
 | 
					  uint64_t SecTime;
 | 
				
			||||||
  uint64_t USecTime;
 | 
					  uint64_t USecTime;
 | 
				
			||||||
  if (SecTimeStr.getAsInteger(10, SecTime) ||
 | 
					  if (SecTimeStr.getAsInteger(10, SecTime) ||
 | 
				
			||||||
      USecTimeStr.getAsInteger(10, USecTime)) {
 | 
					      USecTimeStr.getAsInteger(10, USecTime))
 | 
				
			||||||
    return NoneType();
 | 
					    return NoneType();
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return SecTime * 1000000ULL + USecTime;
 | 
					  return SecTime * 1000000ULL + USecTime;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1930,9 +1900,8 @@ DataAggregator::parseMMapEvent() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const StringRef TimeStr =
 | 
					  const StringRef TimeStr =
 | 
				
			||||||
      Line.substr(0, Pos).rsplit(':').first.rsplit(FieldSeparator).second;
 | 
					      Line.substr(0, Pos).rsplit(':').first.rsplit(FieldSeparator).second;
 | 
				
			||||||
  if (Optional<uint64_t> TimeRes = parsePerfTime(TimeStr)) {
 | 
					  if (Optional<uint64_t> TimeRes = parsePerfTime(TimeStr))
 | 
				
			||||||
    ParsedInfo.Time = *TimeRes;
 | 
					    ParsedInfo.Time = *TimeRes;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Line = Line.drop_front(Pos);
 | 
					  Line = Line.drop_front(Pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2012,12 +1981,11 @@ std::error_code DataAggregator::parseMMapEvents() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  LLVM_DEBUG({
 | 
					  LLVM_DEBUG({
 | 
				
			||||||
    dbgs() << "FileName -> mmap info:\n";
 | 
					    dbgs() << "FileName -> mmap info:\n";
 | 
				
			||||||
    for (const std::pair<const StringRef, MMapInfo> &Pair : GlobalMMapInfo) {
 | 
					    for (const std::pair<const StringRef, MMapInfo> &Pair : GlobalMMapInfo)
 | 
				
			||||||
      dbgs() << "  " << Pair.first << " : " << Pair.second.PID << " [0x"
 | 
					      dbgs() << "  " << Pair.first << " : " << Pair.second.PID << " [0x"
 | 
				
			||||||
             << Twine::utohexstr(Pair.second.BaseAddress) << ", "
 | 
					             << Twine::utohexstr(Pair.second.BaseAddress) << ", "
 | 
				
			||||||
             << Twine::utohexstr(Pair.second.Size) << " @ "
 | 
					             << Twine::utohexstr(Pair.second.Size) << " @ "
 | 
				
			||||||
             << Twine::utohexstr(Pair.second.Offset) << "]\n";
 | 
					             << Twine::utohexstr(Pair.second.Offset) << "]\n";
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  StringRef NameToUse = llvm::sys::path::filename(BC->getFilename());
 | 
					  StringRef NameToUse = llvm::sys::path::filename(BC->getFilename());
 | 
				
			||||||
| 
						 | 
					@ -2063,9 +2031,8 @@ std::error_code DataAggregator::parseMMapEvents() {
 | 
				
			||||||
    if (!GlobalMMapInfo.empty()) {
 | 
					    if (!GlobalMMapInfo.empty()) {
 | 
				
			||||||
      errs() << " Profile for the following binary name(s) is available:\n";
 | 
					      errs() << " Profile for the following binary name(s) is available:\n";
 | 
				
			||||||
      for (auto I = GlobalMMapInfo.begin(), IE = GlobalMMapInfo.end(); I != IE;
 | 
					      for (auto I = GlobalMMapInfo.begin(), IE = GlobalMMapInfo.end(); I != IE;
 | 
				
			||||||
           I = GlobalMMapInfo.upper_bound(I->first)) {
 | 
					           I = GlobalMMapInfo.upper_bound(I->first))
 | 
				
			||||||
        errs() << "  " << I->first << '\n';
 | 
					        errs() << "  " << I->first << '\n';
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      errs() << "Please rename the input binary.\n";
 | 
					      errs() << "Please rename the input binary.\n";
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      errs() << " Failed to extract any binary name from a profile.\n";
 | 
					      errs() << " Failed to extract any binary name from a profile.\n";
 | 
				
			||||||
| 
						 | 
					@ -2088,9 +2055,8 @@ std::error_code DataAggregator::parseTaskEvents() {
 | 
				
			||||||
    if (Optional<int32_t> CommInfo = parseCommExecEvent()) {
 | 
					    if (Optional<int32_t> CommInfo = parseCommExecEvent()) {
 | 
				
			||||||
      // Remove forked child that ran execve
 | 
					      // Remove forked child that ran execve
 | 
				
			||||||
      auto MMapInfoIter = BinaryMMapInfo.find(*CommInfo);
 | 
					      auto MMapInfoIter = BinaryMMapInfo.find(*CommInfo);
 | 
				
			||||||
      if (MMapInfoIter != BinaryMMapInfo.end() && MMapInfoIter->second.Forked) {
 | 
					      if (MMapInfoIter != BinaryMMapInfo.end() && MMapInfoIter->second.Forked)
 | 
				
			||||||
        BinaryMMapInfo.erase(MMapInfoIter);
 | 
					        BinaryMMapInfo.erase(MMapInfoIter);
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      consumeRestOfLine();
 | 
					      consumeRestOfLine();
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -2122,11 +2088,10 @@ std::error_code DataAggregator::parseTaskEvents() {
 | 
				
			||||||
         << BinaryMMapInfo.size() << " PID(s)\n";
 | 
					         << BinaryMMapInfo.size() << " PID(s)\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  LLVM_DEBUG({
 | 
					  LLVM_DEBUG({
 | 
				
			||||||
    for (std::pair<const uint64_t, MMapInfo> &MMI : BinaryMMapInfo) {
 | 
					    for (std::pair<const uint64_t, MMapInfo> &MMI : BinaryMMapInfo)
 | 
				
			||||||
      outs() << "  " << MMI.second.PID << (MMI.second.Forked ? " (forked)" : "")
 | 
					      outs() << "  " << MMI.second.PID << (MMI.second.Forked ? " (forked)" : "")
 | 
				
			||||||
             << ": (0x" << Twine::utohexstr(MMI.second.BaseAddress) << ": 0x"
 | 
					             << ": (0x" << Twine::utohexstr(MMI.second.BaseAddress) << ": 0x"
 | 
				
			||||||
             << Twine::utohexstr(MMI.second.Size) << ")\n";
 | 
					             << Twine::utohexstr(MMI.second.Size) << ")\n";
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return std::error_code();
 | 
					  return std::error_code();
 | 
				
			||||||
| 
						 | 
					@ -2187,9 +2152,8 @@ DataAggregator::writeAggregatedFile(StringRef OutputFilename) const {
 | 
				
			||||||
    OutFile << "boltedcollection\n";
 | 
					    OutFile << "boltedcollection\n";
 | 
				
			||||||
  if (opts::BasicAggregation) {
 | 
					  if (opts::BasicAggregation) {
 | 
				
			||||||
    OutFile << "no_lbr";
 | 
					    OutFile << "no_lbr";
 | 
				
			||||||
    for (const StringMapEntry<NoneType> &Entry : EventNames) {
 | 
					    for (const StringMapEntry<NoneType> &Entry : EventNames)
 | 
				
			||||||
      OutFile << " " << Entry.getKey();
 | 
					      OutFile << " " << Entry.getKey();
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    OutFile << "\n";
 | 
					    OutFile << "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const StringMapEntry<FuncSampleData> &Func : NamesToSamples) {
 | 
					    for (const StringMapEntry<FuncSampleData> &Func : NamesToSamples) {
 | 
				
			||||||
| 
						 | 
					@ -2246,9 +2210,8 @@ void DataAggregator::dump(const LBREntry &LBR) const {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DataAggregator::dump(const PerfBranchSample &Sample) const {
 | 
					void DataAggregator::dump(const PerfBranchSample &Sample) const {
 | 
				
			||||||
  Diag << "Sample LBR entries: " << Sample.LBR.size() << "\n";
 | 
					  Diag << "Sample LBR entries: " << Sample.LBR.size() << "\n";
 | 
				
			||||||
  for (const LBREntry &LBR : Sample.LBR) {
 | 
					  for (const LBREntry &LBR : Sample.LBR)
 | 
				
			||||||
    dump(LBR);
 | 
					    dump(LBR);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DataAggregator::dump(const PerfMemSample &Sample) const {
 | 
					void DataAggregator::dump(const PerfMemSample &Sample) const {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,23 +42,21 @@ namespace bolt {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Optional<StringRef> getLTOCommonName(const StringRef Name) {
 | 
					Optional<StringRef> getLTOCommonName(const StringRef Name) {
 | 
				
			||||||
  size_t LTOSuffixPos = Name.find(".lto_priv.");
 | 
					  size_t LTOSuffixPos = Name.find(".lto_priv.");
 | 
				
			||||||
  if (LTOSuffixPos != StringRef::npos) {
 | 
					  if (LTOSuffixPos != StringRef::npos)
 | 
				
			||||||
    return Name.substr(0, LTOSuffixPos + 10);
 | 
					    return Name.substr(0, LTOSuffixPos + 10);
 | 
				
			||||||
  } else if ((LTOSuffixPos = Name.find(".constprop.")) != StringRef::npos) {
 | 
					  if ((LTOSuffixPos = Name.find(".constprop.")) != StringRef::npos)
 | 
				
			||||||
    return Name.substr(0, LTOSuffixPos + 11);
 | 
					    return Name.substr(0, LTOSuffixPos + 11);
 | 
				
			||||||
  } else {
 | 
					  return NoneType();
 | 
				
			||||||
    return NoneType();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Return true if the function name can change across compilations.
 | 
					/// Return true if the function name can change across compilations.
 | 
				
			||||||
bool hasVolatileName(const BinaryFunction &BF) {
 | 
					bool hasVolatileName(const BinaryFunction &BF) {
 | 
				
			||||||
  for (const StringRef Name : BF.getNames()) {
 | 
					  for (const StringRef Name : BF.getNames())
 | 
				
			||||||
    if (getLTOCommonName(Name))
 | 
					    if (getLTOCommonName(Name))
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
  }
 | 
					
 | 
				
			||||||
  return false;
 | 
					  return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -134,9 +132,8 @@ uint64_t FuncSampleData::getSamples(uint64_t Start, uint64_t End) const {
 | 
				
			||||||
  uint64_t Result = 0;
 | 
					  uint64_t Result = 0;
 | 
				
			||||||
  for (auto I = std::lower_bound(Data.begin(), Data.end(), Start, Compare()),
 | 
					  for (auto I = std::lower_bound(Data.begin(), Data.end(), Start, Compare()),
 | 
				
			||||||
            E = std::lower_bound(Data.begin(), Data.end(), End, Compare());
 | 
					            E = std::lower_bound(Data.begin(), Data.end(), End, Compare());
 | 
				
			||||||
       I != E; ++I) {
 | 
					       I != E; ++I)
 | 
				
			||||||
    Result += I->Hits;
 | 
					    Result += I->Hits;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return Result;
 | 
					  return Result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -206,10 +203,10 @@ void BranchInfo::print(raw_ostream &OS) const {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ErrorOr<const BranchInfo &> FuncBranchData::getBranch(uint64_t From,
 | 
					ErrorOr<const BranchInfo &> FuncBranchData::getBranch(uint64_t From,
 | 
				
			||||||
                                                      uint64_t To) const {
 | 
					                                                      uint64_t To) const {
 | 
				
			||||||
  for (const BranchInfo &I : Data) {
 | 
					  for (const BranchInfo &I : Data)
 | 
				
			||||||
    if (I.From.Offset == From && I.To.Offset == To && I.From.Name == I.To.Name)
 | 
					    if (I.From.Offset == From && I.To.Offset == To && I.From.Name == I.To.Name)
 | 
				
			||||||
      return I;
 | 
					      return I;
 | 
				
			||||||
  }
 | 
					
 | 
				
			||||||
  return make_error_code(llvm::errc::invalid_argument);
 | 
					  return make_error_code(llvm::errc::invalid_argument);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -226,10 +223,10 @@ FuncBranchData::getDirectCallBranch(uint64_t From) const {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  auto Range = std::equal_range(Data.begin(), Data.end(), From, Compare());
 | 
					  auto Range = std::equal_range(Data.begin(), Data.end(), From, Compare());
 | 
				
			||||||
  for (auto I = Range.first; I != Range.second; ++I) {
 | 
					  for (auto I = Range.first; I != Range.second; ++I)
 | 
				
			||||||
    if (I->From.Name != I->To.Name)
 | 
					    if (I->From.Name != I->To.Name)
 | 
				
			||||||
      return *I;
 | 
					      return *I;
 | 
				
			||||||
  }
 | 
					
 | 
				
			||||||
  return make_error_code(llvm::errc::invalid_argument);
 | 
					  return make_error_code(llvm::errc::invalid_argument);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -255,18 +252,15 @@ void FuncMemData::update(const Location &Offset, const Location &Addr) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Error DataReader::preprocessProfile(BinaryContext &BC) {
 | 
					Error DataReader::preprocessProfile(BinaryContext &BC) {
 | 
				
			||||||
  if (std::error_code EC = parseInput()) {
 | 
					  if (std::error_code EC = parseInput())
 | 
				
			||||||
    return errorCodeToError(EC);
 | 
					    return errorCodeToError(EC);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (opts::DumpData) {
 | 
					  if (opts::DumpData)
 | 
				
			||||||
    dump();
 | 
					    dump();
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (collectedInBoltedBinary()) {
 | 
					  if (collectedInBoltedBinary())
 | 
				
			||||||
    outs() << "BOLT-INFO: profile collection done on a binary already "
 | 
					    outs() << "BOLT-INFO: profile collection done on a binary already "
 | 
				
			||||||
              "processed by BOLT\n";
 | 
					              "processed by BOLT\n";
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (auto &BFI : BC.getBinaryFunctions()) {
 | 
					  for (auto &BFI : BC.getBinaryFunctions()) {
 | 
				
			||||||
    BinaryFunction &Function = BFI.second;
 | 
					    BinaryFunction &Function = BFI.second;
 | 
				
			||||||
| 
						 | 
					@ -308,17 +302,15 @@ Error DataReader::readProfilePreCFG(BinaryContext &BC) {
 | 
				
			||||||
          BC.MIB->getOrCreateAnnotationAs<MemoryAccessProfile>(
 | 
					          BC.MIB->getOrCreateAnnotationAs<MemoryAccessProfile>(
 | 
				
			||||||
              II->second, "MemoryAccessProfile");
 | 
					              II->second, "MemoryAccessProfile");
 | 
				
			||||||
      BinaryData *BD = nullptr;
 | 
					      BinaryData *BD = nullptr;
 | 
				
			||||||
      if (MI.Addr.IsSymbol) {
 | 
					      if (MI.Addr.IsSymbol)
 | 
				
			||||||
        BD = BC.getBinaryDataByName(MI.Addr.Name);
 | 
					        BD = BC.getBinaryDataByName(MI.Addr.Name);
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      MemAccessProfile.AddressAccessInfo.push_back(
 | 
					      MemAccessProfile.AddressAccessInfo.push_back(
 | 
				
			||||||
          {BD, MI.Addr.Offset, MI.Count});
 | 
					          {BD, MI.Addr.Offset, MI.Count});
 | 
				
			||||||
      auto NextII = std::next(II);
 | 
					      auto NextII = std::next(II);
 | 
				
			||||||
      if (NextII == Function.Instructions.end()) {
 | 
					      if (NextII == Function.Instructions.end())
 | 
				
			||||||
        MemAccessProfile.NextInstrOffset = Function.getSize();
 | 
					        MemAccessProfile.NextInstrOffset = Function.getSize();
 | 
				
			||||||
      } else {
 | 
					      else
 | 
				
			||||||
        MemAccessProfile.NextInstrOffset = II->first;
 | 
					        MemAccessProfile.NextInstrOffset = II->first;
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Function.HasMemoryProfile = true;
 | 
					    Function.HasMemoryProfile = true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -350,13 +342,11 @@ std::error_code DataReader::parseInput() {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  FileBuf = std::move(MB.get());
 | 
					  FileBuf = std::move(MB.get());
 | 
				
			||||||
  ParsingBuf = FileBuf->getBuffer();
 | 
					  ParsingBuf = FileBuf->getBuffer();
 | 
				
			||||||
  if (std::error_code EC = parse()) {
 | 
					  if (std::error_code EC = parse())
 | 
				
			||||||
    return EC;
 | 
					    return EC;
 | 
				
			||||||
  }
 | 
					  if (!ParsingBuf.empty())
 | 
				
			||||||
  if (!ParsingBuf.empty()) {
 | 
					 | 
				
			||||||
    Diag << "WARNING: invalid profile data detected at line " << Line
 | 
					    Diag << "WARNING: invalid profile data detected at line " << Line
 | 
				
			||||||
         << ". Possibly corrupted profile.\n";
 | 
					         << ". Possibly corrupted profile.\n";
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  buildLTONameMaps();
 | 
					  buildLTONameMaps();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -401,9 +391,8 @@ void DataReader::readProfile(BinaryFunction &BF) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uint64_t MismatchedBranches = 0;
 | 
					  uint64_t MismatchedBranches = 0;
 | 
				
			||||||
  for (const BranchInfo &BI : FBD->Data) {
 | 
					  for (const BranchInfo &BI : FBD->Data) {
 | 
				
			||||||
    if (BI.From.Name != BI.To.Name) {
 | 
					    if (BI.From.Name != BI.To.Name)
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!recordBranch(BF, BI.From.Offset, BI.To.Offset, BI.Branches,
 | 
					    if (!recordBranch(BF, BI.From.Offset, BI.To.Offset, BI.Branches,
 | 
				
			||||||
                      BI.Mispreds)) {
 | 
					                      BI.Mispreds)) {
 | 
				
			||||||
| 
						 | 
					@ -523,9 +512,8 @@ float DataReader::evaluateProfileData(BinaryFunction &BF,
 | 
				
			||||||
  // Until we define a minimal profile, we consider an empty branch data to be
 | 
					  // Until we define a minimal profile, we consider an empty branch data to be
 | 
				
			||||||
  // a valid profile. It could happen to a function without branches when we
 | 
					  // a valid profile. It could happen to a function without branches when we
 | 
				
			||||||
  // still have an EntryData for the execution count.
 | 
					  // still have an EntryData for the execution count.
 | 
				
			||||||
  if (BranchData.Data.empty()) {
 | 
					  if (BranchData.Data.empty())
 | 
				
			||||||
    return 1.0f;
 | 
					    return 1.0f;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uint64_t NumMatchedBranches = 0;
 | 
					  uint64_t NumMatchedBranches = 0;
 | 
				
			||||||
  for (const BranchInfo &BI : BranchData.Data) {
 | 
					  for (const BranchInfo &BI : BranchData.Data) {
 | 
				
			||||||
| 
						 | 
					@ -549,9 +537,8 @@ float DataReader::evaluateProfileData(BinaryFunction &BF,
 | 
				
			||||||
      if (Instr && BC.MIB->isPrefix(*Instr))
 | 
					      if (Instr && BC.MIB->isPrefix(*Instr))
 | 
				
			||||||
        Instr = BF.getInstructionAtOffset(BI.From.Offset + 1);
 | 
					        Instr = BF.getInstructionAtOffset(BI.From.Offset + 1);
 | 
				
			||||||
      if (Instr && (BC.MIB->isCall(*Instr) || BC.MIB->isBranch(*Instr) ||
 | 
					      if (Instr && (BC.MIB->isCall(*Instr) || BC.MIB->isBranch(*Instr) ||
 | 
				
			||||||
                    BC.MIB->isReturn(*Instr))) {
 | 
					                    BC.MIB->isReturn(*Instr)))
 | 
				
			||||||
        IsValid = true;
 | 
					        IsValid = true;
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (IsValid) {
 | 
					    if (IsValid) {
 | 
				
			||||||
| 
						 | 
					@ -567,12 +554,11 @@ float DataReader::evaluateProfileData(BinaryFunction &BF,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const float MatchRatio = (float)NumMatchedBranches / BranchData.Data.size();
 | 
					  const float MatchRatio = (float)NumMatchedBranches / BranchData.Data.size();
 | 
				
			||||||
  if (opts::Verbosity >= 2 && NumMatchedBranches < BranchData.Data.size()) {
 | 
					  if (opts::Verbosity >= 2 && NumMatchedBranches < BranchData.Data.size())
 | 
				
			||||||
    errs() << "BOLT-WARNING: profile branches match only "
 | 
					    errs() << "BOLT-WARNING: profile branches match only "
 | 
				
			||||||
           << format("%.1f%%", MatchRatio * 100.0f) << " ("
 | 
					           << format("%.1f%%", MatchRatio * 100.0f) << " ("
 | 
				
			||||||
           << NumMatchedBranches << '/' << BranchData.Data.size()
 | 
					           << NumMatchedBranches << '/' << BranchData.Data.size()
 | 
				
			||||||
           << ") for function " << BF << '\n';
 | 
					           << ") for function " << BF << '\n';
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return MatchRatio;
 | 
					  return MatchRatio;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -592,11 +578,11 @@ void DataReader::readSampleData(BinaryFunction &BF) {
 | 
				
			||||||
  if (NagUser) {
 | 
					  if (NagUser) {
 | 
				
			||||||
    outs()
 | 
					    outs()
 | 
				
			||||||
        << "BOLT-INFO: operating with basic samples profiling data (no LBR).\n";
 | 
					        << "BOLT-INFO: operating with basic samples profiling data (no LBR).\n";
 | 
				
			||||||
    if (NormalizeByInsnCount) {
 | 
					    if (NormalizeByInsnCount)
 | 
				
			||||||
      outs() << "BOLT-INFO: normalizing samples by instruction count.\n";
 | 
					      outs() << "BOLT-INFO: normalizing samples by instruction count.\n";
 | 
				
			||||||
    } else if (NormalizeByCalls) {
 | 
					    else if (NormalizeByCalls)
 | 
				
			||||||
      outs() << "BOLT-INFO: normalizing samples by branches.\n";
 | 
					      outs() << "BOLT-INFO: normalizing samples by branches.\n";
 | 
				
			||||||
    }
 | 
					
 | 
				
			||||||
    NagUser = false;
 | 
					    NagUser = false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  uint64_t LastOffset = BF.getSize();
 | 
					  uint64_t LastOffset = BF.getSize();
 | 
				
			||||||
| 
						 | 
					@ -608,9 +594,9 @@ void DataReader::readSampleData(BinaryFunction &BF) {
 | 
				
			||||||
    // later need to normalize numbers
 | 
					    // later need to normalize numbers
 | 
				
			||||||
    uint64_t NumSamples =
 | 
					    uint64_t NumSamples =
 | 
				
			||||||
        SampleDataOrErr->getSamples(CurOffset, LastOffset) * 1000;
 | 
					        SampleDataOrErr->getSamples(CurOffset, LastOffset) * 1000;
 | 
				
			||||||
    if (NormalizeByInsnCount && I->second->getNumNonPseudos())
 | 
					    if (NormalizeByInsnCount && I->second->getNumNonPseudos()) {
 | 
				
			||||||
      NumSamples /= I->second->getNumNonPseudos();
 | 
					      NumSamples /= I->second->getNumNonPseudos();
 | 
				
			||||||
    else if (NormalizeByCalls) {
 | 
					    } else if (NormalizeByCalls) {
 | 
				
			||||||
      uint32_t NumCalls = I->second->getNumCalls();
 | 
					      uint32_t NumCalls = I->second->getNumCalls();
 | 
				
			||||||
      NumSamples /= NumCalls + 1;
 | 
					      NumSamples /= NumCalls + 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -655,11 +641,10 @@ void DataReader::convertBranchData(BinaryFunction &BF) const {
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto setOrUpdateAnnotation = [&](StringRef Name, uint64_t Count) {
 | 
					    auto setOrUpdateAnnotation = [&](StringRef Name, uint64_t Count) {
 | 
				
			||||||
      if (opts::Verbosity >= 1 && BC.MIB->hasAnnotation(*Instr, Name)) {
 | 
					      if (opts::Verbosity >= 1 && BC.MIB->hasAnnotation(*Instr, Name))
 | 
				
			||||||
        errs() << "BOLT-WARNING: duplicate " << Name << " info for offset 0x"
 | 
					        errs() << "BOLT-WARNING: duplicate " << Name << " info for offset 0x"
 | 
				
			||||||
               << Twine::utohexstr(BI.From.Offset) << " in function " << BF
 | 
					               << Twine::utohexstr(BI.From.Offset) << " in function " << BF
 | 
				
			||||||
               << '\n';
 | 
					               << '\n';
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      auto &Value = BC.MIB->getOrCreateAnnotationAs<uint64_t>(*Instr, Name);
 | 
					      auto &Value = BC.MIB->getOrCreateAnnotationAs<uint64_t>(*Instr, Name);
 | 
				
			||||||
      Value += Count;
 | 
					      Value += Count;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					@ -670,9 +655,8 @@ void DataReader::convertBranchData(BinaryFunction &BF) const {
 | 
				
			||||||
              *Instr, "CallProfile");
 | 
					              *Instr, "CallProfile");
 | 
				
			||||||
      MCSymbol *CalleeSymbol = nullptr;
 | 
					      MCSymbol *CalleeSymbol = nullptr;
 | 
				
			||||||
      if (BI.To.IsSymbol) {
 | 
					      if (BI.To.IsSymbol) {
 | 
				
			||||||
        if (BinaryData *BD = BC.getBinaryDataByName(BI.To.Name)) {
 | 
					        if (BinaryData *BD = BC.getBinaryDataByName(BI.To.Name))
 | 
				
			||||||
          CalleeSymbol = BD->getSymbol();
 | 
					          CalleeSymbol = BD->getSymbol();
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      CSP.emplace_back(CalleeSymbol, BI.Branches, BI.Mispreds);
 | 
					      CSP.emplace_back(CalleeSymbol, BI.Branches, BI.Mispreds);
 | 
				
			||||||
    } else if (BC.MIB->getConditionalTailCall(*Instr)) {
 | 
					    } else if (BC.MIB->getConditionalTailCall(*Instr)) {
 | 
				
			||||||
| 
						 | 
					@ -701,20 +685,18 @@ bool DataReader::recordBranch(BinaryFunction &BF, uint64_t From, uint64_t To,
 | 
				
			||||||
  // BBs as a result of optimizations. In that case, a branch between these
 | 
					  // BBs as a result of optimizations. In that case, a branch between these
 | 
				
			||||||
  // two will be recorded as a branch from A going to A in the source address
 | 
					  // two will be recorded as a branch from A going to A in the source address
 | 
				
			||||||
  // space. Keep processing.
 | 
					  // space. Keep processing.
 | 
				
			||||||
  if (From == To) {
 | 
					  if (From == To)
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Return from a tail call.
 | 
					  // Return from a tail call.
 | 
				
			||||||
  if (FromBB->succ_size() == 0)
 | 
					  if (FromBB->succ_size() == 0)
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Very rarely we will see ignored branches. Do a linear check.
 | 
					  // Very rarely we will see ignored branches. Do a linear check.
 | 
				
			||||||
  for (std::pair<uint32_t, uint32_t> &Branch : BF.IgnoredBranches) {
 | 
					  for (std::pair<uint32_t, uint32_t> &Branch : BF.IgnoredBranches)
 | 
				
			||||||
    if (Branch ==
 | 
					    if (Branch ==
 | 
				
			||||||
        std::make_pair(static_cast<uint32_t>(From), static_cast<uint32_t>(To)))
 | 
					        std::make_pair(static_cast<uint32_t>(From), static_cast<uint32_t>(To)))
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool OffsetMatches = !!(To == ToBB->getOffset());
 | 
					  bool OffsetMatches = !!(To == ToBB->getOffset());
 | 
				
			||||||
  if (!OffsetMatches) {
 | 
					  if (!OffsetMatches) {
 | 
				
			||||||
| 
						 | 
					@ -742,9 +724,8 @@ bool DataReader::recordBranch(BinaryFunction &BF, uint64_t From, uint64_t To,
 | 
				
			||||||
          BC.MIB->getAnnotationWithDefault<uint32_t>(*LastInstr, "Offset");
 | 
					          BC.MIB->getAnnotationWithDefault<uint32_t>(*LastInstr, "Offset");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // With old .fdata we are getting FT branches for "jcc,jmp" sequences.
 | 
					      // With old .fdata we are getting FT branches for "jcc,jmp" sequences.
 | 
				
			||||||
      if (To == LastInstrOffset && BC.MIB->isUnconditionalBranch(*LastInstr)) {
 | 
					      if (To == LastInstrOffset && BC.MIB->isUnconditionalBranch(*LastInstr))
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (To <= LastInstrOffset) {
 | 
					      if (To <= LastInstrOffset) {
 | 
				
			||||||
        LLVM_DEBUG(dbgs() << "branch recorded into the middle of the block"
 | 
					        LLVM_DEBUG(dbgs() << "branch recorded into the middle of the block"
 | 
				
			||||||
| 
						 | 
					@ -1163,15 +1144,13 @@ std::error_code DataReader::parseInNoLBRMode() {
 | 
				
			||||||
    I->getValue().Data.emplace_back(std::move(MI));
 | 
					    I->getValue().Data.emplace_back(std::move(MI));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (StringMapEntry<FuncSampleData> &FuncSamples : NamesToSamples) {
 | 
					  for (StringMapEntry<FuncSampleData> &FuncSamples : NamesToSamples)
 | 
				
			||||||
    std::stable_sort(FuncSamples.second.Data.begin(),
 | 
					    std::stable_sort(FuncSamples.second.Data.begin(),
 | 
				
			||||||
                     FuncSamples.second.Data.end());
 | 
					                     FuncSamples.second.Data.end());
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (StringMapEntry<FuncMemData> &MemEvents : NamesToMemEvents) {
 | 
					  for (StringMapEntry<FuncMemData> &MemEvents : NamesToMemEvents)
 | 
				
			||||||
    std::stable_sort(MemEvents.second.Data.begin(),
 | 
					    std::stable_sort(MemEvents.second.Data.begin(),
 | 
				
			||||||
                     MemEvents.second.Data.end());
 | 
					                     MemEvents.second.Data.end());
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return std::error_code();
 | 
					  return std::error_code();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1266,15 +1245,13 @@ std::error_code DataReader::parse() {
 | 
				
			||||||
    I->getValue().Data.emplace_back(std::move(MI));
 | 
					    I->getValue().Data.emplace_back(std::move(MI));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (StringMapEntry<FuncBranchData> &FuncBranches : NamesToBranches) {
 | 
					  for (StringMapEntry<FuncBranchData> &FuncBranches : NamesToBranches)
 | 
				
			||||||
    std::stable_sort(FuncBranches.second.Data.begin(),
 | 
					    std::stable_sort(FuncBranches.second.Data.begin(),
 | 
				
			||||||
                     FuncBranches.second.Data.end());
 | 
					                     FuncBranches.second.Data.end());
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (StringMapEntry<FuncMemData> &MemEvents : NamesToMemEvents) {
 | 
					  for (StringMapEntry<FuncMemData> &MemEvents : NamesToMemEvents)
 | 
				
			||||||
    std::stable_sort(MemEvents.second.Data.begin(),
 | 
					    std::stable_sort(MemEvents.second.Data.begin(),
 | 
				
			||||||
                     MemEvents.second.Data.end());
 | 
					                     MemEvents.second.Data.end());
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return std::error_code();
 | 
					  return std::error_code();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1343,9 +1320,8 @@ std::vector<decltype(MapTy::MapEntryTy::second) *> fetchMapEntriesRegex(
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      auto I = Map.find(Name);
 | 
					      auto I = Map.find(Name);
 | 
				
			||||||
      if (I != Map.end()) {
 | 
					      if (I != Map.end())
 | 
				
			||||||
        return {&I->getValue()};
 | 
					        return {&I->getValue()};
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return AllData;
 | 
					  return AllData;
 | 
				
			||||||
| 
						 | 
					@ -1419,15 +1395,13 @@ bool DataReader::hasLocalsWithFileName() const {
 | 
				
			||||||
void DataReader::dump() const {
 | 
					void DataReader::dump() const {
 | 
				
			||||||
  for (const StringMapEntry<FuncBranchData> &Func : NamesToBranches) {
 | 
					  for (const StringMapEntry<FuncBranchData> &Func : NamesToBranches) {
 | 
				
			||||||
    Diag << Func.getKey() << " branches:\n";
 | 
					    Diag << Func.getKey() << " branches:\n";
 | 
				
			||||||
    for (const BranchInfo &BI : Func.getValue().Data) {
 | 
					    for (const BranchInfo &BI : Func.getValue().Data)
 | 
				
			||||||
      Diag << BI.From.Name << " " << BI.From.Offset << " " << BI.To.Name << " "
 | 
					      Diag << BI.From.Name << " " << BI.From.Offset << " " << BI.To.Name << " "
 | 
				
			||||||
           << BI.To.Offset << " " << BI.Mispreds << " " << BI.Branches << "\n";
 | 
					           << BI.To.Offset << " " << BI.Mispreds << " " << BI.Branches << "\n";
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    Diag << Func.getKey() << " entry points:\n";
 | 
					    Diag << Func.getKey() << " entry points:\n";
 | 
				
			||||||
    for (const BranchInfo &BI : Func.getValue().EntryData) {
 | 
					    for (const BranchInfo &BI : Func.getValue().EntryData)
 | 
				
			||||||
      Diag << BI.From.Name << " " << BI.From.Offset << " " << BI.To.Name << " "
 | 
					      Diag << BI.From.Name << " " << BI.From.Offset << " " << BI.To.Name << " "
 | 
				
			||||||
           << BI.To.Offset << " " << BI.Mispreds << " " << BI.Branches << "\n";
 | 
					           << BI.To.Offset << " " << BI.Mispreds << " " << BI.Branches << "\n";
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (auto I = EventNames.begin(), E = EventNames.end(); I != E; ++I) {
 | 
					  for (auto I = EventNames.begin(), E = EventNames.end(); I != E; ++I) {
 | 
				
			||||||
| 
						 | 
					@ -1436,20 +1410,18 @@ void DataReader::dump() const {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  for (const StringMapEntry<FuncSampleData> &Func : NamesToSamples) {
 | 
					  for (const StringMapEntry<FuncSampleData> &Func : NamesToSamples) {
 | 
				
			||||||
    Diag << Func.getKey() << " samples:\n";
 | 
					    Diag << Func.getKey() << " samples:\n";
 | 
				
			||||||
    for (const SampleInfo &SI : Func.getValue().Data) {
 | 
					    for (const SampleInfo &SI : Func.getValue().Data)
 | 
				
			||||||
      Diag << SI.Loc.Name << " " << SI.Loc.Offset << " " << SI.Hits << "\n";
 | 
					      Diag << SI.Loc.Name << " " << SI.Loc.Offset << " " << SI.Hits << "\n";
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (const StringMapEntry<FuncMemData> &Func : NamesToMemEvents) {
 | 
					  for (const StringMapEntry<FuncMemData> &Func : NamesToMemEvents) {
 | 
				
			||||||
    Diag << "Memory events for " << Func.getValue().Name;
 | 
					    Diag << "Memory events for " << Func.getValue().Name;
 | 
				
			||||||
    Location LastOffset(0);
 | 
					    Location LastOffset(0);
 | 
				
			||||||
    for (const MemInfo &MI : Func.getValue().Data) {
 | 
					    for (const MemInfo &MI : Func.getValue().Data) {
 | 
				
			||||||
      if (MI.Offset == LastOffset) {
 | 
					      if (MI.Offset == LastOffset)
 | 
				
			||||||
        Diag << ", " << MI.Addr << "/" << MI.Count;
 | 
					        Diag << ", " << MI.Addr << "/" << MI.Count;
 | 
				
			||||||
      } else {
 | 
					      else
 | 
				
			||||||
        Diag << "\n" << MI.Offset << ": " << MI.Addr << "/" << MI.Count;
 | 
					        Diag << "\n" << MI.Offset << ": " << MI.Addr << "/" << MI.Count;
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      LastOffset = MI.Offset;
 | 
					      LastOffset = MI.Offset;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Diag << "\n";
 | 
					    Diag << "\n";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,9 +41,8 @@ void Heatmap::registerAddressRange(uint64_t StartAddress, uint64_t EndAddress,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (uint64_t Bucket = StartAddress / BucketSize;
 | 
					  for (uint64_t Bucket = StartAddress / BucketSize;
 | 
				
			||||||
       Bucket <= EndAddress / BucketSize; ++Bucket) {
 | 
					       Bucket <= EndAddress / BucketSize; ++Bucket)
 | 
				
			||||||
    Map[Bucket] += Count;
 | 
					    Map[Bucket] += Count;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Heatmap::print(StringRef FileName) const {
 | 
					void Heatmap::print(StringRef FileName) const {
 | 
				
			||||||
| 
						 | 
					@ -72,9 +71,8 @@ void Heatmap::print(raw_ostream &OS) const {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Calculate the max value for scaling.
 | 
					  // Calculate the max value for scaling.
 | 
				
			||||||
  uint64_t MaxValue = 0;
 | 
					  uint64_t MaxValue = 0;
 | 
				
			||||||
  for (const std::pair<const uint64_t, uint64_t> &Entry : Map) {
 | 
					  for (const std::pair<const uint64_t, uint64_t> &Entry : Map)
 | 
				
			||||||
    MaxValue = std::max<uint64_t>(MaxValue, Entry.second);
 | 
					    MaxValue = std::max<uint64_t>(MaxValue, Entry.second);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Print start of the line and fill it with an empty space right before
 | 
					  // Print start of the line and fill it with an empty space right before
 | 
				
			||||||
  // the Address.
 | 
					  // the Address.
 | 
				
			||||||
| 
						 | 
					@ -89,9 +87,8 @@ void Heatmap::print(raw_ostream &OS) const {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (Empty)
 | 
					    if (Empty)
 | 
				
			||||||
      Address = LineAddress + BytesPerLine;
 | 
					      Address = LineAddress + BytesPerLine;
 | 
				
			||||||
    for (uint64_t Fill = LineAddress; Fill < Address; Fill += BucketSize) {
 | 
					    for (uint64_t Fill = LineAddress; Fill < Address; Fill += BucketSize)
 | 
				
			||||||
      OS << FillChar;
 | 
					      OS << FillChar;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Finish line after \p Address was printed.
 | 
					  // Finish line after \p Address was printed.
 | 
				
			||||||
| 
						 | 
					@ -151,11 +148,11 @@ void Heatmap::print(raw_ostream &OS) const {
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (Value <= Range[0]) {
 | 
					    if (Value <= Range[0])
 | 
				
			||||||
      OS << 'o';
 | 
					      OS << 'o';
 | 
				
			||||||
    } else {
 | 
					    else
 | 
				
			||||||
      OS << 'O';
 | 
					      OS << 'O';
 | 
				
			||||||
    }
 | 
					
 | 
				
			||||||
    if (ResetColor)
 | 
					    if (ResetColor)
 | 
				
			||||||
      changeColor(DefaultColor);
 | 
					      changeColor(DefaultColor);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
| 
						 | 
					@ -200,11 +197,10 @@ void Heatmap::print(raw_ostream &OS) const {
 | 
				
			||||||
    const std::pair<const uint64_t, uint64_t> &Entry = *MI;
 | 
					    const std::pair<const uint64_t, uint64_t> &Entry = *MI;
 | 
				
			||||||
    uint64_t Address = Entry.first * BucketSize;
 | 
					    uint64_t Address = Entry.first * BucketSize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (PrevAddress) {
 | 
					    if (PrevAddress)
 | 
				
			||||||
      fillRange(PrevAddress, Address);
 | 
					      fillRange(PrevAddress, Address);
 | 
				
			||||||
    } else {
 | 
					    else
 | 
				
			||||||
      startLine(Address);
 | 
					      startLine(Address);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printValue(Entry.second);
 | 
					    printValue(Entry.second);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,17 +53,14 @@ void YAMLProfileReader::buildNameMaps(
 | 
				
			||||||
    if (Pos != StringRef::npos)
 | 
					    if (Pos != StringRef::npos)
 | 
				
			||||||
      Name = Name.substr(0, Pos);
 | 
					      Name = Name.substr(0, Pos);
 | 
				
			||||||
    ProfileNameToProfile[Name] = &YamlBF;
 | 
					    ProfileNameToProfile[Name] = &YamlBF;
 | 
				
			||||||
    if (const Optional<StringRef> CommonName = getLTOCommonName(Name)) {
 | 
					    if (const Optional<StringRef> CommonName = getLTOCommonName(Name))
 | 
				
			||||||
      LTOCommonNameMap[*CommonName].push_back(&YamlBF);
 | 
					      LTOCommonNameMap[*CommonName].push_back(&YamlBF);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  for (auto &BFI : Functions) {
 | 
					  for (auto &BFI : Functions) {
 | 
				
			||||||
    const BinaryFunction &Function = BFI.second;
 | 
					    const BinaryFunction &Function = BFI.second;
 | 
				
			||||||
    for (StringRef Name : Function.getNames()) {
 | 
					    for (StringRef Name : Function.getNames())
 | 
				
			||||||
      if (const Optional<StringRef> CommonName = getLTOCommonName(Name)) {
 | 
					      if (const Optional<StringRef> CommonName = getLTOCommonName(Name))
 | 
				
			||||||
        LTOCommonNameFunctionMap[*CommonName].insert(&Function);
 | 
					        LTOCommonNameFunctionMap[*CommonName].insert(&Function);
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,11 +120,11 @@ bool YAMLProfileReader::parseFunctionProfile(
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      uint64_t NumSamples = YamlBB.EventCount * 1000;
 | 
					      uint64_t NumSamples = YamlBB.EventCount * 1000;
 | 
				
			||||||
      if (NormalizeByInsnCount && BB.getNumNonPseudos()) {
 | 
					      if (NormalizeByInsnCount && BB.getNumNonPseudos())
 | 
				
			||||||
        NumSamples /= BB.getNumNonPseudos();
 | 
					        NumSamples /= BB.getNumNonPseudos();
 | 
				
			||||||
      } else if (NormalizeByCalls) {
 | 
					      else if (NormalizeByCalls)
 | 
				
			||||||
        NumSamples /= BB.getNumCalls() + 1;
 | 
					        NumSamples /= BB.getNumCalls() + 1;
 | 
				
			||||||
      }
 | 
					
 | 
				
			||||||
      BB.setExecutionCount(NumSamples);
 | 
					      BB.setExecutionCount(NumSamples);
 | 
				
			||||||
      if (BB.isEntryPoint())
 | 
					      if (BB.isEntryPoint())
 | 
				
			||||||
        FunctionExecutionCount += NumSamples;
 | 
					        FunctionExecutionCount += NumSamples;
 | 
				
			||||||
| 
						 | 
					@ -142,9 +139,9 @@ bool YAMLProfileReader::parseFunctionProfile(
 | 
				
			||||||
                                   : nullptr;
 | 
					                                   : nullptr;
 | 
				
			||||||
      bool IsFunction = Callee ? true : false;
 | 
					      bool IsFunction = Callee ? true : false;
 | 
				
			||||||
      MCSymbol *CalleeSymbol = nullptr;
 | 
					      MCSymbol *CalleeSymbol = nullptr;
 | 
				
			||||||
      if (IsFunction) {
 | 
					      if (IsFunction)
 | 
				
			||||||
        CalleeSymbol = Callee->getSymbolForEntryID(YamlCSI.EntryDiscriminator);
 | 
					        CalleeSymbol = Callee->getSymbolForEntryID(YamlCSI.EntryDiscriminator);
 | 
				
			||||||
      }
 | 
					
 | 
				
			||||||
      BF.getAllCallSites().emplace_back(CalleeSymbol, YamlCSI.Count,
 | 
					      BF.getAllCallSites().emplace_back(CalleeSymbol, YamlCSI.Count,
 | 
				
			||||||
                                        YamlCSI.Mispreds, YamlCSI.Offset);
 | 
					                                        YamlCSI.Mispreds, YamlCSI.Offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -221,10 +218,9 @@ bool YAMLProfileReader::parseFunctionProfile(
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If basic block profile wasn't read it should be 0.
 | 
					  // If basic block profile wasn't read it should be 0.
 | 
				
			||||||
  for (BinaryBasicBlock &BB : BF) {
 | 
					  for (BinaryBasicBlock &BB : BF)
 | 
				
			||||||
    if (BB.getExecutionCount() == BinaryBasicBlock::COUNT_NO_PROFILE)
 | 
					    if (BB.getExecutionCount() == BinaryBasicBlock::COUNT_NO_PROFILE)
 | 
				
			||||||
      BB.setExecutionCount(0);
 | 
					      BB.setExecutionCount(0);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (YamlBP.Header.Flags & BinaryFunction::PF_SAMPLE) {
 | 
					  if (YamlBP.Header.Flags & BinaryFunction::PF_SAMPLE) {
 | 
				
			||||||
    BF.setExecutionCount(FunctionExecutionCount);
 | 
					    BF.setExecutionCount(FunctionExecutionCount);
 | 
				
			||||||
| 
						 | 
					@ -236,11 +232,10 @@ bool YAMLProfileReader::parseFunctionProfile(
 | 
				
			||||||
  if (ProfileMatched)
 | 
					  if (ProfileMatched)
 | 
				
			||||||
    BF.markProfiled(YamlBP.Header.Flags);
 | 
					    BF.markProfiled(YamlBP.Header.Flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!ProfileMatched && opts::Verbosity >= 1) {
 | 
					  if (!ProfileMatched && opts::Verbosity >= 1)
 | 
				
			||||||
    errs() << "BOLT-WARNING: " << MismatchedBlocks << " blocks, "
 | 
					    errs() << "BOLT-WARNING: " << MismatchedBlocks << " blocks, "
 | 
				
			||||||
           << MismatchedCalls << " calls, and " << MismatchedEdges
 | 
					           << MismatchedCalls << " calls, and " << MismatchedEdges
 | 
				
			||||||
           << " edges in profile did not match function " << BF << '\n';
 | 
					           << " edges in profile did not match function " << BF << '\n';
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return ProfileMatched;
 | 
					  return ProfileMatched;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -263,16 +258,15 @@ Error YAMLProfileReader::preprocessProfile(BinaryContext &BC) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Sanity check.
 | 
					  // Sanity check.
 | 
				
			||||||
  if (YamlBP.Header.Version != 1) {
 | 
					  if (YamlBP.Header.Version != 1)
 | 
				
			||||||
    return make_error<StringError>(
 | 
					    return make_error<StringError>(
 | 
				
			||||||
        Twine("cannot read profile : unsupported version"),
 | 
					        Twine("cannot read profile : unsupported version"),
 | 
				
			||||||
        inconvertibleErrorCode());
 | 
					        inconvertibleErrorCode());
 | 
				
			||||||
  }
 | 
					
 | 
				
			||||||
  if (YamlBP.Header.EventNames.find(',') != StringRef::npos) {
 | 
					  if (YamlBP.Header.EventNames.find(',') != StringRef::npos)
 | 
				
			||||||
    return make_error<StringError>(
 | 
					    return make_error<StringError>(
 | 
				
			||||||
        Twine("multiple events in profile are not supported"),
 | 
					        Twine("multiple events in profile are not supported"),
 | 
				
			||||||
        inconvertibleErrorCode());
 | 
					        inconvertibleErrorCode());
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Match profile to function based on a function name.
 | 
					  // Match profile to function based on a function name.
 | 
				
			||||||
  buildNameMaps(BC.getBinaryFunctions());
 | 
					  buildNameMaps(BC.getBinaryFunctions());
 | 
				
			||||||
| 
						 | 
					@ -298,9 +292,8 @@ bool YAMLProfileReader::mayHaveProfileData(const BinaryFunction &BF) {
 | 
				
			||||||
    if (ProfileNameToProfile.find(Name) != ProfileNameToProfile.end())
 | 
					    if (ProfileNameToProfile.find(Name) != ProfileNameToProfile.end())
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    if (const Optional<StringRef> CommonName = getLTOCommonName(Name)) {
 | 
					    if (const Optional<StringRef> CommonName = getLTOCommonName(Name)) {
 | 
				
			||||||
      if (LTOCommonNameMap.find(*CommonName) != LTOCommonNameMap.end()) {
 | 
					      if (LTOCommonNameMap.find(*CommonName) != LTOCommonNameMap.end())
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -336,9 +329,9 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (StringRef FunctionName : Function.getNames()) {
 | 
					    for (StringRef FunctionName : Function.getNames()) {
 | 
				
			||||||
      auto PI = ProfileNameToProfile.find(FunctionName);
 | 
					      auto PI = ProfileNameToProfile.find(FunctionName);
 | 
				
			||||||
      if (PI == ProfileNameToProfile.end()) {
 | 
					      if (PI == ProfileNameToProfile.end())
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      }
 | 
					
 | 
				
			||||||
      yaml::bolt::BinaryFunctionProfile &YamlBF = *PI->getValue();
 | 
					      yaml::bolt::BinaryFunctionProfile &YamlBF = *PI->getValue();
 | 
				
			||||||
      if (profileMatches(YamlBF, Function))
 | 
					      if (profileMatches(YamlBF, Function))
 | 
				
			||||||
        matchProfileToFunction(YamlBF, Function);
 | 
					        matchProfileToFunction(YamlBF, Function);
 | 
				
			||||||
| 
						 | 
					@ -394,12 +387,10 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions) {
 | 
					  for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions)
 | 
				
			||||||
    if (!YamlBF.Used && opts::Verbosity >= 1) {
 | 
					    if (!YamlBF.Used && opts::Verbosity >= 1)
 | 
				
			||||||
      errs() << "BOLT-WARNING: profile ignored for function " << YamlBF.Name
 | 
					      errs() << "BOLT-WARNING: profile ignored for function " << YamlBF.Name
 | 
				
			||||||
             << '\n';
 | 
					             << '\n';
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Set for parseFunctionProfile().
 | 
					  // Set for parseFunctionProfile().
 | 
				
			||||||
  NormalizeByInsnCount = usesEvent("cycles") || usesEvent("instructions");
 | 
					  NormalizeByInsnCount = usesEvent("cycles") || usesEvent("instructions");
 | 
				
			||||||
| 
						 | 
					@ -412,11 +403,10 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
 | 
				
			||||||
      ++NumUnused;
 | 
					      ++NumUnused;
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (BinaryFunction *BF = YamlProfileToFunction[YamlBF.Id]) {
 | 
					    if (BinaryFunction *BF = YamlProfileToFunction[YamlBF.Id])
 | 
				
			||||||
      parseFunctionProfile(*BF, YamlBF);
 | 
					      parseFunctionProfile(*BF, YamlBF);
 | 
				
			||||||
    } else {
 | 
					    else
 | 
				
			||||||
      ++NumUnused;
 | 
					      ++NumUnused;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  BC.setNumUnusedProfiledObjects(NumUnused);
 | 
					  BC.setNumUnusedProfiledObjects(NumUnused);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,9 +68,8 @@ void convert(const BinaryFunction &BF,
 | 
				
			||||||
          CSI.EntryDiscriminator = 0;
 | 
					          CSI.EntryDiscriminator = 0;
 | 
				
			||||||
          if (CSP.Symbol) {
 | 
					          if (CSP.Symbol) {
 | 
				
			||||||
            const BinaryFunction *Callee = BC.getFunctionForSymbol(CSP.Symbol);
 | 
					            const BinaryFunction *Callee = BC.getFunctionForSymbol(CSP.Symbol);
 | 
				
			||||||
            if (Callee) {
 | 
					            if (Callee)
 | 
				
			||||||
              CSI.DestId = Callee->getFunctionNumber();
 | 
					              CSI.DestId = Callee->getFunctionNumber();
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          CSI.Count = CSP.Count;
 | 
					          CSI.Count = CSP.Count;
 | 
				
			||||||
          CSI.Mispreds = CSP.Mispreds;
 | 
					          CSI.Mispreds = CSP.Mispreds;
 | 
				
			||||||
| 
						 | 
					@ -115,9 +114,8 @@ void convert(const BinaryFunction &BF,
 | 
				
			||||||
        !(BB->isLandingPad() && BB->getKnownExecutionCount() != 0)) {
 | 
					        !(BB->isLandingPad() && BB->getKnownExecutionCount() != 0)) {
 | 
				
			||||||
      uint64_t SuccessorExecCount = 0;
 | 
					      uint64_t SuccessorExecCount = 0;
 | 
				
			||||||
      for (const BinaryBasicBlock::BinaryBranchInfo &BranchInfo :
 | 
					      for (const BinaryBasicBlock::BinaryBranchInfo &BranchInfo :
 | 
				
			||||||
           BB->branch_info()) {
 | 
					           BB->branch_info())
 | 
				
			||||||
        SuccessorExecCount += BranchInfo.Count;
 | 
					        SuccessorExecCount += BranchInfo.Count;
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (!SuccessorExecCount)
 | 
					      if (!SuccessorExecCount)
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -175,9 +173,9 @@ std::error_code YAMLProfileWriter::writeProfile(const RewriteInstance &RI) {
 | 
				
			||||||
    const BinaryFunction &BF = BFI.second;
 | 
					    const BinaryFunction &BF = BFI.second;
 | 
				
			||||||
    if (BF.hasProfile() && !BF.empty()) {
 | 
					    if (BF.hasProfile() && !BF.empty()) {
 | 
				
			||||||
      assert(BF.getProfileFlags() != BinaryFunction::PF_NONE);
 | 
					      assert(BF.getProfileFlags() != BinaryFunction::PF_NONE);
 | 
				
			||||||
      if (ProfileFlags == BinaryFunction::PF_NONE) {
 | 
					      if (ProfileFlags == BinaryFunction::PF_NONE)
 | 
				
			||||||
        ProfileFlags = BF.getProfileFlags();
 | 
					        ProfileFlags = BF.getProfileFlags();
 | 
				
			||||||
      }
 | 
					
 | 
				
			||||||
      assert(BF.getProfileFlags() == ProfileFlags &&
 | 
					      assert(BF.getProfileFlags() == ProfileFlags &&
 | 
				
			||||||
             "expected consistent profile flags across all functions");
 | 
					             "expected consistent profile flags across all functions");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue