Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert C++ documentation to Doxygen format. #286

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions compiler_gym/envs/llvm/service/ActionSpace.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,26 @@ namespace compiler_gym::llvm_service {
// LLVM transforms. Generated by //compiler_gym/envs/llvm/service/passes:action-genfiles.
#include "compiler_gym/envs/llvm/service/passes/ActionEnum.h" // @donotremove

// The available action spaces for LLVM.
//
// NOTE(cummins): Housekeeping rules - to add a new action space:
// 1. Add a new entry to this LlvmActionSpace enum.
// 2. Add a new switch case to getLlvmActionSpaceList() to return the
// ActionSpace.
// 3. Add a new switch case to LlvmSession::step() to compute
// the actual action.
// 4. Run `bazel test //compiler_gym/...` and update the newly failing tests.
/**
* The available action spaces for LLVM.
*
* \note Implementation housekeeping rules - to add a new action space:
* 1. Add a new entry to this LlvmActionSpace enum.
* 2. Add a new switch case to getLlvmActionSpaceList() to return the
* ActionSpace.
* 3. Add a new switch case to LlvmSession::step() to compute
* the actual action.
* 4. Run `bazel test //compiler_gym/...` and update the newly failing tests.
*/
enum class LlvmActionSpace {
// The full set of transform passes for LLVM.
PASSES_ALL,
PASSES_ALL, ///< The full set of transform passes for LLVM.
};

// Get the list of LLVM action spaces.
/**
* Get the list of LLVM action spaces.
*
* @return A list of ActionSpace instances.
*/
std::vector<ActionSpace> getLlvmActionSpaceList();

} // namespace compiler_gym::llvm_service
102 changes: 89 additions & 13 deletions compiler_gym/envs/llvm/service/Benchmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,62 +17,138 @@

