Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
ORNL Quantum Computing Institute
qcor
Commits
85894c95
Unverified
Commit
85894c95
authored
Jun 28, 2021
by
Mccaskey, Alex
Committed by
GitHub
Jun 28, 2021
Browse files
Merge pull request #171 from tnguyen-ornl/tnguyen/mlir-value-semantics
Added MLIR optimization passes and code refactor
parents
9a14001d
09c51bf3
Changes
61
Hide whitespace changes
Inline
Side-by-side
mlir/dialect/include/Quantum/QuantumOps.td
View file @
85894c95
...
...
@@ -152,4 +152,24 @@ def CreateStringLiteralOp : QuantumOp<"createString", []> {
p << "q.create_string(\"" << op.text() << "\")"; }];
}
// Cast QIR Result to bool (i1 type)
def ResultCastOp : QuantumOp<"resultCast", []> {
let arguments = (ins ResultType:$measure_result);
let results = (outs I1:$bit_result);
let printer = [{ auto op = *this;
p << "q.resultCast" << "(" << op.measure_result() << ") : " << op.bit_result().getType(); }];
}
// Sign-Unsign cast:
// Rationale: std dialect only accepts signless type (i.e. int but not uint)
// we need to have this cast op in the dialect to finally lower to LLVM cast
// which can handle int -> uint casting at the final lowering phase.
// Note: std.index_cast cannot handle int -> unit casting (one of the type must be an index type).
def IntegerCastOp : QuantumOp<"integerCast", []> {
let arguments = (ins AnyInteger:$input);
let results = (outs AnyInteger:$output);
let printer = [{ auto op = *this;
p << "q.integerCast" << "(" << op.input() << ") : " << op.output().getType(); }];
}
#endif // Quantum_OPS
\ No newline at end of file
mlir/dialect/lib/Quantum/QuantumDialect.cpp
View file @
85894c95
...
...
@@ -2,10 +2,43 @@
#include "Quantum/QuantumDialect.h"
#include "Quantum/QuantumOps.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/Transforms/InliningUtils.h"
using
namespace
mlir
;
using
namespace
mlir
::
quantum
;
namespace
{
/// Inliner interface
/// This class defines the interface for handling inlining with Quantum
/// operations.
// We simplify inherit from the base interface class and override
/// the necessary methods.
struct
QuantumInlinerInterface
:
public
DialectInlinerInterface
{
using
DialectInlinerInterface
::
DialectInlinerInterface
;
/// This hook checks to see if the given callable operation is legal to inline
/// into the given call.
/// Operations in Quantum dialect are always legal to inline.
bool
isLegalToInline
(
Operation
*
call
,
Operation
*
callable
,
bool
wouldBeCloned
)
const
final
{
return
true
;
}
/// This hook checks to see if the given operation is legal to inline into the
/// given region.
/// Only inline VSOp for now:
// FIXME: there is a weird error when qalloc is inlined at MLIR level
// hence, just allow VSOp to be inlined for the timebeing.
// i.e. all quantum subroutines that only contain VSOp's can be inlined.
bool
isLegalToInline
(
Operation
*
op
,
Region
*
regione
,
bool
,
BlockAndValueMapping
&
)
const
final
{
if
(
dyn_cast_or_null
<
mlir
::
quantum
::
ValueSemanticsInstOp
>
(
op
))
{
return
true
;
}
return
false
;
}
};
}
// namespace
//===----------------------------------------------------------------------===//
// Quantum dialect.
//===----------------------------------------------------------------------===//
...
...
@@ -15,12 +48,13 @@ void QuantumDialect::initialize() {
#define GET_OP_LIST
#include "Quantum/QuantumOps.cpp.inc"
>
();
addInterfaces
<
QuantumInlinerInterface
>
();
}
// static void print(mlir::OpAsmPrinter &printer, mlir::quantum::InstOp op) {
// printer << "q." << op.name() << "(" << *(op.qubits().begin());
// for (auto i = 1; i < op.qubits().size(); i++) {
// printer << ", " << op.qubits()[i];
// printer << ", " << op.qubits()[i];
// }
// printer << ")";
...
...
mlir/dialect/lib/Quantum/QuantumOps.cpp
View file @
85894c95
...
...
@@ -3,14 +3,12 @@
#include "Quantum/QuantumDialect.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/Builders.h"
bool
isOpaqueTypeWithName
(
mlir
::
Type
type
,
std
::
string
dialect
,
std
::
string
type_name
)
{
if
(
type
.
isa
<
mlir
::
OpaqueType
>
()
&&
dialect
==
"quantum"
)
{
if
(
type_name
==
"Qubit"
)
{
return
true
;
}
if
(
type_name
==
"Result"
)
{
if
(
type_name
==
"Qubit"
||
type_name
==
"Result"
||
type_name
==
"Array"
||
type_name
==
"ArgvType"
||
type_name
==
"QregType"
||
type_name
==
"StringType"
)
{
return
true
;
}
}
...
...
mlir/parsers/qasm3/examples/test_opt.qasm
0 → 100644
View file @
85894c95
OPENQASM 3;
include "qelib1.inc";
const n = 2;
qubit q[n];
x q[0];
ry(1.2345) q[1];
y q[1];
x q[1];
\ No newline at end of file
mlir/parsers/qasm3/examples/test_opt_permute.qasm
0 → 100644
View file @
85894c95
OPENQASM 3;
include "qelib1.inc";
const n = 2;
qubit q[n];
// Rz can be moved forward (pass CX) to combine with z
rz(1.2345) q[0];
cx q[0], q[1];
z q[0];
mlir/parsers/qasm3/handler/qasm3_handler.cpp
View file @
85894c95
...
...
@@ -7,6 +7,7 @@
#include "openqasmv3_mlir_generator.hpp"
#include "qasm3_handler_utils.hpp"
#include "quantum_to_llvm.hpp"
#include "pass_manager.hpp"
using
namespace
clang
;
...
...
@@ -129,6 +130,7 @@ void Qasm3SyntaxHandler::GetReplacement(Preprocessor &PP, Declarator &D,
std
::
vector
<
std
::
string
>
unique_f_names
{
kernel_name
};
mlir
::
PassManager
pm
(
&
context
);
applyPassManagerCLOptions
(
pm
);
qcor
::
configureOptimizationPasses
(
pm
);
pm
.
addPass
(
std
::
make_unique
<
qcor
::
QuantumToLLVMLoweringPass
>
(
true
,
unique_f_names
));
auto
module_op
=
(
*
module
).
getOperation
();
if
(
mlir
::
failed
(
pm
.
run
(
module_op
)))
{
...
...
mlir/parsers/qasm3/qasm3_visitor.hpp
View file @
85894c95
...
...
@@ -38,7 +38,7 @@ class qasm3_visitor : public qasm3::qasm3BaseVisitor {
mlir
::
Identifier
dialect
=
mlir
::
Identifier
::
get
(
"quantum"
,
context
);
qubit_type
=
mlir
::
OpaqueType
::
get
(
context
,
dialect
,
qubit_type_name
);
array_type
=
mlir
::
OpaqueType
::
get
(
context
,
dialect
,
array_type_name
);
result_type
=
mlir
::
Integer
Type
::
get
(
context
,
1
);
result_type
=
mlir
::
Opaque
Type
::
get
(
context
,
dialect
,
result_type_name
);
symbol_table
.
set_op_builder
(
builder
);
}
...
...
@@ -218,10 +218,18 @@ class qasm3_visitor : public qasm3::qasm3BaseVisitor {
"Cannot allocate and initialize memory, shape and number of initial "
"value indices is incorrect"
);
}
// Assert that the values to init the memref array
// must be of the expected type.
for
(
const
auto
&
init_val
:
initial_values
)
{
assert
(
init_val
.
getType
()
==
type
);
}
// Allocate
auto
allocation
=
allocate_1d_memory
(
location
,
shape
,
type
);
// and initialize
for
(
int
i
=
0
;
i
<
initial_values
.
size
();
i
++
)
{
assert
(
initial_indices
[
i
].
getType
().
isa
<
mlir
::
IndexType
>
());
builder
.
create
<
mlir
::
StoreOp
>
(
location
,
initial_values
[
i
],
allocation
,
initial_indices
[
i
]);
}
...
...
mlir/parsers/qasm3/tests/CMakeLists.txt
View file @
85894c95
...
...
@@ -86,3 +86,9 @@ add_executable(qasm3CompilerTester_Kernel test_kernel.cpp)
add_test
(
NAME qcor_qasm3_test_kernel COMMAND qasm3CompilerTester_Kernel
)
target_include_directories
(
qasm3CompilerTester_Kernel PRIVATE . ../../
${
CMAKE_SOURCE_DIR
}
/tools/clang-wrapper/
${
CMAKE_SOURCE_DIR
}
/handlers
${
XACC_ROOT
}
/include/gtest
)
target_link_libraries
(
qasm3CompilerTester_Kernel qcor-mlir-api gtest gtest_main qcor-clang-wrapper qcor-syntax-handler
${
CLANG_LIBS
}
)
add_executable
(
qasm3CompilerTester_PassManager test_optimization.cpp
)
add_test
(
NAME qcor_qasm3_test_pass_mamager COMMAND qasm3CompilerTester_PassManager
)
target_include_directories
(
qasm3CompilerTester_PassManager PRIVATE . ../../
${
CMAKE_SOURCE_DIR
}
/tools/clang-wrapper/
${
CMAKE_SOURCE_DIR
}
/handlers
${
XACC_ROOT
}
/include/gtest
)
target_link_libraries
(
qasm3CompilerTester_PassManager qcor-mlir-api gtest gtest_main qcor-clang-wrapper qcor-syntax-handler
${
CLANG_LIBS
}
)
mlir/parsers/qasm3/tests/test_alias_handler.cpp
View file @
85894c95
...
...
@@ -215,10 +215,10 @@ QCOR_EXPECT_TRUE(m10[3] == 0);
QCOR_EXPECT_TRUE(m10[4] == 0);
QCOR_EXPECT_TRUE(m10[5] == 1);
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
alias_by_indicies
,
"test"
,
auto
mlir
=
qcor
::
mlir_compile
(
alias_by_indicies
,
"test"
,
qcor
::
OutputType
::
MLIR
,
true
);
std
::
cout
<<
"MLIR:
\n
"
<<
mlir
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
alias_by_indicies
,
"test"
));
EXPECT_FALSE
(
qcor
::
execute
(
alias_by_indicies
,
"test"
));
}
int
main
(
int
argc
,
char
**
argv
)
{
...
...
mlir/parsers/qasm3/tests/test_assignment.cpp
View file @
85894c95
...
...
@@ -70,9 +70,9 @@ QCOR_EXPECT_TRUE(ff == 3.14);
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
src
,
"test"
,
qcor
::
OutputType
::
MLIR
,
true
);
qcor
::
mlir_compile
(
src
,
"test"
,
qcor
::
OutputType
::
MLIR
,
true
);
std
::
cout
<<
"MLIR:
\n
"
<<
mlir
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
src
,
"test"
));
EXPECT_FALSE
(
qcor
::
execute
(
src
,
"test"
));
}
int
main
(
int
argc
,
char
**
argv
)
{
...
...
mlir/parsers/qasm3/tests/test_bell.cpp
View file @
85894c95
...
...
@@ -21,12 +21,12 @@ for i in [0:100] {
print(count);
QCOR_EXPECT_TRUE(count > 30);
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
check_pow
,
"check_pow"
,
auto
mlir
=
qcor
::
mlir_compile
(
check_pow
,
"check_pow"
,
qcor
::
OutputType
::
MLIR
,
false
);
std
::
cout
<<
mlir
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
check_pow
,
"check_pow"
));
EXPECT_FALSE
(
qcor
::
execute
(
check_pow
,
"check_pow"
));
}
int
main
(
int
argc
,
char
**
argv
)
{
...
...
mlir/parsers/qasm3/tests/test_casting.cpp
View file @
85894c95
...
...
@@ -19,10 +19,10 @@ QCOR_EXPECT_TRUE(b3 == 1);
QCOR_EXPECT_TRUE(b4 == 1);
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
uint_index
,
"uint_index"
,
auto
mlir
=
qcor
::
mlir_compile
(
uint_index
,
"uint_index"
,
qcor
::
OutputType
::
MLIR
,
false
);
std
::
cout
<<
mlir
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
uint_index
,
"uint_index"
));
EXPECT_FALSE
(
qcor
::
execute
(
uint_index
,
"uint_index"
));
}
TEST
(
qasm3VisitorTester
,
checkCastBitToInt
)
{
...
...
@@ -34,12 +34,12 @@ int[4] t = int[4](c);
print(t);
QCOR_EXPECT_TRUE(t == 15);
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
cast_int
,
"cast_int"
,
auto
mlir
=
qcor
::
mlir_compile
(
cast_int
,
"cast_int"
,
qcor
::
OutputType
::
MLIR
,
false
);
std
::
cout
<<
"cast_int MLIR:
\n
"
<<
mlir
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
cast_int
,
"cast_int"
));
EXPECT_FALSE
(
qcor
::
execute
(
cast_int
,
"cast_int"
));
}
int
main
(
int
argc
,
char
**
argv
)
{
...
...
mlir/parsers/qasm3/tests/test_complex_arithmetic.cpp
View file @
85894c95
...
...
@@ -12,10 +12,10 @@ result = (shots - num_parity_ones) / shots - num_parity_ones / shots;
test = result - .007812;
QCOR_EXPECT_TRUE(test < .01);
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
global_const
,
"global_const"
,
auto
mlir
=
qcor
::
mlir_compile
(
global_const
,
"global_const"
,
qcor
::
OutputType
::
MLIR
,
false
);
std
::
cout
<<
mlir
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
global_const
,
"global_const"
));
EXPECT_FALSE
(
qcor
::
execute
(
global_const
,
"global_const"
));
}
int
main
(
int
argc
,
char
**
argv
)
{
...
...
mlir/parsers/qasm3/tests/test_control_directives.cpp
View file @
85894c95
...
...
@@ -27,10 +27,10 @@ QCOR_EXPECT_TRUE(hit_continue_value == 2);
print("made it out of the loop");
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
uint_index
,
"uint_index"
,
auto
mlir
=
qcor
::
mlir_compile
(
uint_index
,
"uint_index"
,
qcor
::
OutputType
::
MLIR
,
false
);
std
::
cout
<<
mlir
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
uint_index
,
"uint_index"
));
EXPECT_FALSE
(
qcor
::
execute
(
uint_index
,
"uint_index"
));
}
...
...
mlir/parsers/qasm3/tests/test_declaration.cpp
View file @
85894c95
...
...
@@ -46,15 +46,15 @@ float[64] test = 3.14 - f;
QCOR_EXPECT_TRUE(test < .001);
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
src
,
"test"
,
qcor
::
OutputType
::
MLIR
,
true
);
qcor
::
mlir_compile
(
src
,
"test"
,
qcor
::
OutputType
::
MLIR
,
true
);
std
::
cout
<<
"MLIR:
\n
"
<<
mlir
<<
"
\n
"
;
auto
llvmi
=
qcor
::
mlir_compile
(
"qasm3"
,
src
,
"test"
,
qcor
::
OutputType
::
LLVMMLIR
,
true
);
qcor
::
mlir_compile
(
src
,
"test"
,
qcor
::
OutputType
::
LLVMMLIR
,
true
);
std
::
cout
<<
"LLVM:
\n
"
<<
llvmi
<<
"
\n
"
;
auto
llvm
=
qcor
::
mlir_compile
(
"qasm3"
,
src
,
"test"
,
qcor
::
OutputType
::
LLVMIR
,
true
);
qcor
::
mlir_compile
(
src
,
"test"
,
qcor
::
OutputType
::
LLVMIR
,
true
);
std
::
cout
<<
"LLVM:
\n
"
<<
llvm
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
src
,
"test"
));
EXPECT_FALSE
(
qcor
::
execute
(
src
,
"test"
));
const
std
::
string
src2
=
R"#(OPENQASM 3;
include "qelib1.inc";
...
...
@@ -65,9 +65,9 @@ for i in [0:22] {
}
)#"
;
auto
mlir2
=
qcor
::
mlir_compile
(
"qasm3"
,
src2
,
"test"
,
qcor
::
OutputType
::
MLIR
,
true
);
qcor
::
mlir_compile
(
src2
,
"test"
,
qcor
::
OutputType
::
MLIR
,
true
);
std
::
cout
<<
"MLIR:
\n
"
<<
mlir2
<<
"
\n
"
;
EXPECT_TRUE
(
qcor
::
execute
(
"qasm3"
,
src2
,
"test"
));
EXPECT_TRUE
(
qcor
::
execute
(
src2
,
"test"
));
}
...
...
mlir/parsers/qasm3/tests/test_default_designators.cpp
View file @
85894c95
...
...
@@ -24,10 +24,10 @@ print(d);
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
src
,
"test"
,
qcor
::
OutputType
::
MLIR
,
true
);
qcor
::
mlir_compile
(
src
,
"test"
,
qcor
::
OutputType
::
MLIR
,
true
);
std
::
cout
<<
"MLIR:
\n
"
<<
mlir
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
src
,
"test"
));
EXPECT_FALSE
(
qcor
::
execute
(
src
,
"test"
));
}
...
...
mlir/parsers/qasm3/tests/test_kernel.cpp
View file @
85894c95
...
...
@@ -20,11 +20,11 @@ print(j);
QCOR_EXPECT_TRUE(j == 20);
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
kernel_test
,
"kernel_test"
,
auto
mlir
=
qcor
::
mlir_compile
(
kernel_test
,
"kernel_test"
,
qcor
::
OutputType
::
MLIR
,
true
);
std
::
cout
<<
mlir
<<
"
\n
"
;
auto
llvm
=
qcor
::
mlir_compile
(
"qasm3"
,
kernel_test
,
"kernel_test"
,
auto
llvm
=
qcor
::
mlir_compile
(
kernel_test
,
"kernel_test"
,
qcor
::
OutputType
::
LLVMIR
,
true
);
std
::
cout
<<
llvm
<<
"
\n
"
;
...
...
@@ -43,7 +43,7 @@ int test_this(int i) { return i + 10; }
extra_code_to_link
.
push_back
(
std
::
move
(
module
));
// -------------------------------------------//
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
kernel_test
,
"kernel_test"
,
extra_code_to_link
,
0
));
EXPECT_FALSE
(
qcor
::
execute
(
kernel_test
,
"kernel_test"
,
extra_code_to_link
,
0
));
}
int
main
(
int
argc
,
char
**
argv
)
{
...
...
mlir/parsers/qasm3/tests/test_loop_stmts.cpp
View file @
85894c95
...
...
@@ -47,10 +47,10 @@ QCOR_EXPECT_TRUE(loop_count == 12);
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
for_stmt
,
"for_stmt"
,
auto
mlir
=
qcor
::
mlir_compile
(
for_stmt
,
"for_stmt"
,
qcor
::
OutputType
::
MLIR
,
false
);
std
::
cout
<<
"for_stmt MLIR:
\n
"
<<
mlir
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
for_stmt
,
"for_stmt"
));
EXPECT_FALSE
(
qcor
::
execute
(
for_stmt
,
"for_stmt"
));
const
std
::
string
while_stmt
=
R"#(OPENQASM 3;
include "qelib1.inc";
...
...
@@ -61,10 +61,10 @@ while (i < 10) {
}
QCOR_EXPECT_TRUE(i == 10);
)#"
;
auto
mlir2
=
qcor
::
mlir_compile
(
"qasm3"
,
while_stmt
,
"while_stmt"
,
auto
mlir2
=
qcor
::
mlir_compile
(
while_stmt
,
"while_stmt"
,
qcor
::
OutputType
::
MLIR
,
false
);
std
::
cout
<<
mlir2
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
while_stmt
,
"while_stmt"
));
EXPECT_FALSE
(
qcor
::
execute
(
while_stmt
,
"while_stmt"
));
const
std
::
string
decrement
=
R"#(OPENQASM 3;
include "qelib1.inc";
...
...
@@ -72,10 +72,10 @@ for j in [10:-1:0] {
print(j);
}
)#"
;
auto
mlir3
=
qcor
::
mlir_compile
(
"qasm3"
,
decrement
,
"decrement"
,
auto
mlir3
=
qcor
::
mlir_compile
(
decrement
,
"decrement"
,
qcor
::
OutputType
::
MLIR
,
false
);
std
::
cout
<<
mlir3
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
decrement
,
"decrement"
));
EXPECT_FALSE
(
qcor
::
execute
(
decrement
,
"decrement"
));
}
int
main
(
int
argc
,
char
**
argv
)
{
...
...
mlir/parsers/qasm3/tests/test_modifiers.cpp
View file @
85894c95
...
...
@@ -71,12 +71,12 @@ for i in [0:100] {
print(count);
)#"
;
auto
mlir
=
qcor
::
mlir_compile
(
"qasm3"
,
check_pow
,
"check_pow"
,
auto
mlir
=
qcor
::
mlir_compile
(
check_pow
,
"check_pow"
,
qcor
::
OutputType
::
MLIR
,
false
);
std
::
cout
<<
mlir
<<
"
\n
"
;
EXPECT_FALSE
(
qcor
::
execute
(
"qasm3"
,
check_pow
,
"check_pow"
));
EXPECT_FALSE
(
qcor
::
execute
(
check_pow
,
"check_pow"
));
}
int
main
(
int
argc
,
char
**
argv
)
{
...
...
mlir/parsers/qasm3/tests/test_optimization.cpp
0 → 100644
View file @
85894c95
#include "qcor_mlir_api.hpp"
#include "gtest/gtest.h"
namespace
{
// returns count of non-overlapping occurrences of 'sub' in 'str'
int
countSubstring
(
const
std
::
string
&
str
,
const
std
::
string
&
sub
)
{
if
(
sub
.
length
()
==
0
)
return
0
;
int
count
=
0
;
for
(
size_t
offset
=
str
.
find
(
sub
);
offset
!=
std
::
string
::
npos
;
offset
=
str
.
find
(
sub
,
offset
+
sub
.
length
()))
{
++
count
;
}
return
count
;
}
}
// namespace
TEST
(
qasm3PassManagerTester
,
checkIdentityPairRemoval
)
{
const
std
::
string
src
=
R"#(OPENQASM 3;
include "qelib1.inc";
qubit q[2];
x q[0];
x q[0];
cx q[0], q[1];
cx q[0], q[1];
)#"
;
auto
llvm
=
qcor
::
mlir_compile
(
src
,
"test"
,
qcor
::
OutputType
::
LLVMIR
,
true
);
std
::
cout
<<
"LLVM:
\n
"
<<
llvm
<<
"
\n
"
;
// No instrucions left
EXPECT_TRUE
(
llvm
.
find
(
"__quantum__qis"
)
==
std
::
string
::
npos
);
}
TEST
(
qasm3PassManagerTester
,
checkRotationMerge
)
{
const
std
::
string
src
=
R"#(OPENQASM 3;
include "qelib1.inc";
qubit q[2];
x q[0];
z q[1];
rx(1.2345) q[0];
rz(2.4566) q[1];
)#"
;
auto
llvm
=
qcor
::
mlir_compile
(
src
,
"test_kernel"
,
qcor
::
OutputType
::
LLVMIR
,
false
);
std
::
cout
<<
"LLVM:
\n
"
<<
llvm
<<
"
\n
"
;
// Get the function LLVM only (not __internal_mlir_XXXX, etc.)
llvm
=
llvm
.
substr
(
llvm
.
find
(
"@test_kernel"
));
// 2 instrucions left: rx and rz
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__qis"
),
2
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__qis__rx"
),
1
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__qis__rz"
),
1
);
}
TEST
(
qasm3PassManagerTester
,
checkSingleQubitGateMergeOpt
)
{
// Merge to X == rx(pi)
const
std
::
string
src
=
R"#(OPENQASM 3;
include "qelib1.inc";
qubit q[2];
h q[0];
z q[0];
h q[0];
)#"
;
auto
llvm
=
qcor
::
mlir_compile
(
src
,
"test_kernel"
,
qcor
::
OutputType
::
LLVMIR
,
false
);
std
::
cout
<<
"LLVM:
\n
"
<<
llvm
<<
"
\n
"
;
// Get the function LLVM only (not __internal_mlir_XXXX, etc.)
llvm
=
llvm
.
substr
(
llvm
.
find
(
"@test_kernel"
));
// 1 instrucions left: rx
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__qis"
),
1
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__qis__rx"
),
1
);
}
TEST
(
qasm3PassManagerTester
,
checkRemoveUnusedQirCalls
)
{
// Complete cancellation => remove extract and qalloc as well
const
std
::
string
src
=
R"#(OPENQASM 3;
include "qelib1.inc";
qubit q[2];
cx q[0], q[1];
h q[0];
z q[0];
h q[0];
x q[0];
cx q[0], q[1];
)#"
;
auto
llvm
=
qcor
::
mlir_compile
(
src
,
"test_kernel"
,
qcor
::
OutputType
::
LLVMIR
,
false
);
std
::
cout
<<
"LLVM:
\n
"
<<
llvm
<<
"
\n
"
;
// No gates, extract, or alloc/dealloc:
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__qis"
),
0
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__rt__array_get_element_ptr_1d"
),
0
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__rt__qubit_allocate_array"
),
0
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__rt__qubit_release_array"
),
0
);
}
TEST
(
qasm3PassManagerTester
,
checkInliner
)
{
// Inline a call ==> gate cancellation
const
std
::
string
src
=
R"#(OPENQASM 3;
include "qelib1.inc";
gate oracle b {
x b;
}
qubit q[2];
x q[0];
oracle q[0];
)#"
;
auto
llvm
=
qcor
::
mlir_compile
(
src
,
"test_kernel"
,
qcor
::
OutputType
::
LLVMIR
,
false
);
std
::
cout
<<
"LLVM:
\n
"
<<
llvm
<<
"
\n
"
;
// Get the main kernel section only (there is the oracle LLVM section as well)
llvm
=
llvm
.
substr
(
llvm
.
find
(
"@test_kernel"
));
const
auto
last
=
llvm
.
find_first_of
(
"}"
);
llvm
=
llvm
.
substr
(
0
,
last
+
1
);
std
::
cout
<<
"LLVM:
\n
"
<<
llvm
<<
"
\n
"
;
// No gates, extract, or alloc/dealloc:
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__qis"
),
0
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__rt__array_get_element_ptr_1d"
),
0
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__rt__qubit_allocate_array"
),
0
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__rt__qubit_release_array"
),
0
);
}
TEST
(
qasm3PassManagerTester
,
checkPermuteAndCancel
)
{
// Permute rz-cnot ==> gate cancellation
const
std
::
string
src
=
R"#(OPENQASM 3;
include "qelib1.inc";
qubit q[2];
rz(0.123) q[0];
cx q[0], q[1];
rz(-0.123) q[0];
cx q[0], q[1];
)#"
;
auto
llvm
=
qcor
::
mlir_compile
(
src
,
"test_kernel"
,
qcor
::
OutputType
::
LLVMIR
,
false
);
std
::
cout
<<
"LLVM:
\n
"
<<
llvm
<<
"
\n
"
;
// Get the main kernel section only (there is the oracle LLVM section as well)
llvm
=
llvm
.
substr
(
llvm
.
find
(
"@test_kernel"
));
const
auto
last
=
llvm
.
find_first_of
(
"}"
);
llvm
=
llvm
.
substr
(
0
,
last
+
1
);
std
::
cout
<<
"LLVM:
\n
"
<<
llvm
<<
"
\n
"
;
// Cancel all => No gates, extract, or alloc/dealloc:
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__qis"
),
0
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__rt__array_get_element_ptr_1d"
),
0
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__rt__qubit_allocate_array"
),
0
);
EXPECT_EQ
(
countSubstring
(
llvm
,
"__quantum__rt__qubit_release_array"
),
0
);
}
int
main
(
int
argc
,
char
**
argv
)
{
::
testing
::
InitGoogleTest
(
&
argc
,
argv
);
auto
ret
=
RUN_ALL_TESTS
();
return
ret
;
}
\ No newline at end of file
Prev
1
2
3
4
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment