Skip to content

Commit ce146cc

Browse files
authored
Merge pull request #2581 from khalatepradnya/align-with-main
[features/run] Align with main
2 parents 98aac0d + ce969ea commit ce146cc

File tree

129 files changed

+3934
-1253
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+3934
-1253
lines changed

include/cudaq/Optimizer/Builder/Factory.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ std::optional<double> maybeValueOfFloatConstant(mlir::Value v);
186186
/// \em{not} control dependent (other than on function entry).
187187
mlir::Value createLLVMTemporary(mlir::Location loc, mlir::OpBuilder &builder,
188188
mlir::Type type, std::size_t size = 1);
189+
mlir::Value createTemporary(mlir::Location loc, mlir::OpBuilder &builder,
190+
mlir::Type type, std::size_t size = 1);
189191

190192
//===----------------------------------------------------------------------===//
191193

include/cudaq/Optimizer/Builder/Intrinsics.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ class IRBuilder : public mlir::OpBuilder {
148148
mlir::LogicalResult loadIntrinsic(mlir::ModuleOp module,
149149
llvm::StringRef name);
150150

151+
llvm::StringRef getIntrinsicText(llvm::StringRef name);
152+
mlir::LogicalResult loadIntrinsicWithAliases(mlir::ModuleOp module,
153+
llvm::StringRef name,
154+
llvm::StringRef prefix);
155+
151156
std::string hashStringByContent(llvm::StringRef sref);
152157

153158
/// Generates code that yields the size of any type that can be reified in

include/cudaq/Optimizer/CodeGen/CodeGenOps.td

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,22 @@ def cgq_RAIIOp : CGQOp<"qmem_raii", [MemoryEffects<[MemAlloc, MemWrite]>]> {
4747
}];
4848
}
4949

50+
def cgq_MaterializeConstantArrayOp :
51+
CGQOp<"materialize_constant_array", [Pure]> {
52+
let summary = "Macro to materialize a cc.const_array into memory.";
53+
let description = [{
54+
This operation is the equivalent of creating some space in memory (such as
55+
on the stack) and storing a cc.const_array value to that memory address.
56+
This operation is needed for local rewrites, but is likely to be eliminated
57+
if the constant array can be completely folded away.
58+
}];
59+
60+
let arguments = (ins cc_ArrayType:$constArray);
61+
let results = (outs cc_PointerType);
62+
63+
let assemblyFormat = [{
64+
$constArray `:` functional-type(operands, results) attr-dict
65+
}];
66+
}
67+
5068
#endif