namespace compiler_gym::llvm_service {

// A 160 bits SHA1 that identifies an LLVM module.
/**
* A 160 bits SHA1 that identifies an LLVM module.
*/
using BenchmarkHash = llvm::ModuleHash;

/**
* A bitcode.
*/
using Bitcode = llvm::SmallString<0>;

/**
* Read a bitcode file from disk.
*
* @param path The path of the bitcode file to read.
* @param bitcode The destination bitcode.
* @return `OK` on success, `NOT_FOUND` if the file is not found, or
* `INVALID_ARGUMENT` if the file is invalid.
*/
grpc::Status readBitcodeFile(const boost::filesystem::path& path, Bitcode* bitcode);

// Parses the given bitcode into a module and strips the identifying ModuleID
// and source_filename attributes. Returns nullptr on error and sets status.
/**
* Construct an LLVM module from a bitcode.
*
* Parses the given bitcode into a module and strips the identifying `ModuleID`
* and `source_filename` attributes.
*
* @param context An LLVM context for the new module.
* @param bitcode The bitcode to parse.
* @param name The name of the module.
* @param status An error status that is set to `OK` on success or
* `INVALID_ARGUMENT` if the bitcode cannot be parsed.
* @return A unique pointer to an LLVM module, or `nullptr` on error and sets
* `status`.
*/
std::unique_ptr<llvm::Module> makeModule(llvm::LLVMContext& context, const Bitcode& bitcode,
const std::string& name, grpc::Status* status);

// A benchmark is an LLVM module and the LLVM context that owns it. A benchmark
// is mutable and can be changed over the course of a session.
/**
* An LLVM module and the LLVM context that owns it.
*
* A benchmark is mutable and can be changed over the course of a session.
*/
class Benchmark {
public:
/**
* Construct a benchmark from a bitcode.
*/
Benchmark(const std::string& name, const Bitcode& bitcode,
const boost::filesystem::path& workingDirectory, const BaselineCosts& baselineCosts);

/**
* Construct a benchmark from an LLVM module.
*/
Benchmark(const std::string& name, std::unique_ptr<llvm::LLVMContext> context,
std::unique_ptr<llvm::Module> module, size_t bitcodeSize,
const boost::filesystem::path& workingDirectory, const BaselineCosts& baselineCosts);

// Make a copy of the benchmark.
/**
* Make a copy of the benchmark.
*
* @param workingDirectory The working directory for the new benchmark.
* @return A copy of the benchmark.
*/
std::unique_ptr<Benchmark> clone(const boost::filesystem::path& workingDirectory) const;

// Compute and return a SHA1 hash of the module.
/**
* Compute and return a SHA1 hash of the module.
*
* @return A SHA1 hash of the module.
*/
BenchmarkHash module_hash() const;

// Wrapper around llvm::verifyModule() which returns an error status on
// failure.
/**
* Wrapper around `llvm::verifyModule()` which returns an error status on
* failure.
*
* @return `OK` on success, else `DATA_LOSS` if verification fails.
*/
grpc::Status verify_module();

/**
* The name of the benchmark.
*/
inline const std::string& name() const { return name_; }

/**
* The size of the bitcode that was parsed to produce the initial benchmark.
*/
inline const size_t bitcodeSize() const { return bitcodeSize_; }

/**
* The underlying LLVM module.
*/
inline llvm::Module& module() { return *module_; }

/**
* The underlying LLVM module.
*/
inline const llvm::Module& module() const { return *module_; }

/**
* The underlying LLVM context.
*/
inline llvm::LLVMContext& context() { return *context_; }

/**
* The underlying LLVM context.
*/
inline const llvm::LLVMContext& context() const { return *context_; }

inline const BaselineCosts& baselineCosts() const { return baselineCosts_; }

// Accessors for the underlying raw pointers.

/**
* A pointer to the underlying LLVM context.
*/
inline const llvm::LLVMContext* context_ptr() const { return context_.get(); }

/**
* A pointer to the underlying LLVM module.
*/
inline const llvm::Module* module_ptr() const { return module_.get(); }

// Replace the benchmark module with a new one. This is to enable
// out-of-process modification of the IR by serializing the benchmark to a
// file, modifying the file, then loading the modified file and updating the
// module pointer here.
/** Replace the benchmark module with a new one.
*
* This is to enable out-of-process modification of the IR by serializing the
* benchmark to a file, modifying the file, then loading the modified file and
* updating the module pointer here.
*
* @param module A new module.
*/
inline void replaceModule(std::unique_ptr<llvm::Module> module) { module_ = std::move(module); }

private:
Expand Down
2 changes: 1 addition & 1 deletion compiler_gym/envs/llvm/service/BenchmarkFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Status BenchmarkFactory::getBenchmark(const BenchmarkProto& benchmarkMessage,
break;
}
case compiler_gym::File::DataCase::kUri: {
// Check that protocol of the benmchmark URI.
// Check the protocol of the benchmark URI.
if (programFile.uri().find("file:///") != 0) {
return Status(StatusCode::INVALID_ARGUMENT,
fmt::format("Invalid benchmark data URI. "
Expand Down
75 changes: 56 additions & 19 deletions compiler_gym/envs/llvm/service/BenchmarkFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,56 @@

namespace compiler_gym::llvm_service {

// Benchmarks are loaded from disk and cached in-memory so that future uses
// do not require a disk access. The number of benchmarks that may be
// simultaneously loaded is limited by the combined size of the bitcodes, in
// bytes. Once this size is reached, benchmarks are offloaded so that they must
// be re-read from disk.
/**
* Maximum number of bytes before benchmark cache eviction.
*
* Benchmarks are loaded from disk and cached in-memory so that future uses do
* not require a disk access. The number of benchmarks that may be
* simultaneously loaded is limited by the combined size of the bitcodes, in
* bytes. Once this size is reached, benchmarks are offloaded so that they must
* be re-read from disk.
*/
constexpr size_t kMaxLoadedBenchmarkSize = 512 * 1024 * 1024;

// A factory object for instantiating LLVM modules for use in optimization
// sessions. Example usage:
//
// BenchmarkFactory factory;
// auto benchmark = factory.getBenchmark("file:////tmp/my_bitcode.bc");
// // ... do fun stuff
/**
* A factory object for instantiating LLVM modules for use in optimization
* sessions.
*
* Example usage:
*
* \code{.cpp}
* BenchmarkFactory factory;
* auto benchmark = factory.getBenchmark("file:////tmp/my_bitcode.bc");
* // ... do fun stuff
* \endcode
*/
class BenchmarkFactory {
public:
/**
* Return the global benchmark factory singleton.
*
* @param workingDirectory The working directory.
* @param rand An optional random number generator. This is used for cache
* evictions.
* @param maxLoadedBenchmarkSize The maximum size in bytes of the benchmark
* cache before evictions.
* @return The benchmark factory singleton instance.
*/
static BenchmarkFactory& getSingleton(const boost::filesystem::path& workingDirectory,
std::optional<std::mt19937_64> rand = std::nullopt,
size_t maxLoadedBenchmarkSize = kMaxLoadedBenchmarkSize) {
static BenchmarkFactory instance(workingDirectory, rand, maxLoadedBenchmarkSize);
return instance;
}

// Get the requested named benchmark.
/**
* Get the requested named benchmark.
*
* @param benchmarkMessage A Benchmark protocol message.
* @param benchmark A benchmark instance to assign this benchmark to.
* @return `OK` on success, or `INVALID_ARGUMENT` if the protocol message is
* invalid.
*/
[[nodiscard]] grpc::Status getBenchmark(const compiler_gym::Benchmark& benchmarkMessage,
std::unique_ptr<Benchmark>* benchmark);

Expand All @@ -53,24 +80,34 @@ class BenchmarkFactory {
[[nodiscard]] grpc::Status addBitcode(const std::string& uri,
const boost::filesystem::path& path);

// Construct a benchmark factory. rand is a random seed used to control the
// selection of random benchmarks. maxLoadedBenchmarkSize is the maximum
// combined size of the bitcodes that may be cached in memory. Once this
// size is reached, benchmarks are offloaded so that they must be re-read from
// disk.
/**
* Construct a benchmark factory.
*
* @param workingDirectory A filesystem directory to use for storing temporary
* files.
* @param rand is a random seed used to control the selection of random
* benchmarks.
* @param maxLoadedBenchmarkSize is the maximum combined size of the bitcodes
* that may be cached in memory. Once this size is reached, benchmarks are
* offloaded so that they must be re-read from disk.
*/
BenchmarkFactory(const boost::filesystem::path& workingDirectory,
std::optional<std::mt19937_64> rand = std::nullopt,
size_t maxLoadedBenchmarkSize = kMaxLoadedBenchmarkSize);

BenchmarkFactory(const BenchmarkFactory&) = delete;
BenchmarkFactory& operator=(const BenchmarkFactory&) = delete;

// A mapping from URI to benchmarks which have been loaded into memory.
/**
* A mapping from URI to benchmarks which have been loaded into memory.
*/
std::unordered_map<std::string, Benchmark> benchmarks_;

const boost::filesystem::path workingDirectory_;
std::mt19937_64 rand_;
// The current and maximum allowed sizes of the loaded benchmarks.
/**
* The current and maximum allowed sizes of the loaded benchmarks.
*/
size_t loadedBenchmarksSize_;
const size_t maxLoadedBenchmarkSize_;
};
Expand Down
Loading