|
2 | 2 |
|
3 | 3 | !Zq0 = !mod_arith.int<1095233372161 : i64> |
4 | 4 | !Zq1 = !mod_arith.int<1032955396097 : i64> |
| 5 | +!Zq2 = !mod_arith.int<1002198353921 : i64> |
5 | 6 | #ring_1 = #polynomial.ring<coefficientType = !rns.rns<!Zq0>, polynomialModulus = <1 + x**1024>> |
6 | 7 | !poly_ty_1 = !polynomial.polynomial<ring=#ring_1, form=coeff> |
| 8 | +!ntt_poly_ty_1 = !polynomial.polynomial<ring=#ring_1, form=eval> |
7 | 9 |
|
8 | 10 | #ring_2 = #polynomial.ring<coefficientType = !rns.rns<!Zq0, !Zq1>, polynomialModulus = <1 + x**1024>> |
9 | 11 | !poly_ty_2 = !polynomial.polynomial<ring=#ring_2, form=coeff> |
10 | 12 |
|
| 13 | +#ring_3 = #polynomial.ring<coefficientType = !rns.rns<!Zq0, !Zq1, !Zq2>, polynomialModulus = <1 + x**1024>> |
| 14 | +!poly_ty_3 = !polynomial.polynomial<ring=#ring_3, form=coeff> |
| 15 | + |
| 16 | +#ring_4 = #polynomial.ring<coefficientType = !rns.rns<!Zq1>, polynomialModulus = <1 + x**1024>> |
| 17 | +!poly_ty_4 = !polynomial.polynomial<ring=#ring_4, form=coeff> |
| 18 | +!ntt_poly_ty_4 = !polynomial.polynomial<ring=#ring_4, form=eval> |
| 19 | + |
11 | 20 | module { |
12 | 21 | // Covers: a shared-dataflow circuit where optimal placement must avoid |
13 | 22 | // redundant conversions on mul chains while still satisfying coeff-only |
@@ -42,4 +51,28 @@ module { |
42 | 51 | %out = polynomial.convert_basis %prod {targetBasis = !rns.rns<!Zq0>} : !poly_ty_2 -> !poly_ty_1 |
43 | 52 | return %out, %x_t, %shift_t : !poly_ty_1, tensor<1024x!rns.rns<!Zq0, !Zq1>>, tensor<1024x!rns.rns<!Zq0, !Zq1>> |
44 | 53 | } |
| 54 | + |
| 55 | + // Covers: limb-aware conversion costs can move NTTs past extract_slice. |
| 56 | + // Old unweighted costs would hoist one NTT on %x; the weighted model keeps |
| 57 | + // %x in coeff form and inserts two cheaper one-limb NTTs on the slices. |
| 58 | + // CHECK: func.func @weighted_extract_slice_ntt_placement([[x:%.+]]: [[poly_ty_3:![^ ]+]]) -> ([[ntt_poly_ty_1:![^ ]+]], [[ntt_poly_ty_4:![^ ]+]], tensor<1024x[[RNS3:![^ ]+]]>) { |
| 59 | + // CHECK-NOT: polynomial.ntt |
| 60 | + // CHECK: [[a:%.+]] = polynomial.extract_slice [[x]] {size = 1 : index, start = 0 : index} : [[poly_ty_3]] -> [[poly_ty_1:![^ ]+]] |
| 61 | + // CHECK: [[a_ntt:%.+]] = polynomial.ntt [[a]] : [[poly_ty_1]] |
| 62 | + // CHECK: [[b:%.+]] = polynomial.extract_slice [[x]] {size = 1 : index, start = 1 : index} : [[poly_ty_3]] -> [[poly_ty_4:![^ ]+]] |
| 63 | + // CHECK: [[b_ntt:%.+]] = polynomial.ntt [[b]] : [[poly_ty_4]] |
| 64 | + // CHECK: [[ma:%.+]] = polynomial.mul [[a_ntt]], [[a_ntt]] : [[ntt_poly_ty_1]] |
| 65 | + // CHECK: [[mb:%.+]] = polynomial.mul [[b_ntt]], [[b_ntt]] : [[ntt_poly_ty_4]] |
| 66 | + // CHECK: [[x_t:%.+]] = polynomial.to_tensor [[x]] : [[poly_ty_3]] -> tensor<1024x[[RNS3]]> |
| 67 | + // CHECK: return [[ma]], [[mb]], [[x_t]] : [[ntt_poly_ty_1]], [[ntt_poly_ty_4]], tensor<1024x[[RNS3]]> |
| 68 | + func.func @weighted_extract_slice_ntt_placement(%x: !poly_ty_3) -> (!poly_ty_1, !poly_ty_4, tensor<1024x!rns.rns<!Zq0, !Zq1, !Zq2>>) { |
| 69 | + %a = polynomial.extract_slice %x {start = 0 : index, size = 1 : index} |
| 70 | + : !poly_ty_3 -> !poly_ty_1 |
| 71 | + %b = polynomial.extract_slice %x {start = 1 : index, size = 1 : index} |
| 72 | + : !poly_ty_3 -> !poly_ty_4 |
| 73 | + %ma = polynomial.mul %a, %a : !poly_ty_1 |
| 74 | + %mb = polynomial.mul %b, %b : !poly_ty_4 |
| 75 | + %x_t = polynomial.to_tensor %x : !poly_ty_3 -> tensor<1024x!rns.rns<!Zq0, !Zq1, !Zq2>> |
| 76 | + return %ma, %mb, %x_t : !poly_ty_1, !poly_ty_4, tensor<1024x!rns.rns<!Zq0, !Zq1, !Zq2>> |
| 77 | + } |
45 | 78 | } |
0 commit comments