Library / SDK
Tiramisu-Compiler/tiramisu avatar
Tiramisu-Compiler/tiramisu

Tiramisu: A Polyhedral Compiler With a C++ Scheduling API

A polyhedral compiler for expressing fast and portable data parallel algorithms

961 stars138 forksC++MIT

At a glance

What is it?
Tiramisu lets you declare loop nests and schedule them separately, then emit code for x86, CUDA, MPI or Vivado HLS. The idea is sound and the build is heavy: the last tagged release is V0.2 from July 2018.
Who is it for?
Adopt Tiramisu if you are writing a tensor or stencil kernel generator and you want the loop schedule expressed as C++ calls rather than as a tuning language, and if you can afford a build that pulls in ISL, LLVM and Halide. Do not adopt it if you need tagged releases newer than V0.2, a stable binary package, or a backend outside x86, CUDA, MPI and Vivado HLS.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 56 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The Problem Tiramisu Targets: Separating What a Loop Computes From How It Runs

In a hand-written kernel, the algorithm and the schedule are the same text. If you want to tile a loop nest, vectorize the inner dimension and run the outer dimension across cores, you edit the loop body and hope the compiler's own optimizer does not undo your work. Tiramisu takes the other route. The README describes it as a compiler that provides "a simple C++ API for expressing algorithms (Tiramisu expressions) and how these algorithms should be optimized by the compiler." Two separate objects: a computation, and a list of transformations applied to it. The audience is narrow and identifiable. It is for people building kernel generators for tensor algebra, deep learning operators, image processing pipelines, stencil codes and linear algebra, who need one source description to reach several targets. The repository topics list code-generation, tensor-algebra and deep-neural-networks, which matches that audience. It is not a general-purpose compiler you point at an existing C file. You write against the API.

Computations, Buffers and Schedule Calls: The Actual Mechanism

The README example is the clearest description of the data flow. You call tiramisu::init("foo") to name the function to be generated. You declare iteration variables with bounds, here var i("i", 0, 100) and var j("j", 0, 100). You declare a computation over those variables: computation C({i,j}, 0), which the README says is equivalent to a nested loop writing zero into C(i,j). Then the schedule: C.parallelize(i) and C.vectorize(j, 4). Then storage: buffer b_C("b_C", {100, 100}, p_int32, a_output) and C.store_in(&b_C). Finally C.codegen({&b_C}, "generated_code.o") emits the object file. The transformations are method calls on the computation object, not pragmas or a separate schedule file. The compiler is "based on the polyhedral model," per the README, which is what allows it to express "a large set of loop optimizations and data layout transformations" while keeping the algorithm text unchanged. The targets listed are multicore x86 CPUs, Nvidia GPUs, Xilinx FPGAs through Vivado HLS, and distributed machines through MPI. The README also states the design intent: "It is designed to enable easy integration of code generators for new architectures." That is the architectural claim to weigh, because the four shipped backends are the evidence for it.

Three Build Paths, and Why the Third One Is the Honest One

The README gives three ways in. The shortest is spack: spack install tiramisu, which builds everything from source. The second installs dependencies through Homebrew or apt and then configures with CMake. On Ubuntu that means fetching llvm.sh, running sudo ./llvm.sh 14 all, then installing liblld-14-dev, llvm-14-runtime, libllvm14, llvm-14-dev, llvm14-*, halide and libisl-dev. On macOS it means brew install cmake, llvm@14, halide and isl, followed by brew link halide and brew link isl. You then locate ISL with dpkg -L libisl-dev or brew info isl and pass the paths to CMake: cmake . -B build -DISL_LIB_DIRECTORY=$ISL_LIB_DIRECTORY -DISL_INCLUDE_DIRECTORY=$ISL_INCLUDE_DIRECTORY -DPython3_EXECUTABLE=`which python3`, then cmake --build build. The third path clones the repository and runs ./utils/scripts/install_submodules.sh with an absolute TIRAMISU_ROOT_DIR, which fetches and builds ISL, LLVM and Halide. The README warns this "may take between few minutes to few hours (downloading and compiling LLVM is time consuming)." It also requires exporting Halide's build directory onto CMAKE_PREFIX_PATH before configuring. Required prerequisites are CMake 3.22 or greater, Autoconf, libtool and Ninja. OpenMPI, CUDA and Python 3.8+ are optional and gate the MPI backend, the GPU backend and the Python bindings respectively. If you want the third path to be reproducible, the submodule script is the part to pin, because it decides which LLVM and Halide you end up compiling against.

configure.cmake Is Where the Backends Are Actually Decided

The build is not configured by flags on the command line alone. The README points at configure.cmake in the repository root and says a description of each variable is in comments inside that file. Three switches matter. USE_GPU set to TRUE enables the GPU backend, and if CUDA is not found automatically the build prompts for the CUDA library path. USE_MPI set to TRUE enables the distributed backend, and if MPI is not found you set MPI_INCLUDE_DIR, MPI_LIB_DIR and MPI_LIB_FLAGS yourself. USE_AUTO_SCHEDULER set to TRUE builds the autoscheduler module. The README notes that editing configure.cmake is "Needed only if you want to generate MPI or GPU code, run the BLAS benchmarks, or if you want to build the autoscheduler module." That sentence is worth reading twice, because it tells you the default build is a CPU-only compiler plus whatever the autoscheduler adds. If your evaluation of Tiramisu depends on the CUDA or MPI path, you are not testing the default configuration. Installing the Python bindings adds two more variables: Tiramisu_INSTALL_PYTHONDIR to place the package, and CMAKE_INSTALL_PREFIX for the install root, after which you have to extend PYTHONPATH and LD_LIBRARY_PATH. CMake 3.22 is a hard floor, and the README's tested platforms are Ubuntu 18.04 and macOS 13.0.1, which is a dated pair.

