forked from NVIDIA/cuda-quantum
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlift_array.qke
More file actions
174 lines (153 loc) · 11.1 KB
/
lift_array.qke
File metadata and controls
174 lines (153 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// ========================================================================== //
// Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. //
// All rights reserved. //
// //
// This source code and the accompanying materials are made available under //
// the terms of the Apache License 2.0 which accompanies this distribution. //
// ========================================================================== //
// RUN: cudaq-opt -lift-array-alloc %s | FileCheck %s
// RXN: cudaq-opt -lift-array-alloc -globalize-array-values %s | FileCheck --check-prefix=GLOBAL %s
func.func @__nvqpp__mlirgen__function_test_complex_constant_array._Z27test_complex_constant_arrayv() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} {
%cst = complex.constant [0.707106769 : f32, 0.000000e+00 : f32] : complex<f32>
%cst_0 = complex.constant [0.000000e+00 : f32, 0.000000e+00 : f32] : complex<f32>
%0 = cc.alloca !cc.array<complex<f32> x 4>
%1 = cc.cast %0 : (!cc.ptr<!cc.array<complex<f32> x 4>>) -> !cc.ptr<complex<f32>>
cc.store %cst, %1 : !cc.ptr<complex<f32>>
%2 = cc.compute_ptr %0[1] : (!cc.ptr<!cc.array<complex<f32> x 4>>) -> !cc.ptr<complex<f32>>
cc.store %cst, %2 : !cc.ptr<complex<f32>>
%3 = cc.compute_ptr %0[2] : (!cc.ptr<!cc.array<complex<f32> x 4>>) -> !cc.ptr<complex<f32>>
cc.store %cst_0, %3 : !cc.ptr<complex<f32>>
%4 = cc.compute_ptr %0[3] : (!cc.ptr<!cc.array<complex<f32> x 4>>) -> !cc.ptr<complex<f32>>
cc.store %cst_0, %4 : !cc.ptr<complex<f32>>
%5 = quake.alloca !quake.veq<2>
%6 = quake.init_state %5, %1 : (!quake.veq<2>, !cc.ptr<complex<f32>>) -> !quake.veq<2>
return
}
// CHECK-LABEL: func.func @__nvqpp__mlirgen__function_test_complex_constant_array._Z27test_complex_constant_arrayv() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} {
// CHECK: %[[VAL_0:.*]] = cc.const_array {{\[\[}}0.707106769 : f32, 0.000000e+00 : f32], [0.707106769 : f32, 0.000000e+00 : f32], [0.000000e+00 : f32, 0.000000e+00 : f32], [0.000000e+00 : f32, 0.000000e+00 : f32]] : !cc.array<complex<f32> x 4>
// CHECK: %[[VAL_1:.*]] = cc.alloca !cc.array<complex<f32> x 4>
// CHECK: cc.store %[[VAL_0]], %[[VAL_1]] : !cc.ptr<!cc.array<complex<f32> x 4>>
// CHECK: %[[VAL_2:.*]] = cc.cast %[[VAL_1]] : (!cc.ptr<!cc.array<complex<f32> x 4>>) -> !cc.ptr<complex<f32>>
// CHECK: %[[VAL_3:.*]] = quake.alloca !quake.veq<2>
// CHECK: %[[VAL_4:.*]] = quake.init_state %[[VAL_3]], %[[VAL_2]] : (!quake.veq<2>, !cc.ptr<complex<f32>>) -> !quake.veq<2>
// CHECK: return
// CHECK: }
// GLOBAL-LABEL: func.func @__nvqpp__mlirgen__function_test_complex_constant_array._Z27test_complex_constant_arrayv() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} {
// GLOBAL: %[[VAL_0:.*]] = cc.address_of @__nvqpp__mlirgen__function_test_complex_constant_array._Z27test_complex_constant_arrayv.rodata_{{[0-9]+}} : !cc.ptr<!cc.array<complex<f32> x 4>>
// GLOBAL: %[[VAL_1:.*]] = quake.alloca !quake.veq<2>
// GLOBAL: %[[VAL_2:.*]] = quake.init_state %[[VAL_1]], %[[VAL_0]] : (!quake.veq<2>, !cc.ptr<!cc.array<complex<f32> x 4>>) -> !quake.veq<2>
// GLOBAL: return
// GLOBAL: }
func.func private @__nvqpp_vectorCopyCtor(!cc.ptr<i8>, i64, i64) -> !cc.ptr<i8>
func.func @__nvqpp__mlirgen__function_custom_h_generator_1._Z20custom_h_generator_1v() -> !cc.stdvec<complex<f64>> attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} {
%cst = complex.constant [0.70710678118654757, 0.000000e+00] : complex<f64>
%cst_0 = complex.constant [-0.70710678118654757, 0.000000e+00] : complex<f64>
%c16_i64 = arith.constant 16 : i64
%c4_i64 = arith.constant 4 : i64
%0 = cc.alloca !cc.array<complex<f64> x 4>
%1 = cc.cast %0 : (!cc.ptr<!cc.array<complex<f64> x 4>>) -> !cc.ptr<complex<f64>>
cc.store %cst, %1 : !cc.ptr<complex<f64>>
%2 = cc.compute_ptr %0[1] : (!cc.ptr<!cc.array<complex<f64> x 4>>) -> !cc.ptr<complex<f64>>
cc.store %cst, %2 : !cc.ptr<complex<f64>>
%3 = cc.compute_ptr %0[2] : (!cc.ptr<!cc.array<complex<f64> x 4>>) -> !cc.ptr<complex<f64>>
cc.store %cst, %3 : !cc.ptr<complex<f64>>
%4 = cc.compute_ptr %0[3] : (!cc.ptr<!cc.array<complex<f64> x 4>>) -> !cc.ptr<complex<f64>>
cc.store %cst_0, %4 : !cc.ptr<complex<f64>>
%5 = cc.cast %0 : (!cc.ptr<!cc.array<complex<f64> x 4>>) -> !cc.ptr<i8>
%6 = call @__nvqpp_vectorCopyCtor(%5, %c4_i64, %c16_i64) : (!cc.ptr<i8>, i64, i64) -> !cc.ptr<i8>
%7 = cc.stdvec_init %6, %c4_i64 : (!cc.ptr<i8>, i64) -> !cc.stdvec<complex<f64>>
return %7 : !cc.stdvec<complex<f64>>
}
// CHECK-LABEL: func.func @__nvqpp__mlirgen__function_custom_h_generator_1._Z20custom_h_generator_1v() -> !cc.stdvec<complex<f64>> attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} {
// CHECK: %[[VAL_0:.*]] = arith.constant 16 : i64
// CHECK: %[[VAL_1:.*]] = arith.constant 4 : i64
// CHECK: %[[VAL_2:.*]] = cc.const_array {{\[\[}}0.70710678118654757, 0.000000e+00], [0.70710678118654757, 0.000000e+00], [0.70710678118654757, 0.000000e+00], [-0.70710678118654757, 0.000000e+00]] : !cc.array<complex<f64> x 4>
// CHECK: %[[VAL_3:.*]] = cc.alloca !cc.array<complex<f64> x 4>
// CHECK: cc.store %[[VAL_2]], %[[VAL_3]] : !cc.ptr<!cc.array<complex<f64> x 4>>
// CHECK: %[[VAL_4:.*]] = cc.cast %[[VAL_3]] : (!cc.ptr<!cc.array<complex<f64> x 4>>) -> !cc.ptr<i8>
// CHECK: %[[VAL_5:.*]] = call @__nvqpp_vectorCopyCtor(%[[VAL_4]], %[[VAL_1]], %[[VAL_0]]) : (!cc.ptr<i8>, i64, i64) -> !cc.ptr<i8>
// CHECK: %[[VAL_6:.*]] = cc.stdvec_init %[[VAL_5]], %[[VAL_1]] : (!cc.ptr<i8>, i64) -> !cc.stdvec<complex<f64>>
// CHECK: return %[[VAL_6]] : !cc.stdvec<complex<f64>>
// CHECK: }
// GLOBAL-LABEL: func.func @__nvqpp__mlirgen__function_custom_h_generator_1._Z20custom_h_generator_1v() -> !cc.stdvec<complex<f64>> attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} {
// GLOBAL: %[[VAL_0:.*]] = arith.constant 16 : i64
// GLOBAL: %[[VAL_1:.*]] = arith.constant 4 : i64
// GLOBAL: %[[VAL_2:.*]] = cc.address_of @__nvqpp__mlirgen__function_custom_h_generator_1._Z20custom_h_generator_1v.rodata_{{[0-9]+}} : !cc.ptr<!cc.array<complex<f64> x 4>>
// GLOBAL: %[[VAL_3:.*]] = cc.cast %[[VAL_2]] : (!cc.ptr<!cc.array<complex<f64> x 4>>) -> !cc.ptr<i8>
// GLOBAL: %[[VAL_4:.*]] = call @__nvqpp_vectorCopyCtor(%[[VAL_3]], %[[VAL_1]], %[[VAL_0]]) : (!cc.ptr<i8>, i64, i64) -> !cc.ptr<i8>
// GLOBAL: %[[VAL_5:.*]] = cc.stdvec_init %[[VAL_4]], %[[VAL_1]] : (!cc.ptr<i8>, i64) -> !cc.stdvec<complex<f64>>
// GLOBAL: return %[[VAL_5]] : !cc.stdvec<complex<f64>>
// GLOBAL: }
func.func @test2() -> !quake.veq<2> {
%cst = arith.constant 9.000000e+00 : f64
%cst_0 = arith.constant 6.000000e+00 : f64
%cst_1 = arith.constant 2.000000e+00 : f64
%cst_2 = arith.constant 1.000000e+00 : f64
%0 = cc.alloca !cc.array<f64 x 4>
%1 = cc.compute_ptr %0[0] : (!cc.ptr<!cc.array<f64 x 4>>) -> !cc.ptr<f64>
cc.store %cst_2, %1 : !cc.ptr<f64>
%2 = cc.compute_ptr %0[1] : (!cc.ptr<!cc.array<f64 x 4>>) -> !cc.ptr<f64>
cc.store %cst_1, %2 : !cc.ptr<f64>
%3 = cc.compute_ptr %0[2] : (!cc.ptr<!cc.array<f64 x 4>>) -> !cc.ptr<f64>
cc.store %cst_0, %3 : !cc.ptr<f64>
%4 = cc.compute_ptr %0[3] : (!cc.ptr<!cc.array<f64 x 4>>) -> !cc.ptr<f64>
cc.store %cst, %4 : !cc.ptr<f64>
%5 = quake.alloca !quake.veq<2>
%6 = quake.init_state %5, %0 : (!quake.veq<2>, !cc.ptr<!cc.array<f64 x 4>>) -> !quake.veq<2>
return %6 : !quake.veq<2>
}
// CHECK-LABEL: func.func @test2() -> !quake.veq<2> {
// CHECK: %[[VAL_0:.*]] = cc.const_array [1.000000e+00, 2.000000e+00, 6.000000e+00, 9.000000e+00] : !cc.array<f64 x 4>
// CHECK: %[[VAL_1:.*]] = cc.alloca !cc.array<f64 x 4>
// CHECK: cc.store %[[VAL_0]], %[[VAL_1]] : !cc.ptr<!cc.array<f64 x 4>>
// CHECK: %[[VAL_2:.*]] = quake.alloca !quake.veq<2>
// CHECK: %[[VAL_3:.*]] = quake.init_state %[[VAL_2]], %[[VAL_1]] : (!quake.veq<2>, !cc.ptr<!cc.array<f64 x 4>>) -> !quake.veq<2>
// CHECK: return %[[VAL_3]] : !quake.veq<2>
// CHECK: }
// GLOBAL-LABEL: func.func @test2() -> !quake.veq<2> {
// GLOBAL: %[[VAL_0:.*]] = cc.address_of @test2.rodata_{{[0-9]+}} : !cc.ptr<!cc.array<f64 x 4>>
// GLOBAL: %[[VAL_1:.*]] = quake.alloca !quake.veq<2>
// GLOBAL: %[[VAL_2:.*]] = quake.init_state %[[VAL_1]], %[[VAL_0]] : (!quake.veq<2>, !cc.ptr<!cc.array<f64 x 4>>) -> !quake.veq<2>
// GLOBAL: return %[[VAL_2]] : !quake.veq<2>
// GLOBAL: }
// GLOBAL-DAG: cc.global constant private @__nvqpp__mlirgen__function_test_complex_constant_array._Z27test_complex_constant_arrayv.rodata_{{[0-9]+}} (dense<[(0.707106769,0.000000e+00), (0.707106769,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00)]> : tensor<4xcomplex<f32>>) : !cc.array<complex<f32> x 4>
// GLOBAL-DAG: cc.global constant private @__nvqpp__mlirgen__function_custom_h_generator_1._Z20custom_h_generator_1v.rodata_{{[0-9]+}} (dense<[(0.70710678118654757,0.000000e+00), (0.70710678118654757,0.000000e+00), (0.70710678118654757,0.000000e+00), (-0.70710678118654757,0.000000e+00)]> : tensor<4xcomplex<f64>>) : !cc.array<complex<f64> x 4>
// GLOBAL-DAG: cc.global constant private @test2.rodata_{{[0-9]+}} (dense<[1.000000e+00, 2.000000e+00, 6.000000e+00, 9.000000e+00]>" : tensor<4xf64>) : !cc.array<f64 x 4>
func.func @test_two_stores() {
%c0_i64 = arith.constant 0 : i64
%c1_i64 = arith.constant 1 : i64
// qubits = cudaq.qvector(2)
%0 = quake.alloca !quake.veq<2>
// arr1 = [1]
%1 = cc.alloca !cc.array<i64 x 1>
%2 = cc.cast %1 : (!cc.ptr<!cc.array<i64 x 1>>) -> !cc.ptr<i64>
cc.store %c1_i64, %2 : !cc.ptr<i64>
// t = arr1[0]
%3 = cc.load %2 : !cc.ptr<i64>
// arr2 = [0]
%4 = cc.alloca !cc.array<i64 x 1>
%5 = cc.cast %4 : (!cc.ptr<!cc.array<i64 x 1>>) -> !cc.ptr<i64>
cc.store %c0_i64, %5 : !cc.ptr<i64> // Dominates the next store, don't lift
// arr2[0] = t
cc.store %3, %5 : !cc.ptr<i64>
// b = arr2[0]
%6 = cc.load %5 : !cc.ptr<i64>
// x(qubits[b])
%7 = quake.extract_ref %0[%6] : (!quake.veq<2>, i64) -> !quake.ref
quake.x %7 : (!quake.ref) -> ()
return
}
// CHECK-LABEL: func.func @test_two_stores() {
// CHECK: %[[VAL_0:.*]] = arith.constant 0 : i64
// CHECK: %[[VAL_1:.*]] = quake.alloca !quake.veq<2>
// CHECK: %[[VAL_2:.*]] = cc.const_array [1] : !cc.array<i64 x 1>
// CHECK: %[[VAL_3:.*]] = cc.extract_value %[[VAL_2]][0] : (!cc.array<i64 x 1>) -> i64
// CHECK: %[[VAL_4:.*]] = cc.alloca !cc.array<i64 x 1>
// CHECK: %[[VAL_5:.*]] = cc.cast %[[VAL_4]] : (!cc.ptr<!cc.array<i64 x 1>>) -> !cc.ptr<i64>
// CHECK: cc.store %[[VAL_0]], %[[VAL_5]] : !cc.ptr<i64>
// CHECK: cc.store %[[VAL_3]], %[[VAL_5]] : !cc.ptr<i64>
// CHECK: %[[VAL_6:.*]] = cc.load %[[VAL_5]] : !cc.ptr<i64>
// CHECK: %[[VAL_7:.*]] = quake.extract_ref %[[VAL_1]][%[[VAL_6]]] : (!quake.veq<2>, i64) -> !quake.ref
// CHECK: quake.x %[[VAL_7]] : (!quake.ref) -> ()
// CHECK: return
// CHECK: }