Skip to content
Merged
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
41 changes: 41 additions & 0 deletions brilir/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
cmake_minimum_required(VERSION 3.20.0)
project(brilir LANGUAGES C CXX)

set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON)

set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to")

set(EXTERNAL_PROJECT_BUILD FALSE)
find_package(MLIR REQUIRED CONFIG)

# Define the default argument to use by `lit` when testing.
set(LLVM_LIT_ARGS "-sv" CACHE STRING "Default options for lit")

message(STATUS "Using MLIRConfig.cmake in: ${MLIR_DIR}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/bin)
set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/lib)
set(MLIR_BINARY_DIR ${CMAKE_BINARY_DIR})

list(APPEND CMAKE_MODULE_PATH "${MLIR_CMAKE_DIR}")
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")

include(TableGen)
include(AddLLVM)
include(AddMLIR)
include(HandleLLVMOptions)

include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${MLIR_INCLUDE_DIRS})
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${PROJECT_BINARY_DIR}/include)
link_directories(${LLVM_BUILD_LIBRARY_DIR})
add_definitions(${LLVM_DEFINITIONS})

add_subdirectory(include)
add_subdirectory(lib)

add_subdirectory(bril-opt)
add_subdirectory(bril2mlir)
add_subdirectory(mlir2bril)
67 changes: 67 additions & 0 deletions brilir/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# An out-of-tree MLIR dialect for Bril