include/cudaq/Optimizer/CodeGen/Passes.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,17 @@ namespace cudaq::opt {
3232
/// @param pm Pass Manager to add QIR passes to
3333
/// @param convertTo Expected to be `qir-base` or `qir-adaptive` (comes from the
3434
/// cudaq-translate command line `--convert-to` parameter)
35-
/// @param performPrep Whether or not to perform the initial prep pass (normally
36-
/// true, but false for the WireSet QIR path)
37-
void addQIRProfilePipeline(mlir::OpPassManager &pm, llvm::StringRef convertTo,
38-
bool performPrep = true);
35+
/// \deprecated Replaced by the convert to QIR API pipeline.
36+
void addQIRProfilePipeline(mlir::OpPassManager &pm, llvm::StringRef convertTo);
37+
38+
void addQIRProfileVerify(mlir::OpPassManager &pm, llvm::StringRef convertTo);
3939

4040
void addLowerToCCPipeline(mlir::OpPassManager &pm);
4141
void addWiresetToProfileQIRPipeline(mlir::OpPassManager &pm,
4242
llvm::StringRef profile);
4343

44-
/// @brief Verify that all `CallOp` targets are QIR- or NVQIR-defined functions
45-
/// or in the provided allowed list.
44+
/// Verify that all `CallOp` targets are QIR- or NVQIR-defined functions or in
45+
/// the provided allowed list.
4646
std::unique_ptr<mlir::Pass>
4747
createVerifyNVQIRCallOpsPass(const std::vector<llvm::StringRef> &allowedFuncs);
4848

@@ -61,7 +61,18 @@ void registerCodeGenDialect(mlir::DialectRegistry &registry);
6161

6262
mlir::LLVM::LLVMStructType lambdaAsPairOfPointers(mlir::MLIRContext *context);
6363

64+
/// The pipeline for lowering Quake code to the QIR API. There will be three
65+
/// distinct flavors of QIR that can be generated with this pipeline. These
66+
/// are `"qir"`, `"qir-base"`, and `"qir-adaptive"`. This pipeline should be run
67+
/// before conversion to the LLVM-IR dialect.
68+
void registerToQIRAPIPipeline();
69+
void addConvertToQIRAPIPipeline(mlir::OpPassManager &pm, mlir::StringRef api,
70+
bool opaquePtr = false);
71+
72+
/// The pipeline for lowering Quake code to the execution manager API. This
73+
/// pipeline should be run before conversion to the LLVM-IR dialect.
6474
void registerToExecutionManagerCCPipeline();
75+
6576
void registerWireSetToProfileQIRPipeline();
6677
void populateCCTypeConversions(mlir::LLVMTypeConverter *converter);
6778

include/cudaq/Optimizer/CodeGen/Passes.td

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ def ConvertToQIR : Pass<"quake-to-qir", "mlir::ModuleOp"> {
6565
def LowerToCG : Pass<"lower-to-cg", "mlir::ModuleOp"> {
6666
let summary = "Lower Quake to CG dialect.";
6767
let description = [{
68-
For testing purposes only.
68+
Lower the Quake IR to the codegen dialect. The codegen dialect is used to
69+
fuse small DAGs of IR into larger macro operations just prior to the final
70+
codegen. This allows conversions to take place on the macro operations and
71+
avoid some of the limitations of an MLIR conversion pass.
6972
}];
7073
let dependentDialects = [ "cudaq::codegen::CodeGenDialect" ];
7174
}
@@ -212,4 +215,61 @@ def WireSetToProfileQIRPrep :
212215
let dependentDialects = ["cudaq::cc::CCDialect", "mlir::func::FuncDialect"];
213216
}
214217

218+
def QuakeToQIRAPI : Pass<"quake-to-qir-api"> {
219+
let summary = "Convert the Quake dialect to the QIR API.";
220+
let description = [{
221+
This pass converts Quake operations to the QIR API as expressed in terms
222+
of function calls to QIR functions.
223+
224+
Which QIR functions are to be used is parameterized on the `api` option.
225+
226+
This pass can lower to either use the obsolete opaque structure types (per
227+
the QIR spec) or to use LLVM's currently supported opaque pointers. In the
228+
latter case, type information is fully understood from the function names
229+
themselves.
230+
}];
231+
232+
let dependentDialects = ["cudaq::cc::CCDialect", "mlir::arith::ArithDialect",
233+
"mlir::cf::ControlFlowDialect", "mlir::func::FuncDialect",
234+
"mlir::LLVM::LLVMDialect"];
235+
236+
let options = [
237+
Option<"api", "api", "std::string", /*default=*/"\"full\"",
238+
"Select the QIR API to use.">,
239+
Option<"opaquePtr", "opaque-pointer", "bool", /*default=*/"false",
240+
"Use opaque pointers.">
241+
];
242+
}
243+
244+
def QuakeToQIRAPIFinal : Pass<"quake-to-qir-api-final", "mlir::ModuleOp"> {
245+
let summary = "Convert the Quake dialect to the QIR API finalization.";
246+
let description = [{
247+
}];
248+
249+
let dependentDialects = ["cudaq::cc::CCDialect", "mlir::arith::ArithDialect",
250+
"mlir::cf::ControlFlowDialect", "mlir::func::FuncDialect",
251+
"mlir::LLVM::LLVMDialect"];
252+
253+
let options = [
254+
Option<"api", "api", "std::string", /*default=*/"\"full\"",
255+
"Select the QIR API to use.">
256+
];
257+
}
258+
259+
def QuakeToQIRAPIPrep : Pass<"quake-to-qir-api-prep", "mlir::ModuleOp"> {
260+
let summary = "Convert the Quake dialect to the QIR API preparation.";
261+
let description = [{
262+
}];
263+
let dependentDialects = ["cudaq::cc::CCDialect", "mlir::arith::ArithDialect",
264+
"mlir::cf::ControlFlowDialect", "mlir::func::FuncDialect",
265+
"mlir::LLVM::LLVMDialect", "cudaq::codegen::CodeGenDialect"];
266+
let options = [
267+
Option<"api", "api", "std::string", /*default=*/"\"full\"",
268+
"Select the QIR API to use.">,
269+
Option<"opaquePtr", "opaque-pointer", "bool", /*default=*/"false",
270+
"Use opaque pointers.">
271+
];
272+
}
273+
274+
215275
#endif // CUDAQ_OPT_OPTIMIZER_CODEGEN_PASSES

include/cudaq/Optimizer/CodeGen/Peephole.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#pragma once
1010

1111
#include "cudaq/Optimizer/CodeGen/QIRFunctionNames.h"
12+
#include "cudaq/Optimizer/CodeGen/QIROpaqueStructTypes.h"
1213
#include "cudaq/Optimizer/Dialect/Quake/QuakeOps.h"
1314
#include "llvm/ADT/StringRef.h"
1415
#include "mlir/IR/ValueRange.h"

include/cudaq/Optimizer/CodeGen/Pipelines.h

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,41 @@
2121

2222
namespace cudaq::opt {
2323

24-
/// The common pipeline.
25-
/// Adds the common pipeline (with or without a profile specifier) but without
26-
/// the final QIR profile lowering passes.
27-
void commonPipelineConvertToQIR(
24+
/// Adds the common pipeline. \p codeGenFor specifies which variant of QIR is to
25+
/// be generated: full, base-profile, adaptive-profile, etc. \p passConfigAs
26+
/// specifies which variant of QIR to use with \e other passes, and not the
27+
/// final `codegen`, in the pipeline. Typically, \p codeGenFor and \p
28+
/// passConfigAs will have identical values.
29+
void commonPipelineConvertToQIR(mlir::PassManager &pm,
30+
mlir::StringRef codeGenFor = "qir",
31+
mlir::StringRef passConfigAs = "qir");
32+
33+
/// \deprecated{Only for Python, since it can't use the new QIR codegen.}
34+
void commonPipelineConvertToQIR_PythonWorkaround(
2835
mlir::PassManager &pm, const std::optional<mlir::StringRef> &convertTo);
2936

3037
/// \brief Pipeline builder to convert Quake to QIR.
3138
/// Does not specify a particular QIR profile.
3239
inline void addPipelineConvertToQIR(mlir::PassManager &pm) {
33-
commonPipelineConvertToQIR(pm, std::nullopt);
40+
commonPipelineConvertToQIR(pm);
41+
}
42+
43+
/// \deprecated{Only for Python, since it can't use the new QIR codegen.}
44+
inline void addPipelineConvertToQIR_PythonWorkaround(mlir::PassManager &pm) {
45+
commonPipelineConvertToQIR_PythonWorkaround(pm, std::nullopt);
3446
}
3547

3648
/// \brief Pipeline builder to convert Quake to QIR.
3749
/// Specifies a particular QIR profile in \p convertTo.
3850
/// \p pm Pass manager to append passes to
3951
/// \p convertTo name of QIR profile (e.g., `qir-base`, `qir-adaptive`, ...)
40-
inline void addPipelineConvertToQIR(mlir::PassManager &pm,
41-
mlir::StringRef convertTo) {
42-
commonPipelineConvertToQIR(pm, convertTo);
52+
void addPipelineConvertToQIR(mlir::PassManager &pm, mlir::StringRef convertTo);
53+
54+
/// \deprecated{Only for Python, since it can't use the new QIR codegen.}
55+
inline void
56+
addPipelineConvertToQIR_PythonWorkaround(mlir::PassManager &pm,
57+
mlir::StringRef convertTo) {
58+
commonPipelineConvertToQIR_PythonWorkaround(pm, convertTo);
4359
addQIRProfilePipeline(pm, convertTo);
4460
}
4561

include/cudaq/Optimizer/CodeGen/QIRAttributeNames.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,7 @@ static constexpr const char QIRRequiredResultsAttrName[] = "requiredResults";
2323
static constexpr const char QIRIrreversibleFlagName[] = "irreversible";
2424

2525
static constexpr const char StartingOffsetAttrName[] = "StartingOffset";
26+
static constexpr const char ResultIndexAttrName[] = "ResultIndex";
27+
static constexpr const char MzAssignedNameAttrName[] = "MzAssignedName";
2628

2729
} // namespace cudaq::opt

include/cudaq/Optimizer/CodeGen/QIRFunctionNames.h

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
/// This file provides some common QIR function names for use throughout our
1212
/// MLIR lowering infrastructure.
1313

14-
#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
15-
1614
namespace cudaq::opt {
1715

1816
/// QIS Function name strings
@@ -21,14 +19,19 @@ static constexpr const char QIRMeasureBody[] = "__quantum__qis__mz__body";
2119
static constexpr const char QIRMeasure[] = "__quantum__qis__mz";
2220
static constexpr const char QIRMeasureToRegister[] =
2321
"__quantum__qis__mz__to__register";
22+
static constexpr const char QIRResetBody[] = "__quantum__qis__reset__body";
23+
static constexpr const char QIRReset[] = "__quantum__qis__reset";
2424

25-
static constexpr const char QIRCnot[] = "__quantum__qis__cnot";
25+
static constexpr const char QIRCnot[] = "__quantum__qis__cnot__body";
2626
static constexpr const char QIRCphase[] = "__quantum__qis__cphase";
27-
static constexpr const char QIRCZ[] = "__quantum__qis__cz";
27+
static constexpr const char QIRCZ[] = "__quantum__qis__cz__body";
2828
static constexpr const char QIRReadResultBody[] =
2929
"__quantum__qis__read_result__body";
3030

3131
static constexpr const char QIRCustomOp[] = "__quantum__qis__custom_unitary";
32+
static constexpr const char QIRCustomAdjOp[] =
33+
"__quantum__qis__custom_unitary__adj";
34+
static constexpr const char QIRExpPauli[] = "__quantum__qis__exp_pauli";
3235

3336
static constexpr const char NVQIRInvokeWithControlBits[] =
3437
"invokeWithControlQubits";
@@ -38,6 +41,8 @@ static constexpr const char NVQIRInvokeU3RotationWithControlBits[] =
3841
"invokeU3RotationWithControlQubits";
3942
static constexpr const char NVQIRInvokeWithControlRegisterOrBits[] =
4043
"invokeWithControlRegisterOrQubits";
44+
static constexpr const char NVQIRGeneralizedInvokeAny[] =
45+
"generalizedInvokeWithRotationsControlsTargets";
4146
static constexpr const char NVQIRPackSingleQubitInArray[] =
4247
"packSingleQubitInArray";
4348
static constexpr const char NVQIRReleasePackedQubitArray[] =
@@ -89,30 +94,4 @@ static constexpr const char QIRRecordOutput[] =
8994
static constexpr const char QIRClearResultMaps[] =
9095
"__quantum__rt__clear_result_maps";
9196

92-
inline mlir::Type getQuantumTypeByName(mlir::StringRef type,
93-
mlir::MLIRContext *context) {
94-
return mlir::LLVM::LLVMStructType::getOpaque(type, context);
95-
}
96-
97-
inline mlir::Type getQubitType(mlir::MLIRContext *context) {
98-
return mlir::LLVM::LLVMPointerType::get(
99-
getQuantumTypeByName("Qubit", context));
100-
}
101-
102-
inline mlir::Type getArrayType(mlir::MLIRContext *context) {
103-
return mlir::LLVM::LLVMPointerType::get(
104-
getQuantumTypeByName("Array", context));
105-
}
106-
107-
inline mlir::Type getResultType(mlir::MLIRContext *context) {
108-
return mlir::LLVM::LLVMPointerType::get(
109-
getQuantumTypeByName("Result", context));
110-
}
111-
112-
inline mlir::Type getCharPointerType(mlir::MLIRContext *context) {
113-
return mlir::LLVM::LLVMPointerType::get(mlir::IntegerType::get(context, 8));
114-
}
115-
116-
void initializeTypeConversions(mlir::LLVMTypeConverter &typeConverter);
117-
11897
} // namespace cudaq::opt
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/****************************************************************-*- C++ -*-****
2+
* Copyright (c) 2022 - 2024 NVIDIA Corporation & Affiliates. *
3+
* All rights reserved. *
4+
* *
5+
* This source code and the accompanying materials are made available under *
6+
* the terms of the Apache License 2.0 which accompanies this distribution. *
7+
******************************************************************************/
8+
9+
#pragma once
10+
11+
/// This file provides the opaque struct types to be used with the obsolete LLVM
12+
/// typed pointer type.
13+
14+
#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
15+
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
16+
17+
namespace cudaq {
18+
inline mlir::Type getQuantumTypeByName(mlir::StringRef type,
19+
mlir::MLIRContext *context) {
20+
return mlir::LLVM::LLVMStructType::getOpaque(type, context);
21+
}
22+
23+
namespace opt {
24+
25+
// The following type creators are deprecated and should only be used in the
26+
// older codegen passes. Use the creators in the cg namespace immediately below
27+
// instead.
28+
inline mlir::Type getOpaquePointerType(mlir::MLIRContext *context) {
29+
return mlir::LLVM::LLVMPointerType::get(context);
30+
}
31+
32+
inline mlir::Type getQubitType(mlir::MLIRContext *context) {
33+
return mlir::LLVM::LLVMPointerType::get(
34+
getQuantumTypeByName("Qubit", context));
35+
}
36+
37+
inline mlir::Type getArrayType(mlir::MLIRContext *context) {
38+
return mlir::LLVM::LLVMPointerType::get(
39+
getQuantumTypeByName("Array", context));
40+
}
41+
42+
inline mlir::Type getResultType(mlir::MLIRContext *context) {
43+
return mlir::LLVM::LLVMPointerType::get(
44+
getQuantumTypeByName("Result", context));
45+
}
46+
47+
inline mlir::Type getCharPointerType(mlir::MLIRContext *context) {
48+
return mlir::LLVM::LLVMPointerType::get(mlir::IntegerType::get(context, 8));
49+
}
50+
51+
void initializeTypeConversions(mlir::LLVMTypeConverter &typeConverter);
52+
53+
} // namespace opt
54+
55+
namespace cg {
56+
57+
// The following type creators replace the ones above. They are configurable on
58+
// the fly to either use opaque structs or opaque pointers. The default is to
59+
// use pointers to opaque structs, which is no longer supported in modern LLVM.
60+
61+
inline mlir::Type getOpaquePointerType(mlir::MLIRContext *context) {
62+
return cc::PointerType::get(mlir::NoneType::get(context));
63+
}
64+
65+
inline mlir::Type getQubitType(mlir::MLIRContext *context,
66+
bool useOpaquePtr = false) {
67+
if (useOpaquePtr)
68+
return getOpaquePointerType(context);
69+
return cc::PointerType::get(getQuantumTypeByName("Qubit", context));
70+
}
71+
72+
inline mlir::Type getArrayType(mlir::MLIRContext *context,
73+
bool useOpaquePtr = false) {
74+
if (useOpaquePtr)
75+
return getOpaquePointerType(context);
76+
return cc::PointerType::get(getQuantumTypeByName("Array", context));
77+
}
78+
79+
inline mlir::Type getResultType(mlir::MLIRContext *context,
80+
bool useOpaquePtr = false) {
81+
if (useOpaquePtr)
82+
return getOpaquePointerType(context);
83+
return cc::PointerType::get(getQuantumTypeByName("Result", context));
84+
}
85+
86+
inline mlir::Type getCharPointerType(mlir::MLIRContext *context,
87+
bool useOpaquePtr = false) {
88+
if (useOpaquePtr)
89+
return getOpaquePointerType(context);
90+
return cc::PointerType::get(mlir::IntegerType::get(context, 8));
91+
}
92+
93+
} // namespace cg
94+
} // namespace cudaq

0 commit comments

Comments
 (0)