doc(compiler): Enhance FHE Dialect documentation

This commit is contained in:
Quentin Bourgerie
2022-01-04 20:55:18 +01:00
parent fcf5ee05d5
commit 4ecae140ca
4 changed files with 120 additions and 13 deletions

View File

@@ -18,9 +18,17 @@ include "concretelang/Dialect/FHE/IR/FHETypes.td"
class FHE_Op<string mnemonic, list<OpTrait> traits = []> :
Op<FHE_Dialect, mnemonic, traits>;
// Generates an encrypted zero constant
def ZeroEintOp : FHE_Op<"zero", [NoSideEffect]> {
let summary = "Return an encryption of 0";
let summary = "Returns a trivial encrypted integer of 0";
let description = [{
Returns a trivial encrypted integer of 0
Example:
```mlir
"FHE.zero"() : () -> !FHE.eint<2>
```
}];
let arguments = (ins);
let results = (outs EncryptedIntegerType:$out);
@@ -30,6 +38,22 @@ def AddEintIntOp : FHE_Op<"add_eint_int"> {
let summary = "Adds an encrypted integer and a clear integer";
let description = [{
Adds an encrypted integer and a clear integer.
The clear integer must have at most one more bit than the encrypted integer
and the result must have the same width than the encrypted integer.
Example:
```mlir
// ok
"FHE.add_eint_int"(%a, %i) : (!FHE.eint<2>, i3) -> !FHE.eint<2>
// error
"FHE.add_eint_int"(%a, %i) : (!FHE.eint<2>, i4) -> !FHE.eint<2>
"FHE.add_eint_int"(%a, %i) : (!FHE.eint<2>, i3) -> !FHE.eint<3>
```
}];
let arguments = (ins EncryptedIntegerType:$a, AnyInteger:$b);
let results = (outs EncryptedIntegerType);
@@ -48,6 +72,21 @@ def AddEintOp : FHE_Op<"add_eint"> {
let summary = "Adds two encrypted integers";
let description = [{
Adds two encrypted integers
The encrypted integers and the result must have the same width.
Example:
```mlir
// ok
"FHE.add_eint"(%a, %b): (!FHE.eint<2>, !FHE.eint<2>) -> (!FHE.eint<2>)
// error
"FHE.add_eint"(%a, %b): (!FHE.eint<2>, !FHE.eint<3>) -> (!FHE.eint<2>)
"FHE.add_eint"(%a, %b): (!FHE.eint<2>, !FHE.eint<2>) -> (!FHE.eint<3>)
```
}];
let arguments = (ins EncryptedIntegerType:$a, EncryptedIntegerType:$b);
let results = (outs EncryptedIntegerType);
@@ -66,6 +105,22 @@ def SubIntEintOp : FHE_Op<"sub_int_eint"> {
let summary = "Substract a clear integer and an encrypted integer";
let description = [{
Substract a clear integer and an encrypted integer.
The clear integer must have at most one more bit than the encrypted integer
and the result must have the same width than the encrypted integer.
Example:
```mlir
// ok
"FHE.sub_int_eint"(%i, %a) : (i3, !FHE.eint<2>) -> !FHE.eint<2>
// error
"FHE.sub_int_eint"(%i, %a) : (i4, !FHE.eint<2>) -> !FHE.eint<2>
"FHE.sub_int_eint"(%i, %a) : (i3, !FHE.eint<2>) -> !FHE.eint<3>
```
}];
let arguments = (ins AnyInteger:$a, EncryptedIntegerType:$b);
let results = (outs EncryptedIntegerType);
@@ -84,6 +139,20 @@ def NegEintOp : FHE_Op<"neg_eint"> {
let summary = "Negates an encrypted integer";
let description = [{
Negates an encrypted integer.
The result must have the same width than the encrypted integer.
Example:
```mlir
// ok
"FHE.neg_eint"(%a): (!FHE.eint<2>) -> (!FHE.eint<2>)
// error
"FHE.neg_eint"(%a): (!FHE.eint<2>) -> (!FHE.eint<3>)
```
}];
let arguments = (ins EncryptedIntegerType:$a);
let results = (outs EncryptedIntegerType);
@@ -102,6 +171,22 @@ def MulEintIntOp : FHE_Op<"mul_eint_int"> {
let summary = "Mulitplies an encrypted integer and a clear integer";
let description = [{
Mulitplies an encrypted integer and a clear integer.
The clear integer must have at most one more bit than the encrypted integer
and the result must have the same width than the encrypted integer.
Example:
```mlir
// ok
"FHE.mul_eint_int"(%a, %i) : (!FHE.eint<2>, i3) -> !FHE.eint<2>
// error
"FHE.mul_eint_int"(%a, %i) : (!FHE.eint<2>, i4) -> !FHE.eint<2>
"FHE.mul_eint_int"(%a, %i) : (!FHE.eint<2>, i3) -> !FHE.eint<3>
```
}];
let arguments = (ins EncryptedIntegerType:$a, AnyInteger:$b);
let results = (outs EncryptedIntegerType);
@@ -120,8 +205,24 @@ def ApplyLookupTableEintOp : FHE_Op<"apply_lookup_table"> {
let summary = "Applies a clear lookup table to an encrypted integer";
let arguments = (ins EncryptedIntegerType:$ct,
TensorOf<[AnyInteger]>:$l_cst);
let description = [{
Applies a clear lookup table to an encrypted integer, the width of the result can be different than the width of the operand.
The lookup table must be a tensor of size equals to `2^p` where `p` is the width of the encrypted integer.
Example:
```mlir
// ok
"FHE.apply_lookup_table"(%a, %lut): (!FHE.eint<2>, tensor<4xi64>) -> (!FHE.eint<2>)
"FHE.apply_lookup_table"(%a, %lut): (!FHE.eint<2>, tensor<4xi64>) -> (!FHE.eint<3>)
"FHE.apply_lookup_table"(%a, %lut): (!FHE.eint<3>, tensor<4xi64>) -> (!FHE.eint<2>)
// error
"FHE.apply_lookup_table"(%a, %lut): (!FHE.eint<2>, tensor<8xi64>) -> (!FHE.eint<2>)
```
}];
let arguments = (ins EncryptedIntegerType:$a,
TensorOf<[AnyInteger]>:$lut);
let results = (outs EncryptedIntegerType);
let verifier = [{

View File

@@ -14,7 +14,13 @@ def EncryptedIntegerType : FHE_Type<"EncryptedInteger",
let summary = "An encrypted integer";
let description = [{
An encrypted integer with clear precision of width.
An encrypted integer with `width` bits to performs FHE Operations.
Examples:
```mlir
!FHE.eint<7>
!FHE.eint<6>
```
}];
let parameters = (ins "unsigned":$width);

View File

@@ -107,20 +107,20 @@ bool verifyEncryptedIntegerInputsConsistency(::mlir::OpState &op,
}
::mlir::LogicalResult verifyApplyLookupTable(ApplyLookupTableEintOp &op) {
auto ct = op.ct().getType().cast<EncryptedIntegerType>();
auto l_cst = op.l_cst().getType().cast<TensorType>();
auto ct = op.a().getType().cast<EncryptedIntegerType>();
auto lut = op.lut().getType().cast<TensorType>();
auto result = op.getResult().getType().cast<EncryptedIntegerType>();
// Check the shape of l_cst argument
// Check the shape of lut argument
auto width = ct.getWidth();
auto expectedSize = 1 << width;
auto lCstShape = l_cst.getShape();
auto lCstShape = lut.getShape();
mlir::SmallVector<int64_t, 1> expectedShape{expectedSize};
if (!l_cst.hasStaticShape(expectedShape)) {
emitErrorBadLutSize(op, "l_cst", "ct", expectedSize, width);
if (!lut.hasStaticShape(expectedShape)) {
emitErrorBadLutSize(op, "lut", "ct", expectedSize, width);
return mlir::failure();
}
if (!l_cst.getElementType().isInteger(64)) {
if (!lut.getElementType().isInteger(64)) {
op.emitOpError() << "should have the i64 constant";
return mlir::failure();
}

View File

@@ -1,6 +1,6 @@
// RUN: not concretecompiler --action=roundtrip %s 2>&1| FileCheck %s
// CHECK-LABEL: error: 'FHE.apply_lookup_table' op : `l_cst` (operand #2) inner dimension should have size 4(=2^2) to match `ct` (operand #1) elements bitwidth (2)
// CHECK-LABEL: error: 'FHE.apply_lookup_table' op : `lut` (operand #2) inner dimension should have size 4(=2^2) to match `ct` (operand #1) elements bitwidth (2)
func @apply_lookup_table(%arg0: !FHE.eint<2>, %arg1: tensor<8xi3>) -> !FHE.eint<2> {
%1 = "FHE.apply_lookup_table"(%arg0, %arg1): (!FHE.eint<2>, tensor<8xi3>) -> (!FHE.eint<2>)
return %1: !FHE.eint<2>