This repo contains an out-of-tree [MLIR](https://mlir.llvm.org/) dialect for [Bril](https://capra.cs.cornell.edu/bril/intro.html), a standalone `opt`-like tool to operate on Bril dialect, and conversion tools for translating between Bril and MLIR (`bril2mlir` and `mlir2bril`).

## Building

The first step is to obtain and build MLIR itself.
Ensure you have all the required dependencies listed [in the MLIR documentation](https://mlir.llvm.org/getting_started/).
Then do something like this:

Use something like this to obtain and build the MLIR dependency:

```sh
git clone https://github.com/llvm/llvm-project.git
cd llvm-project
mkdir build
cd build
cmake -G Ninja ../llvm \
-DLLVM_ENABLE_PROJECTS=mlir \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_ASSERTIONS=ON
ninja
```

You may need to change some of the LLVM build options depending on the setup you want.
For example, use `-DLLVM_CCACHE_BUILD=ON` to enable [Ccache](https://ccache.dev) to speed up the build.
This project was most recently tested against commit `598657158b5cb42c07bee949f193d3c8d79ce20f` of the LLVM monorepo.

To build this Bril dialect, you'll need the [nlohmann-json](https://github.com/nlohmann/json) library.
Using [Homebrew](https://brew.sh), for instance, you can type `brew install nlohmann-json`.

To build `brilir` (ensure `BUILD_DIR` matches the paths used in the previous step):

```sh
export BUILD_DIR=$HOME/path/to/llvm-project/build
mkdir build
cd build
cmake -G Ninja .. \
-DMLIR_DIR=$BUILD_DIR/lib/cmake/mlir
ninja
```

This will build three executables: `bril2mlir`, `mlir2bril`, and `bril-opt`.

## Example Usage

`bril2mlir` expects the Bril source to be in SSA form, which can be prepared as follows (using the [example implementations](https://github.com/sampsyo/bril/tree/main/examples) from the Bril repo):

```sh
bril2json < source.bril | python ~/path/to/bril/examples/to_ssa.py | python ~/path/to/bril/examples/tdce.py tdce+
```

For Bril to MLIR conversion:

```sh
bril2mlir < bril_input.json 2>&1 | mlir2bril | bril2txt
```

For lowering to LLVM IR and subsequent linking:

```sh
bril2mlir < bril_input.json 2>&1 | bril-opt --pass-pipeline="builtin.module(convert-bril-to-std,rename-main-function,convert-arith-to-llvm,convert-func-to-llvm,convert-cf-to-llvm,canonicalize,cse)" - | mlir-translate --mlir-to-llvmir - -o output.ll
# The Bril entry point is exposed as `bril_main` and can be linked against.
clang++ output.ll main.cpp
```

All the built tools are located in `build/bin` directory.
13 changes: 13 additions & 0 deletions brilir/bril-opt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
set(LIBS
MLIRArithDialect
MLIROptLib
MLIRRegisterAllDialects
MLIRRegisterAllPasses
MLIRBril
)
add_llvm_executable(bril-opt bril-opt.cpp)

llvm_update_compile_flags(bril-opt)
target_link_libraries(bril-opt PRIVATE ${LIBS})

mlir_check_all_link_libraries(bril-opt)
35 changes: 35 additions & 0 deletions brilir/bril-opt/bril-opt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===- bril-opt.cpp ---------------------------------------*- C++ -*-===//
//
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/InitAllDialects.h"
#include "mlir/InitAllPasses.h"
#include "mlir/Support/FileUtilities.h"
#include "mlir/Tools/mlir-opt/MlirOptMain.h"

#include "bril/BrilDialect.h"
#include "bril/BrilPasses.h"

int main(int argc, char **argv) {
mlir::registerAllPasses();
mlir::bril::registerPasses();

mlir::DialectRegistry registry;
registry.insert<mlir::bril::BrilDialect, mlir::arith::ArithDialect,
mlir::func::FuncDialect, mlir::memref::MemRefDialect>();
// Add the following to include *all* MLIR Core dialects, or selectively
// include what you need like above. You only need to register dialects that
// will be *parsed* by the tool, not the one generated
registerAllDialects(registry);

return mlir::asMainReturnCode(
mlir::MlirOptMain(argc, argv, "Bril optimizer driver\n", registry));
}
12 changes: 12 additions & 0 deletions brilir/bril2mlir/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
find_package(nlohmann_json 3.12.0 REQUIRED)

set(LIBS
MLIRBril
nlohmann_json::nlohmann_json
)
add_llvm_executable(bril2mlir bril2mlir.cpp)

llvm_update_compile_flags(bril2mlir)
target_link_libraries(bril2mlir PRIVATE ${LIBS})

mlir_check_all_link_libraries(bril2mlir)
37 changes: 37 additions & 0 deletions brilir/bril2mlir/bril2mlir.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "bril/BrilDialect.h"
#include "bril/MLIRGen.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/MLIRContext.h"
#include "llvm/Support/raw_ostream.h"
#include <llvm/Support/ErrorOr.h>
#include <llvm/Support/MemoryBuffer.h>
#include <nlohmann/json.hpp>
#include <system_error>

int main() {
mlir::MLIRContext context;

context.getOrLoadDialect<mlir::bril::BrilDialect>();

llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =
llvm::MemoryBuffer::getSTDIN();
if (std::error_code ec = fileOrErr.getError()) {
llvm::errs() << "Error reading from stdin: " << ec.message() << "\n";
return 1;
}

auto buffer = fileOrErr->get()->getBuffer();

nlohmann::json brilJson = nlohmann::json::parse(buffer);

auto module = bril::mlirGen(context, brilJson);

if (!module) {
llvm::errs() << "Failed to generate MLIR module\n";
return 1;
}

module->dump();

return 0;
}
1 change: 1 addition & 0 deletions brilir/include/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_subdirectory(bril)
17 changes: 17 additions & 0 deletions brilir/include/bril/BrilDialect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//===- BrilDialect.h - Bril dialect -----------------*- C++ -*-===//
//
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef BRIL_BRILDIALECT_H
#define BRIL_BRILDIALECT_H

#include "mlir/Bytecode/BytecodeOpInterface.h"
#include "mlir/IR/Dialect.h"

#include "bril/BrilOpsDialect.h.inc"

#endif // BRIL_BRILDIALECT_H
39 changes: 39 additions & 0 deletions brilir/include/bril/BrilDialect.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//===- BrilDialect.td - Bril dialect -----------*- tablegen -*-===//
//
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef BRIL_DIALECT
#define BRIL_DIALECT

include "mlir/IR/OpBase.td"

//===----------------------------------------------------------------------===//
// Bril dialect definition.
//===----------------------------------------------------------------------===//

def Bril_Dialect : Dialect {
let name = "bril";
let summary = "An MLIR dialect for Bril.";
let description = [{
This dialect is an example of an out-of-tree MLIR dialect designed to
illustrate the basic setup required to develop MLIR-based tools without
working inside of the LLVM source tree.
}];
let cppNamespace = "::mlir::bril";
let useDefaultTypePrinterParser = 1;
let extraClassDeclaration = [{
void registerTypes();
}];
}

//===----------------------------------------------------------------------===//
// Base bril operation definition.
//===----------------------------------------------------------------------===//

class Bril_Op<string mnemonic, list<Trait> traits = []> :
Op<Bril_Dialect, mnemonic, traits>;
#endif // BRIL_DIALECT
26 changes: 26 additions & 0 deletions brilir/include/bril/BrilOps.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===- BrilOps.h - Bril dialect ops -----------------*- C++ -*-===//
//
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef BRIL_BRILOPS_H
#define BRIL_BRILOPS_H

#include "bril/BrilDialect.h"
#include "bril/BrilTypes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/Interfaces/CallInterfaces.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"
#include "mlir/Interfaces/FunctionInterfaces.h"
#include "mlir/Interfaces/InferTypeOpInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"

#define GET_OP_CLASSES
#include "bril/BrilOps.h.inc"

#endif // BRIL_BRILOPS_H
Loading
Loading