123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- //===-- BasicBlockSectionsProfileReader.cpp -------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // Implementation of the basic block sections profile reader pass. It parses
- // and stores the basic block sections profile file (which is specified via the
- // `-basic-block-sections` flag).
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
- #include "llvm/ADT/SmallSet.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringMap.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/Support/Error.h"
- #include "llvm/Support/LineIterator.h"
- #include "llvm/Support/MemoryBuffer.h"
- using namespace llvm;
- char BasicBlockSectionsProfileReader::ID = 0;
- INITIALIZE_PASS(BasicBlockSectionsProfileReader, "bbsections-profile-reader",
- "Reads and parses a basic block sections profile.", false,
- false)
- bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const {
- return getBBClusterInfoForFunction(FuncName).first;
- }
- std::pair<bool, SmallVector<BBClusterInfo>>
- BasicBlockSectionsProfileReader::getBBClusterInfoForFunction(
- StringRef FuncName) const {
- std::pair<bool, SmallVector<BBClusterInfo>> cluster_info(false, {});
- auto R = ProgramBBClusterInfo.find(getAliasName(FuncName));
- if (R != ProgramBBClusterInfo.end()) {
- cluster_info.second = R->second;
- cluster_info.first = true;
- }
- return cluster_info;
- }
- // Basic Block Sections can be enabled for a subset of machine basic blocks.
- // This is done by passing a file containing names of functions for which basic
- // block sections are desired. Additionally, machine basic block ids of the
- // functions can also be specified for a finer granularity. Moreover, a cluster
- // of basic blocks could be assigned to the same section.
- // A file with basic block sections for all of function main and three blocks
- // for function foo (of which 1 and 2 are placed in a cluster) looks like this:
- // ----------------------------
- // list.txt:
- // !main
- // !foo
- // !!1 2
- // !!4
- static Error getBBClusterInfo(const MemoryBuffer *MBuf,
- ProgramBBClusterInfoMapTy &ProgramBBClusterInfo,
- StringMap<StringRef> &FuncAliasMap) {
- assert(MBuf);
- line_iterator LineIt(*MBuf, /*SkipBlanks=*/true, /*CommentMarker=*/'#');
- auto invalidProfileError = [&](auto Message) {
- return make_error<StringError>(
- Twine("Invalid profile " + MBuf->getBufferIdentifier() + " at line " +
- Twine(LineIt.line_number()) + ": " + Message),
- inconvertibleErrorCode());
- };
- auto FI = ProgramBBClusterInfo.end();
- // Current cluster ID corresponding to this function.
- unsigned CurrentCluster = 0;
- // Current position in the current cluster.
- unsigned CurrentPosition = 0;
- // Temporary set to ensure every basic block ID appears once in the clusters
- // of a function.
- SmallSet<unsigned, 4> FuncBBIDs;
- for (; !LineIt.is_at_eof(); ++LineIt) {
- StringRef S(*LineIt);
- if (S[0] == '@')
- continue;
- // Check for the leading "!"
- if (!S.consume_front("!") || S.empty())
- break;
- // Check for second "!" which indicates a cluster of basic blocks.
- if (S.consume_front("!")) {
- if (FI == ProgramBBClusterInfo.end())
- return invalidProfileError(
- "Cluster list does not follow a function name specifier.");
- SmallVector<StringRef, 4> BBIDs;
- S.split(BBIDs, ' ');
- // Reset current cluster position.
- CurrentPosition = 0;
- for (auto BBIDStr : BBIDs) {
- unsigned long long BBID;
- if (getAsUnsignedInteger(BBIDStr, 10, BBID))
- return invalidProfileError(Twine("Unsigned integer expected: '") +
- BBIDStr + "'.");
- if (!FuncBBIDs.insert(BBID).second)
- return invalidProfileError(Twine("Duplicate basic block id found '") +
- BBIDStr + "'.");
- if (BBID == 0 && CurrentPosition)
- return invalidProfileError("Entry BB (0) does not begin a cluster.");
- FI->second.emplace_back(
- BBClusterInfo{((unsigned)BBID), CurrentCluster, CurrentPosition++});
- }
- CurrentCluster++;
- } else { // This is a function name specifier.
- // Function aliases are separated using '/'. We use the first function
- // name for the cluster info mapping and delegate all other aliases to
- // this one.
- SmallVector<StringRef, 4> Aliases;
- S.split(Aliases, '/');
- for (size_t i = 1; i < Aliases.size(); ++i)
- FuncAliasMap.try_emplace(Aliases[i], Aliases.front());
- // Prepare for parsing clusters of this function name.
- // Start a new cluster map for this function name.
- FI = ProgramBBClusterInfo.try_emplace(Aliases.front()).first;
- CurrentCluster = 0;
- FuncBBIDs.clear();
- }
- }
- return Error::success();
- }
- void BasicBlockSectionsProfileReader::initializePass() {
- if (!MBuf)
- return;
- if (auto Err = getBBClusterInfo(MBuf, ProgramBBClusterInfo, FuncAliasMap))
- report_fatal_error(std::move(Err));
- }
- ImmutablePass *
- llvm::createBasicBlockSectionsProfileReaderPass(const MemoryBuffer *Buf) {
- return new BasicBlockSectionsProfileReader(Buf);
- }
|