The Release Cadence Is the First Thing to Check Before Adopting

The two tagged releases are V0.1 from 17 July 2018 and V0.2 from 26 July 2018, nine days apart. There is nothing tagged since. The repository is not archived and the last push is recent, so development has continued, but anyone who depends on versioned artifacts is depending on a snapshot rather than a release. That has a direct consequence for the spack path: spack install tiramisu resolves through a package recipe, and the recipe's pinned revision is what you get, not the head of master. The same applies to the submodule script, which pulls ISL, LLVM and Halide at whatever revision the script specifies. Practically, this means your build is reproducible only as long as those pins hold, and upgrading means moving all of them together. There is no mention in the README of a stable ABI, a deprecation policy, or a compatibility statement across versions. Treat the C++ API as moving. If you need a compiler whose interface you can freeze for years, this is a cost you should price before writing kernels against it.

Where Tiramisu Is the Wrong Tool

The clearest failure mode is the one the README implies rather than states: Tiramisu compiles Tiramisu expressions, not arbitrary C++. If you already have a loop nest in C or Fortran that you want retargeted, there is no path described here for ingesting it. You rewrite it against the API. The second limitation is backend coverage. The listed targets are multicore x86, Nvidia GPUs, Xilinx FPGAs via Vivado HLS, and MPI. There is no ARM, no AMD GPU, no WebAssembly, no RISC-V backend in the material. The README frames extensibility as a design goal, so adding one is theoretically the intended workflow, but that is compiler engineering, not configuration. The third limitation is the FPGA path specifically: it goes through Vivado HLS, which is a Xilinx tool with its own licensing and its own synthesis constraints, so "Xilinx FPGA support" here means "emits HLS C++," not "closes timing." The fourth is the build itself. A toolchain that compiles LLVM from source, needs Halide linked in, and pins ISL is not something you drop into a CI image casually. If your use case is a single fixed target and a single fixed schedule, writing the kernel directly is less work and less risk. Tiramisu pays off when the same computation must reach several targets, or when the schedule has to be searched rather than chosen.

The Halide Comparison, and What the Overlap Actually Means

Halide is the obvious reference point, and the README makes the relationship concrete rather than rhetorical: Halide is a required dependency, installed via brew install halide or apt-get install halide, and its CMake directory must be on CMAKE_PREFIX_PATH for the submodule build. Halide also separates algorithm from schedule, and it also targets CPU and GPU. The difference in approach is the scheduling surface. Halide expresses schedules through a domain-specific language embedded in C++, with a defined set of scheduling primitives. Tiramisu exposes the schedule as ordinary method calls on computation objects, parallelize, vectorize, store_in, inside a C++ program you compile normally, and it derives the transformations from the polyhedral model, which the README credits for the breadth of loop optimizations and data layout transformations it can express. The other difference is target reach: Tiramisu adds MPI and Vivado HLS to the list, which Halide does not cover in this material. If your problem is a two-target image pipeline, Halide is the more established choice and Tiramisu's extra backends buy you nothing. If you need the same kernel on a cluster and on an FPGA, the overlap with Halide is not the deciding factor.

Licence and the Cost of Living With a Compiler You Build Yourself

Tiramisu is MIT licensed, per the badge and the LICENSE file linked in the README. MIT is permissive: it allows modification and redistribution with the copyright notice and permission notice retained, and it carries no copyleft obligation on your own code. That is the licence of Tiramisu itself. It is not the licence of what Tiramisu links against, and the README names LLVM, Halide, ISL, OpenMPI and the CUDA Toolkit as dependencies. Those carry their own terms, and the CUDA Toolkit and Vivado HLS in particular are not open source. If you ship a product built on the GPU or FPGA path, the terms that matter are those of the vendor toolchain, not Tiramisu's MIT grant. This is a factual observation about which licences are in play, not legal advice; check the actual terms with your own counsel. On maintenance: because the tagged releases stop at V0.2, your upgrade unit is a commit plus a set of submodule revisions for ISL, LLVM and Halide. Budget for rebuild time accordingly, since the README itself warns the submodule step can run into hours. The upside of the same design is that a pinned checkout is a complete, self-contained toolchain, which is easier to archive than a package that resolves dependencies at install time.

Editorial conclusion

Adopt Tiramisu if you are writing a tensor or stencil kernel generator and you want the loop schedule expressed as C++ calls rather than as a tuning language, and if you can afford a build that pulls in ISL, LLVM and Halide. Do not adopt it if you need tagged releases newer than V0.2, a stable binary package, or a backend outside x86, CUDA, MPI and Vivado HLS. Before committing, clone the repository, run ./utils/scripts/install_submodules.sh with an absolute path, set USE_GPU and USE_MPI in configure.cmake to match your hardware, and confirm that the generated object file for a single computation matches what you would have written by hand.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. Tiramisu-Compiler/tiramisu on GitHub
Community notes

Community notes