Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,21 @@ config_setting(
},
)

# CHEDDAR GPU FHE backend (opt-in, requires CUDA)
# use by passing `--//:enable_cheddar=1` to `bazel build`
string_flag(
name = "enable_cheddar",
build_setting_default = "0",
)

config_setting(
name = "config_enable_cheddar",
flag_values = {
":enable_cheddar": "1",
},
visibility = ["//visibility:public"],
)

# OpenFHE interpreter
string_flag(
name = "openfhe_enable_timing",
Expand Down
14 changes: 14 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.8.2", dev_dependenc
# implicitly depends upon the target '//:license'. How bizarre.
bazel_dep(name = "rules_license", version = "1.0.0")
bazel_dep(name = "platforms", version = "1.0.0")
bazel_dep(name = "rules_cuda", version = "0.3.0")
bazel_dep(name = "rules_foreign_cc", version = "0.15.1")
bazel_dep(name = "rules_go", version = "0.53.0")
bazel_dep(name = "rules_python", version = "1.5.1")
bazel_dep(name = "googletest", version = "1.17.0")
Expand Down Expand Up @@ -64,6 +66,18 @@ use_repo(
"llvm_zstd",
)

# CHEDDAR GPU FHE library (opt-in, requires CUDA)
cheddar_extensions = use_extension("//bazel:extensions.bzl", "cheddar_deps")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So there's a lot of stuff in this PR around adding the cheddar backend (bazel overlay, opt-in config, etc.) but as far as I can tell nothing tests it because there are no end-to-end tests in this PR.

Can we either include an end-to-end test in this PR, or else have this PR only include the MLIR-only parts? (dialect, transforms, lit tests, emitter).

In particular, when I pull this branch to my local machine and I try running bazel build @cheddar, I get

$ bazel build @cheddar  
ERROR: /usr/local/google/home/jkun/.cache/bazel/_bazel_jkun/886f3804b421b5442165b2f8eb57dad5/external/rules_cuda++toolchain+cuda/BUILD: no such target '@@rules_cuda++toolchain+cuda//:thrust': target 'thrust' not declared in package '' defined by /usr/local/google/home/jkun/.cache/bazel/_bazel_jkun/886f3804b421b5442165b2f8eb57dad5/external/rules_cuda++toolchain+cuda/BUILD
ERROR: /usr/local/google/home/jkun/.cache/bazel/_bazel_jkun/886f3804b421b5442165b2f8eb57dad5/external/+cheddar_deps+cheddar/BUILD.bazel:50:11: no such target '@@rules_cuda++toolchain+cuda//:thrust': target 'thrust' not declared in package '' defined by /usr/local/google/home/jkun/.cache/bazel/_bazel_jkun/886f3804b421b5442165b2f8eb57dad5/external/rules_cuda++toolchain+cuda/BUILD and referenced by '@@+cheddar_deps+cheddar//:cheddar'
ERROR: Analysis of target '@@+cheddar_deps+cheddar//:cheddar' failed; build aborted: Analysis failed
INFO: Elapsed time: 1.340s, Critical Path: 0.02s
INFO: 1 process: 1 internal.
ERROR: Build did NOT complete successfully

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@missing tests: indeed, that's an oopsie on my side while extracting this out of the overall cheddar WIP branch. As we discussed in the office hour yesterday, I'll split this PR into three

  1. Dialect
  2. Emitter and FileCheck tests (I think I'll re-use this PR for this, to preserve the relevant review comments)
  3. Bazel dependency & end-to-end tests

@ local machine: Does your local machine have an Nvidia GPU with CUDA/etc installed? Otherwise, I'm pretty sure that this is an expected failure, due to @rules_cuda being unable to find the required CUDA related stuff? Maybe there's a way to set up the BUILD file to get a nicer/more helpful error message? Since you're directly asking bezel to build the cheddar target, enable_cheddar isn't "protecting" you here, I guess?

Copy link
Copy Markdown
Collaborator

@j2kun j2kun May 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From https://bazel-contrib.github.io/rules_cuda/0.3.0/

For hermetic toolchains, the rules handle toolchain configuration and library downloading automatically. See cuda.redist_json integration test for a comprehensible example.

For locally installed toolchains, _detect_local_cuda_toolkit and detect_clang determines how they are detected.

Either situation depends on cc toolchain availability, so you must also ensure the cc compiler is properly configured. On Windows, this means that you will also need to set the environment variable BAZEL_VC properly.

I would like to try this again on a machine that has an NVIDIA GPU as well as the hermetic LLVM toolchain. In theory, with the hermetic toolchain we should be able to build the targets even if the machine does not have a GPU or CUDA installed. But yes, we should split that into a standalone PR.

use_repo(cheddar_extensions, "cheddar")

# CUDA toolkit (for CHEDDAR and other GPU backends)
cuda = use_extension("@rules_cuda//cuda:extensions.bzl", "toolchain")
cuda.toolkit(
name = "cuda",
toolkit_path = "",
)
use_repo(cuda, "cuda")

# The subset of LLVM backend targets that should be compiled
_LLVM_TARGETS = [
"X86",
Expand Down
7 changes: 7 additions & 0 deletions bazel/cheddar/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This build file is necessary to mark this directory as a subpackage for bazel
# to have access to the files.

package(
default_applicable_licenses = ["@heir//:license"],
default_visibility = ["//visibility:public"],
)
56 changes: 56 additions & 0 deletions bazel/cheddar/cheddar.BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake")

package(
default_visibility = ["//visibility:public"],
)

filegroup(
name = "all_srcs",
srcs = glob(
["**"],
exclude = [
"bazel-*/**",
"build/**",
"cmake-build*/**",
],
),
)

cmake(
name = "cheddar_cmake",
cache_entries = {
"CMAKE_BUILD_TYPE": "Release",
"BUILD_UNITTEST": "OFF",
"ENABLE_EXTENSION": "ON",
"USE_GMP": "OFF",
# Build for the local GPU architecture to keep build times manageable.
"CMAKE_CUDA_ARCHITECTURES": "native",
# Assumes conventional CUDA toolkit location and configuration.
"CMAKE_CUDA_COMPILER": "/usr/local/cuda/bin/nvcc",
"CUDAToolkit_ROOT": "/usr/local/cuda",
"CMAKE_CUDA_HOST_COMPILER:FILEPATH": "/usr/bin/g++",
"CMAKE_CUDA_FLAGS": "-ccbin=/usr/bin/g++",
# Wipe toolchain-provided linker flags that can inject unsupported host options.
"CMAKE_EXE_LINKER_FLAGS": "",
"CMAKE_MODULE_LINKER_FLAGS": "",
"CMAKE_SHARED_LINKER_FLAGS": "",
},
generate_crosstool_file = False,
lib_source = ":all_srcs",
out_include_dir = "include",
out_shared_libs = [
"libcheddar.so",
],
targets = ["cheddar"],
)

# Wrap the cmake output with CUDA Thrust headers so downstream consumers
# can resolve cheddar's public #include <thrust/...> directives.
cc_library(
name = "cheddar",
deps = [
":cheddar_cmake",
"@cuda//:thrust",
],
)
21 changes: 21 additions & 0 deletions bazel/cheddar/config.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Helper macros for CHEDDAR opt-in build configuration."""

def if_cheddar_enabled(if_true, if_false = []):
"""Select based on whether CHEDDAR is enabled."""
return select({
"@heir//:config_enable_cheddar": if_true,
"//conditions:default": if_false,
})

def requires_cheddar():
"""Returns target_compatible_with for CHEDDAR-requiring targets."""
return select({
"@heir//:config_enable_cheddar": [],
"//conditions:default": ["@platforms//:incompatible"],
})

def cheddar_deps(extra = []):
"""Returns CHEDDAR library deps, empty when disabled."""
return if_cheddar_enabled(
["@cheddar//:cheddar"] + extra,
)
16 changes: 16 additions & 0 deletions bazel/extensions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,19 @@ def _llvm_deps_impl(_):
llvm_deps = module_extension(
implementation = _llvm_deps_impl,
)

# CHEDDAR GPU FHE library
CHEDDAR_COMMIT = "307b49cbe03e7f8f14bf31485f716c1090c9ec9d"

def _cheddar_deps_impl(_):
maybe(
new_git_repository,
name = "cheddar",
build_file = "@heir//bazel/cheddar:cheddar.BUILD",
commit = CHEDDAR_COMMIT,
remote = "https://github.com/scale-snu/cheddar-fhe.git",
patches = ["@heir//patches:cheddar.patch"],
patch_args = ["-p1"],
)

cheddar_deps = module_extension(implementation = _cheddar_deps_impl)
156 changes: 156 additions & 0 deletions lib/Dialect/Cheddar/IR/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Cheddar dialect implementation

load("@heir//lib/Dialect:dialect.bzl", "add_heir_dialect_library")
load("@llvm-project//mlir:tblgen.bzl", "td_library")
load("@rules_cc//cc:cc_library.bzl", "cc_library")

package(
default_applicable_licenses = ["@heir//:license"],
default_visibility = ["//visibility:public"],
)

cc_library(
name = "Dialect",
srcs = [
"CheddarDialect.cpp",
],
hdrs = [
"CheddarAttributes.h",
"CheddarDialect.h",
"CheddarOps.h",
"CheddarTypes.h",
],
deps = [
":CheddarAttributes",
":CheddarOps",
":CheddarTypes",
":attributes_inc_gen",
":dialect_inc_gen",
":ops_inc_gen",
":types_inc_gen",
"@heir//lib/Dialect:HEIRInterfaces",
"@llvm-project//llvm:Support",
"@llvm-project//mlir:IR",
"@llvm-project//mlir:InferTypeOpInterface",
],
)

cc_library(
name = "CheddarAttributes",
srcs = [
"CheddarAttributes.cpp",
],
hdrs = [
"CheddarAttributes.h",
"CheddarDialect.h",
],
deps = [
":attributes_inc_gen",
":dialect_inc_gen",
"@llvm-project//mlir:IR",
],
)

cc_library(
name = "CheddarTypes",
srcs = [
"CheddarTypes.cpp",
],
hdrs = [
"CheddarAttributes.h",
"CheddarDialect.h",
"CheddarTypes.h",
],
deps = [
":CheddarAttributes",
":attributes_inc_gen",
":dialect_inc_gen",
":types_inc_gen",
"@heir//lib/Dialect:HEIRInterfaces",
"@llvm-project//mlir:IR",
],
)

cc_library(
name = "CheddarOps",
srcs = [
"CheddarOps.cpp",
],
hdrs = [
"CheddarDialect.h",
"CheddarOps.h",
"CheddarTypes.h",
],
deps = [
":CheddarAttributes",
":CheddarTypes",
":dialect_inc_gen",
":ops_inc_gen",
":types_inc_gen",
"@heir//lib/Dialect:HEIRInterfaces",
"@heir//lib/Utils",
"@heir//lib/Utils:RotationUtils",
"@llvm-project//mlir:IR",
"@llvm-project//mlir:InferTypeOpInterface",
"@llvm-project//mlir:Support",
],
)

td_library(
name = "td_files",
srcs = [
"CheddarAttributes.td",
"CheddarDialect.td",
"CheddarOps.td",
"CheddarTypes.td",
],
# include from the heir-root to enable fully-qualified include-paths
includes = ["../../../.."],
deps = [
"@heir//lib/Dialect:td_files",
"@llvm-project//mlir:BuiltinDialectTdFiles",
"@llvm-project//mlir:InferTypeOpInterfaceTdFiles",
"@llvm-project//mlir:OpBaseTdFiles",
],
)

add_heir_dialect_library(
name = "dialect_inc_gen",
dialect = "Cheddar",
kind = "dialect",
td_file = "CheddarDialect.td",
deps = [
":td_files",
],
)

add_heir_dialect_library(
name = "attributes_inc_gen",
dialect = "Cheddar",
kind = "attribute",
td_file = "CheddarAttributes.td",
deps = [
":td_files",
],
)

add_heir_dialect_library(
name = "types_inc_gen",
dialect = "Cheddar",
kind = "type",
td_file = "CheddarTypes.td",
deps = [
":td_files",
],
)

add_heir_dialect_library(
name = "ops_inc_gen",
dialect = "Cheddar",
kind = "op",
td_file = "CheddarOps.td",
deps = [
":td_files",
"@heir//lib/Dialect:td_files",
],
)
7 changes: 7 additions & 0 deletions lib/Dialect/Cheddar/IR/CheddarAttributes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "lib/Dialect/Cheddar/IR/CheddarAttributes.h"

namespace mlir {
namespace heir {
namespace cheddar {} // namespace cheddar
} // namespace heir
} // namespace mlir
9 changes: 9 additions & 0 deletions lib/Dialect/Cheddar/IR/CheddarAttributes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef LIB_DIALECT_CHEDDAR_IR_CHEDDARATTRIBUTES_H_
#define LIB_DIALECT_CHEDDAR_IR_CHEDDARATTRIBUTES_H_

#include "lib/Dialect/Cheddar/IR/CheddarDialect.h"

#define GET_ATTRDEF_CLASSES
#include "lib/Dialect/Cheddar/IR/CheddarAttributes.h.inc"

#endif // LIB_DIALECT_CHEDDAR_IR_CHEDDARATTRIBUTES_H_
30 changes: 30 additions & 0 deletions lib/Dialect/Cheddar/IR/CheddarAttributes.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef LIB_DIALECT_CHEDDAR_IR_CHEDDARATTRIBUTES_TD_
#define LIB_DIALECT_CHEDDAR_IR_CHEDDARATTRIBUTES_TD_

include "CheddarDialect.td"

include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/DialectBase.td"

class Cheddar_Attribute<string attrName, string attrMnemonic>
: AttrDef<Cheddar_Dialect, attrName> {
let mnemonic = attrMnemonic;
let assemblyFormat = "`<` struct(params) `>`";
}

def Cheddar_ParameterFileAttr
: Cheddar_Attribute<"ParameterFile", "parameter_file"> {
let summary = "Path to a CHEDDAR parameter JSON file";
let description = [{
This attribute holds the path to a CHEDDAR parameter JSON file.

CHEDDAR parameters are loaded from pre-built JSON files that specify
ring dimension, prime chains, scale, and other CKKS parameters.
}];
let parameters = (ins
StringRefParameter<"path to JSON parameter file">:$path,
DefaultValuedParameter<"bool", "false", "use 64-bit word type">:$use64Bit
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field appears to be unused. (In fact, this entire attribute appears to be unused)

);
}

#endif // LIB_DIALECT_CHEDDAR_IR_CHEDDARATTRIBUTES_TD_
Loading