LLZK 2.1.1
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
PodToScalarPass.cpp File Reference

This file implements the -llzk-pod-to-scalar pass. More...

#include "llzk/Dialect/Array/IR/Dialect.h"
#include "llzk/Dialect/Bool/IR/Dialect.h"
#include "llzk/Dialect/Cast/IR/Dialect.h"
#include "llzk/Dialect/Constrain/IR/Dialect.h"
#include "llzk/Dialect/Felt/IR/Dialect.h"
#include "llzk/Dialect/Function/IR/Dialect.h"
#include "llzk/Dialect/Function/IR/Ops.h"
#include "llzk/Dialect/Include/IR/Dialect.h"
#include "llzk/Dialect/LLZK/IR/Dialect.h"
#include "llzk/Dialect/LLZK/IR/Ops.h"
#include "llzk/Dialect/POD/IR/Dialect.h"
#include "llzk/Dialect/POD/IR/Ops.h"
#include "llzk/Dialect/POD/IR/Types.h"
#include "llzk/Dialect/POD/Transforms/TransformationPasses.h"
#include "llzk/Dialect/Polymorphic/IR/Dialect.h"
#include "llzk/Dialect/RAM/IR/Dialect.h"
#include "llzk/Dialect/String/IR/Dialect.h"
#include "llzk/Dialect/Struct/IR/Ops.h"
#include "llzk/Transforms/LLZKConversionUtils.h"
#include "llzk/Transforms/SpecializedMemoryPasses.h"
#include "llzk/Util/Concepts.h"
#include "llzk/Util/Walk.h"
#include <mlir/Dialect/SCF/IR/SCF.h>
#include <mlir/Pass/PassManager.h>
#include <mlir/Transforms/DialectConversion.h>
#include <mlir/Transforms/GreedyPatternRewriteDriver.h>
#include <mlir/Transforms/Passes.h>
#include <llvm/ADT/DenseMapInfo.h>
#include <llvm/ADT/STLExtras.h>
#include <llvm/Support/Debug.h>
#include "llzk/Dialect/POD/Transforms/TransformationPasses.h.inc"
Include dependency graph for PodToScalarPass.cpp:

Go to the source code of this file.

Classes

class  llzk::pod::impl::PodToScalarPassBase< DerivedT >
struct  llvm::DenseMapInfo< RecordChain >

Namespaces

namespace  llzk
namespace  llzk::pod
namespace  llzk::pod::impl
namespace  llvm

Macros

#define GEN_PASS_DEF_PODTOSCALARPASS
#define DEBUG_TYPE   "llzk-pod-to-scalar"

Functions

std::unique_ptr<::mlir::Pass > llzk::pod::impl::createPodToScalarPass ()
std::unique_ptr<::mlir::Pass > llzk::pod::createPodToScalarPass ()

Detailed Description

This file implements the -llzk-pod-to-scalar pass.

The steps of this transformation are as follows:

  1. Scan to find llzk.nondet ops that allocate uninitialized pods and replace them with an equivalent pod.new
  2. Run a dialect conversion that replaces PodType struct members with one scalar member per record and remembers how each original member was split.
  3. Run a dialect conversion that does the following:
    • Replace MemberReadOp and MemberWriteOp targeting the members that were split in step 1 so they instead perform scalar reads and writes from the new members. The transformation is local to the current op. Therefore, when replacing the MemberReadOp a new pod is created locally and all uses of the MemberReadOp are replaced with the new pod Value, then each scalar member read is followed by scalar write into the new pod. Similarly, when replacing a MemberWriteOp, each element in the pod operand needs a scalar read from the pod followed by a scalar write to the new member. Making only local changes keeps this step simple and later steps will optimize.
    • Remove optional initialization from NewPodOp and instead insert a list of WritePodOp immediately following.
    • Split pods to scalars in FuncDefOp, CallOp, and ReturnOp and insert the necessary create/read/write ops so the changes are as local as possible (just as described for MemberReadOp and MemberWriteOp)
  4. Promote pod reads and writes out of scf.if, scf.for, and scf.while regions when the access can be modeled as an SSA value flowing through the region boundary. This puts the pod accesses that mem2reg must eliminate into a parent block or loop-carried value.
  5. Run MLIR "sroa" pass to split each pod with N records into N pods with 1 record each (to prepare for the "mem2reg" pass because its API cannot split memory by itself).
  6. Run MLIR "mem2reg" pass to convert all single-record pod allocations and accesses into SSA values.

** Steps 4 and 5 are rerun while nested POD types are still being exposed, until a fixpoint.

Note: This transformation imposes a "last write wins" semantics on pod records. If different/configurable semantics are added in the future, some additional transformation would be necessary before/during this pass so that multiple writes to the same record can be handled properly while they still exist.

Note: This transformation will introduce a nondet op when there exists a read from a pod record that was not earlier written to.

Definition in file PodToScalarPass.cpp.

Macro Definition Documentation

◆ DEBUG_TYPE

#define DEBUG_TYPE   "llzk-pod-to-scalar"

Definition at line 106 of file PodToScalarPass.cpp.

◆ GEN_PASS_DEF_PODTOSCALARPASS

#define GEN_PASS_DEF_PODTOSCALARPASS

Definition at line 96 of file PodToScalarPass.cpp.