Skip to content

Commit 503eb93

Browse files
authored
Add a target compilation manager framework (#200)
Adds a target compilation manager (in analogy to the pass manager) to the qss-compiler. This manager provides a systematic compilation of trees of target systems and their children. It also provides a threaded implementation of the target compilation manager that uses the shared threadpool from the MLIRContext to provide simultaneous threading of both target passes and across target compilation with unified resource management through the shared threadpool.
1 parent 40e4a50 commit 503eb93

File tree

20 files changed

+1034
-363
lines changed

20 files changed

+1034
-363
lines changed

include/Dialect/QUIR/Utils/Utils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ auto getNodeType(Operation *moduleOperation) -> std::string;
5959

6060
/// takes a module Op and returns the quir.nodeId attribute.
6161
// TODO: Should be replaced by an analysis compatable struct.
62-
auto getNodeId(Operation *moduleOperation) -> int;
62+
llvm::Expected<uint32_t> getNodeId(Operation *moduleOperation);
6363

6464
// adds the qubit Ids on the physicalId or physicalIds attributes to theseIds
6565
void addQubitIdsFromAttr(Operation *operation, std::vector<uint> &theseIds);

include/Frontend/OpenQASM3/OpenQASM3Frontend.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ namespace qssc::frontend::openqasm3 {
4646
/// otherwise
4747
llvm::Error parse(std::string const &source, bool sourceIsFilename,
4848
bool emitRawAST, bool emitPrettyAST, bool emitMLIR,
49-
mlir::ModuleOp &newModule,
49+
mlir::ModuleOp newModule,
5050
std::optional<DiagnosticCallback> diagnosticCb);
5151

5252
}; // namespace qssc::frontend::openqasm3

include/Frontend/OpenQASM3/QUIRGenQASM3Visitor.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class QUIRGenQASM3Visitor : public BaseQASM3Visitor {
4141
mlir::OpBuilder builder;
4242
mlir::OpBuilder topLevelBuilder;
4343
mlir::OpBuilder circuitParentBuilder;
44-
mlir::ModuleOp &newModule;
44+
mlir::ModuleOp newModule;
4545
mlir::quir::CircuitOp currentCircuitOp;
4646
std::string filename;
4747
bool hasFailed{false};
@@ -95,14 +95,14 @@ class QUIRGenQASM3Visitor : public BaseQASM3Visitor {
9595

9696
public:
9797
QUIRGenQASM3Visitor(QASM::ASTStatementList *sList, mlir::OpBuilder b,
98-
mlir::ModuleOp &newModule, std::string f)
98+
mlir::ModuleOp newModule, std::string f)
9999
: BaseQASM3Visitor(sList), builder(b), topLevelBuilder(b),
100100
circuitParentBuilder(b), newModule(newModule), filename(std::move(f)),
101101
expression(llvm::createStringError(llvm::inconvertibleErrorCode(),
102102
"Testing error")),
103103
varHandler(builder) {}
104104

105-
QUIRGenQASM3Visitor(mlir::OpBuilder b, mlir::ModuleOp &newModule,
105+
QUIRGenQASM3Visitor(mlir::OpBuilder b, mlir::ModuleOp newModule,
106106
std::string filename)
107107
: builder(b), topLevelBuilder(b), circuitParentBuilder(b),
108108
newModule(newModule), filename(std::move(filename)),
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
//===- TargetCompilationManager.h - Compilation Scheduler -----*- C++ -*-===//
2+
//
3+
// (C) Copyright IBM 2023.
4+
//
5+
// This code is part of Qiskit.
6+
//
7+
// This code is licensed under the Apache License, Version 2.0 with LLVM
8+
// Exceptions. You may obtain a copy of this license in the LICENSE.txt
9+
// file in the root directory of this source tree.
10+
//
11+
// Any modifications or derivative works of this code must retain this
12+
// copyright notice, and modified files need to carry a notice indicating
13+
// that they have been altered from the originals.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
///
17+
/// This file declares the classes for the top-level compilation scheduling
18+
/// interface.
19+
///
20+
//===----------------------------------------------------------------------===//
21+
#ifndef TARGETCOMPILATIONMANAGER_H
22+
#define TARGETCOMPILATIONMANAGER_H
23+
24+
#include "HAL/TargetSystem.h"
25+
26+
#include "mlir/IR/BuiltinOps.h"
27+
28+
#include "llvm/Support/Error.h"
29+
30+
#include <string>
31+
32+
using namespace qssc;
33+
34+
namespace qssc::hal::compile {
35+
36+
/// @brief Base class for the compiler's
37+
/// target compilation infrastructure.
38+
/// A target system is a tree of compilation targets.
39+
/// We aim to support compiling each disjoint
40+
/// target subtree independently.
41+
class TargetCompilationManager {
42+
protected:
43+
TargetCompilationManager(hal::TargetSystem &target,
44+
mlir::MLIRContext *context);
45+
46+
using WalkTargetFunction =
47+
std::function<llvm::Error(hal::Target *, mlir::ModuleOp)>;
48+
// Depth first walker for a target system
49+
llvm::Error walkTarget(Target *target, mlir::ModuleOp targetModuleOp,
50+
const WalkTargetFunction &walkFunc,
51+
const WalkTargetFunction &postChildrenCallbackFunc);
52+
53+
public:
54+
virtual ~TargetCompilationManager() = default;
55+
virtual const std::string getName() const = 0;
56+
57+
/// Get the base target system to be compiled.
58+
virtual hal::Target &getTargetSystem() { return target; }
59+
60+
/// Get the base MLIR context for this compilation scheduler.
61+
mlir::MLIRContext *getContext() { return context; };
62+
63+
/// @brief Compile only at the MLIR level for the full target
64+
/// system.
65+
/// @param moduleOp The root module operation to compile for.
66+
/// This must not be specialized to a system already.
67+
virtual llvm::Error compileMLIR(mlir::ModuleOp moduleOp) = 0;
68+
69+
/// @brief Generate the full configured compilation pipeline
70+
/// for all targets of the base target system. This will also
71+
/// invoke compileMLIR.
72+
/// @param moduleOp The root module operation to compile for.
73+
/// This must not be specialized to a system already.
74+
/// @param payload The payload to populate.
75+
/// @param doCompileMLIR Whether to call compileMLIR prior to compiling the
76+
/// payload. Defaults to true.
77+
virtual llvm::Error compilePayload(mlir::ModuleOp moduleOp,
78+
qssc::payload::Payload &payload,
79+
bool doCompileMLIR = true) = 0;
80+
81+
void enableIRPrinting(bool printBeforeAllTargetPasses,
82+
bool printAfterAllTargetPasses,
83+
bool printBeforeAllTargetPayload,
84+
bool printAfterTargetCompileFailure);
85+
86+
protected:
87+
bool getPrintBeforeAllTargetPasses() { return printBeforeAllTargetPasses; }
88+
bool getPrintAfterAllTargetPasses() { return printAfterAllTargetPasses; }
89+
bool getPrintBeforeAllTargetPayload() { return printBeforeAllTargetPayload; }
90+
bool getPrintAfterTargetCompileFailure() {
91+
return printAfterTargetCompileFailure;
92+
}
93+
94+
void printIR(llvm::StringRef msg, mlir::Operation *op,
95+
llvm::raw_ostream &out);
96+
97+
private:
98+
hal::TargetSystem &target;
99+
mlir::MLIRContext *context;
100+
101+
bool printBeforeAllTargetPasses = false;
102+
bool printAfterAllTargetPasses = false;
103+
bool printBeforeAllTargetPayload = false;
104+
bool printAfterTargetCompileFailure = false;
105+
106+
}; // class TargetCompilationManager
107+
108+
/// Register a set of useful command-line options that can be used to configure
109+
/// a target compilation scheduler.
110+
void registerTargetCompilationManagerCLOptions();
111+
112+
/// Apply any values provided to the target compilation scheduler options that
113+
/// were registered with 'registerTargetCompilationManagerCLOptions'.
114+
mlir::LogicalResult
115+
applyTargetCompilationManagerCLOptions(TargetCompilationManager &scheduler);
116+
117+
} // namespace qssc::hal::compile
118+
#endif // TARGETCOMPILATIONMANAGER_H
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//===- ThreadedCompilationManager.h - Threaded Scheduler ------*- C++ -*-===//
2+
//
3+
// (C) Copyright IBM 2023.
4+
//
5+
// This code is part of Qiskit.
6+
//
7+
// This code is licensed under the Apache License, Version 2.0 with LLVM
8+
// Exceptions. You may obtain a copy of this license in the LICENSE.txt
9+
// file in the root directory of this source tree.
10+
//
11+
// Any modifications or derivative works of this code must retain this
12+
// copyright notice, and modified files need to carry a notice indicating
13+
// that they have been altered from the originals.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
///
17+
/// This file declares the classes for the top-level threaded compilation
18+
/// interfaces.
19+
///
20+
//===----------------------------------------------------------------------===//
21+
#ifndef THREADEDCOMPILATIONMANAGER_H
22+
#define THREADEDCOMPILATIONMANAGER_H
23+
24+
#include "HAL/Compile/TargetCompilationManager.h"
25+
26+
#include <string>
27+
28+
namespace qssc::hal::compile {
29+
30+
/// @brief A threaded implementation of a TargetCompilationManager
31+
/// based on the threading pools provided by the mlir::MLIRContext.
32+
/// This enables compilation across disjoint subtree of compilation
33+
/// targets in parallel.
34+
/// If threading is disabled within the MLIRContext the implementation
35+
/// will fall back to a sequential unthreaded version.
36+
/// The threaded implementation relies on MLIR's
37+
/// <a
38+
/// href="https://mlir.llvm.org/docs/PassManagement/#operation-pass">multi-threading
39+
/// assumptions</a>. As compilation is based on the shared MLIRContext's
40+
/// threadpool we are able to safely mix parallel nested passes and parallel
41+
/// target compilation subtrees without oversubscribing the compilation host's
42+
/// cores.
43+
class ThreadedCompilationManager : public TargetCompilationManager {
44+
protected:
45+
/// Threaded depth first walker for a target system using the current
46+
/// MLIRContext's threadpool.
47+
llvm::Error walkTargetThreaded(
48+
Target *target, mlir::ModuleOp targetModuleOp,
49+
const TargetCompilationManager::WalkTargetFunction &walkFunc,
50+
const TargetCompilationManager::WalkTargetFunction
51+
&postChildrenCallbackFunc);
52+
53+
public:
54+
using PMBuilder = std::function<llvm::Error(mlir::PassManager &)>;
55+
56+
ThreadedCompilationManager(qssc::hal::TargetSystem &target,
57+
mlir::MLIRContext *context, PMBuilder pmBuilder);
58+
virtual ~ThreadedCompilationManager() = default;
59+
virtual const std::string getName() const override;
60+
61+
virtual llvm::Error compileMLIR(mlir::ModuleOp moduleOp) override;
62+
virtual llvm::Error compilePayload(mlir::ModuleOp moduleOp,
63+
qssc::payload::Payload &payload,
64+
bool doCompileMLIR = true) override;
65+
66+
bool isMultithreadingEnabled() {
67+
return getContext()->isMultithreadingEnabled();
68+
}
69+
llvm::ThreadPool &getThreadPool() { return getContext()->getThreadPool(); }
70+
71+
llvm::Error buildTargetPassManager(mlir::PassManager &pm);
72+
73+
private:
74+
/// Compiles the input module for a single target.
75+
llvm::Error compileMLIRTarget(Target &target, mlir::ModuleOp targetModuleOp);
76+
/// Compiles the input payload for a single target.
77+
llvm::Error compilePayloadTarget(Target &target,
78+
mlir::ModuleOp targetModuleOp,
79+
qssc::payload::Payload &payload,
80+
bool doCompileMLIR);
81+
82+
PMBuilder pmBuilder;
83+
84+
}; // class THREADEDCOMPILATIONMANAGER
85+
86+
} // namespace qssc::hal::compile
87+
#endif // THREADEDCOMPILATIONMANAGER_H

0 commit comments

Comments
 (0)