Skip to content

Commit ab1aa29

Browse files
j2kuncopybara-github
authored andcommitted
add mgmt.bootstrap to validate-scale
PiperOrigin-RevId: 962306977
1 parent 3f5a1f7 commit ab1aa29

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

lib/Transforms/ValidateScale/ValidateScale.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,33 @@ struct ValidateScale : impl::ValidateScaleBase<ValidateScale> {
166166
}
167167
}
168168
}
169+
170+
// 5. Bootstrap
171+
if (auto bootstrapOp = dyn_cast<mgmt::BootstrapOp>(op)) {
172+
Value input = bootstrapOp.getInput();
173+
Value res = bootstrapOp.getResult();
174+
auto inScale = getScale(input);
175+
auto resScale = getScale(res);
176+
if (inScale && resScale) {
177+
const auto& logqi = param.getLogqi();
178+
if (logqi.empty()) {
179+
result =
180+
bootstrapOp.emitOpError("scheme parameters logqi is empty");
181+
return;
182+
}
183+
int64_t firstModBits = static_cast<int64_t>(std::llround(logqi[0]));
184+
if (*inScale > firstModBits - 1) {
185+
result = bootstrapOp.emitOpError(
186+
"input scale must be less than or equal to first-mod-bits - 1");
187+
return;
188+
}
189+
if (*resScale != param.getLogDefaultScale()) {
190+
result = bootstrapOp.emitOpError(
191+
"output scale must match the default scale");
192+
return;
193+
}
194+
}
195+
}
169196
});
170197
return result;
171198
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: heir-opt --validate-scale --verify-diagnostics --split-input-file %s
2+
3+
// Case 1: Valid bootstrap (should pass)
4+
module attributes {ckks.schemeParam = #ckks.scheme_param<logN = 13, Q = [36028797019389953, 35184372121601], P = [36028797019488257], logDefaultScale = 45>, scheme.ckks} {
5+
func.func @bootstrap_success(%arg0: !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 54>}) -> !secret.secret<f32> {
6+
%0 = secret.generic(%arg0 : !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 54>}) {
7+
^body(%input0: f32):
8+
// first-mod-bits = round(log2(36028797019389953)) = 55
9+
// input scale 54 <= 55 - 1 (54) -> OK
10+
// output scale 45 == logDefaultScale (45) -> OK
11+
%1 = mgmt.bootstrap %input0 {id = 0 : i64, mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>} : f32
12+
secret.yield %1 : f32
13+
} -> (!secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>})
14+
return %0 : !secret.secret<f32>
15+
}
16+
}
17+
18+
// -----
19+
20+
// Case 2: Input scale too large
21+
module attributes {ckks.schemeParam = #ckks.scheme_param<logN = 13, Q = [36028797019389953, 35184372121601], P = [36028797019488257], logDefaultScale = 45>, scheme.ckks} {
22+
func.func @bootstrap_input_scale_too_large(%arg0: !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 55>}) -> !secret.secret<f32> {
23+
%0 = secret.generic(%arg0 : !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 55>}) {
24+
^body(%input0: f32):
25+
// first-mod-bits = 55
26+
// input scale 55 > 55 - 1 (54) -> Fail
27+
// expected-error @+1 {{input scale must be less than or equal to first-mod-bits - 1}}
28+
%1 = mgmt.bootstrap %input0 {id = 0 : i64, mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>} : f32
29+
secret.yield %1 : f32
30+
} -> (!secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>})
31+
return %0 : !secret.secret<f32>
32+
}
33+
}
34+
35+
// -----
36+
37+
// Case 3: Output scale mismatch
38+
module attributes {ckks.schemeParam = #ckks.scheme_param<logN = 13, Q = [36028797019389953, 35184372121601], P = [36028797019488257], logDefaultScale = 45>, scheme.ckks} {
39+
func.func @bootstrap_output_scale_mismatch(%arg0: !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>}) -> !secret.secret<f32> {
40+
%0 = secret.generic(%arg0 : !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>}) {
41+
^body(%input0: f32):
42+
// output scale 46 != logDefaultScale (45) -> Fail
43+
// expected-error @+1 {{output scale must match the default scale}}
44+
%1 = mgmt.bootstrap %input0 {id = 0 : i64, mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 46>} : f32
45+
secret.yield %1 : f32
46+
} -> (!secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 46>})
47+
return %0 : !secret.secret<f32>
48+
}
49+
}

0 commit comments

Comments
 (0)