Skip to main content

Parasol compiler

Our next-generation compiler is designed to make it easy for any engineer to write highly optimized FHE programs.

Instead of rewriting an application in some niche eDSL, our vision is that engineers should bring their existing program written in a mainstream language and simply add directives to indicate which functions are FHE programs and which inputs should be kept hidden!

Initially, we support C. Depending on demand, we may add support for Rust as well.

How Parasol differs from our first generation compiler

If you worked with our first generation FHE compiler, you may wonder how our new one differs.

Some important changes to call out include:

  • Moving away from an eDSL approach. Now, developers can write directly in a mainstream language.
  • Moving from the BFV scheme to our own variant of TFHE. This allows us to more easily and cheaply support comparison operations.
  • Unlimited computation over encrypted data. Previously, we could only support bounded computation.
  • Program composability is now simpler to provide. Previously, programs could be generated under different scheme parameters, meaning that they would not be compatible with one another. Our new compiler uses fixed parameters so that we no longer have this issue.

Some hardcore technical details about our approach

To provide a great developer experience, we build an LLVM-based compiler. The benefits of this approach are twofold. First, it allows developers to use a variety of mainstream programming languages like Rust, C, or C++ with the only changes to their programs being the directives mentioned above. Second, it allows us to leverage decades worth of optimizations and transformations that are already built into LLVM.

Building the Parasol compiler was very technically challenging and required designing and implementing a virtual processor that operates over a mix of plaintext and encrypted data (aka the parasol processor). The processor is integrated as a backend for the LLVM toolchain, which requires us to map our instruction set architecture to the internal LLVM representations. We adopt an out-of-order processor design and feature dynamic scheduling within instructions to maximize parallelism.

Our compiler and processor rely on an in-house created variant of the TFHE scheme. We chose TFHE as it gives developers access to a variety of operations—most importantly, comparisons. A key feature of FHE is “bootstrapping” which is an operation to reduce noise in ciphertexts, allowing us to compute indefinitely. It tends to be a relatively expensive operation to perform, and there are various flavors of bootstrapping for the TFHE scheme.

What’s special about our TFHE variant is that it utilizes circuit bootstrapping and (homomorphic) multiplexer trees to realize arbitrary computation. This form of bootstrapping, if configured correctly, allows us to extract and maximize parallelism in programs. In taking this approach, we rely on a cheap multiplexer operation to do data propagation. In contrast, when working with functional/programmable bootstrapping, data propagation is instead achieved through the much more expensive bootstrap operation.

The benefits of our approach may not be obvious on laptops or smaller machines but maximizing parallelism will be key to unlocking FHE’s performance promise over the coming years.