This commit brings support for multiple secret keys in the TFHE
dialect. In particular, a parameterized `TFHE` circuit can now be
given as input, with any combination of (semantically valid) of
ks/bs/woppbs mixing different secret keys, and compiled down to a
valid executable function, with server keys properly looked up.
Secret keys are now stateful objects which can be:
-> none/unparameterized (syntax `sk?`): The keys are in state after
the lowering from the `FHE` dialect.
-> parameterized (syntax `sk<identifier, polysize, dimension>`): The
keys were parameterized, either by user or by the optimizer. The
`identifier` field can be used to disambiguate two keys with same
`polysize` and `dimension`.
-> normalized (syntax `sk[index]<polysize, dimension>`): The keys were
attached to their index in the list of keys in the runtime context.
The _normalization_ of key indices also acts on the ksk, bsk and pksk,
which are given indices in the same spirit now.
Finally, in order to allow parameterized `TFHE` circuit to be given
as input and compiled down to executable functions, we added a way to
pass the encodings that are used to encode/decode the circuit
inputs/outputs. In the case of a compilation from the `FHE` dialect,
those informations are automatically extracted from the higher level
informations available in this dialect.
Google benchmark is built twice due to the new bench infrastructure for
concrete-cuda, this commit fixes it by introducing
CONCRETE_CUDA_BUILD_TESTS and CONCRETE_CUDA_BUILD_BENCHMARKS options to skip
unecessary builds.
For debugging purpose, add a cmake variable that allows to generate
unsecure keycaches, that allows tracing ops to show the message in the
ciphertext body.
Re-introduce the previously deleted batching tests for BConcrete as
tests for TFHE with the addition of a new test, checking that
non-batchable operands generated by pure operations are hoisted.
With TFHE operations becoming batchable, the batching pass must now be
run after the conversion to TFHE,and TFHE parametrization, but before
any further lowering.
The batching pass only creates a batched version of a batchable
operation if all of its non-batchable operands are defined out ouf the
outermost loop the iterating over the values of the batchable operand.
This change also allows for operations to be batched if the
non-batachable operands are generated by operations, which are pure
and thus hoistable out of the outermost loop.
An early test for a batchable operation checks whether the batchable
operand is produced by a `tensor.extract` operation and bails out if
this is not the case. However, the use of `llvm::dyn_cast<T>()` directly
on the defining operation of the batchable operand causes an attempt
to cast a null value for an operand which is not produced by an
operation (e.g., block arguments).
Using `llvm::dyn_cast_or_null<T>()` fixes this issue.