diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000000..9b3aa8b7213 --- /dev/null +++ b/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: LLVM diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..0385e34309a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true diff --git a/.github/buildAndTest.yml b/.github/workflows/buildAndTest.yml similarity index 100% rename from .github/buildAndTest.yml rename to .github/workflows/buildAndTest.yml diff --git a/.gitignore b/.gitignore index 259148fa18f..6838d7f9651 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,9 @@ *.exe *.out *.app + +# CMake +build/ + +# Editor +.vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000000..94e7a76467e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,68 @@ +cmake_minimum_required(VERSION 3.10) + +# Policies requried by LLVM. +if(POLICY CMP0068) + cmake_policy(SET CMP0068 NEW) + set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON) +endif() + +if(POLICY CMP0075) + cmake_policy(SET CMP0075 NEW) +endif() + +if(POLICY CMP0077) + cmake_policy(SET CMP0077 NEW) +endif() + +project(phism LANGUAGES CXX C) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED YES) + +set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/cmake") + +find_package(MLIR REQUIRED CONFIG) + +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}") + +# Define the default arguments to use with 'lit', and an option for the user to +# override. +set(LIT_ARGS_DEFAULT "-sv") +if (MSVC_IDE OR XCODE) + set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") +endif() +set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") + +# ------------------------------------------------- Dependencies + +# ------------------------------------------------- This project +set(PHISM_MAIN_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" ) # --src-root +set(PHISM_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/include" ) # --includedir + +set(PHISM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +set(PHISM_BINARY_DIR "${CMAKE_BINARY_DIR}/bin") +set(PHISM_TOOLS_DIR "${CMAKE_BINARY_DIR}/bin") + +list(APPEND CMAKE_MODULE_PATH "${MLIR_CMAKE_DIR}") +list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") + +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") + +# add_subdirectory(include/polymer) +# add_subdirectory(lib) +add_subdirectory(tools) +add_subdirectory(test) diff --git a/README.md b/README.md index 8a2c48affed..ca756ccf95e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,91 @@ # Phism: Polyhedral High-Level Synthesis in MLIR +![Build and Test](https://github.com/kumasento/phism/workflows/Build%20and%20Test/badge.svg) +## Setup + +Install prerequisites for [MLIR/LLVM](https://mlir.llvm.org/getting_started/) and [Pluto](https://github.com/kumasento/pluto/blob/master/README.md). + +Specifically, you need: + +* (LLVM) `cmake` >= 3.13.4. +* (LLVM) Valid compiler tool-chain that supports C++ 14 +* (Pluto) Automatic build tools (for Pluto), including `autoconf`, `automake`, and `libtool`. +* (Pluto) Pre-built LLVM-9 tools (`clang-9` and `FileCheck-9`) and their header files are needed. +* (Pluto) `libgmp` that is required by isl. +* (Pluto) `flex` and `bison` for `clan` that Pluto depends on. +* (Pluto) `texinfo` used to generate some docs. + +Here is a one-liner on Ubuntu 20.04: + +```shell +sudo apt-get install -y build-essential libtool autoconf pkg-config flex bison libgmp-dev clang-9 libclang-9-dev texinfo +``` + +On Ubuntu you may need to specify the default versions of these tools: + +```shell +sudo update-alternatives --install /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-9 100 +sudo update-alternatives --install /usr/bin/FileCheck FileCheck /usr/bin/FileCheck-9 100 +sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-9 100 +sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-9 100 +``` + +## Install + +Download this repository: + +```shell +git clone https://github.com/kumasento/phism +``` + +Update the submodules: + +```shell +git submodule update +``` + +### LLVM + +To install LLVM: + +```shell +# At the top-level directory +mkdir llvm/build +cd llvm/build +cmake ../llvm \ + -DLLVM_ENABLE_PROJECTS="llvm;clang;mlir" \ + -DLLVM_TARGETS_TO_BUILD="host" \ + -DLLVM_ENABLE_ASSERTIONS=ON \ + -DCMAKE_BUILD_TYPE=DEBUG \ + -DLLVM_INSTALL_UTILS=ON \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ \ + -G Ninja +cmake --build . -- -j$(nproc) +cmake --build . --target check-mlir +``` + +### Polymer + +TBA + +### This project + +```shell +# At the top-level directory +mkdir build +cd build +cmake .. \ + -DCMAKE_BUILD_TYPE=DEBUG \ + -DMLIR_DIR=$PWD/../llvm/build/lib/cmake/mlir \ + -DLLVM_DIR=$PWD/../llvm/build/lib/cmake/llvm \ + -DLLVM_ENABLE_ASSERTIONS=ON \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DLLVM_EXTERNAL_LIT=${PWD}/../llvm/build/bin/llvm-lit \ +cmake --build . + +# Unit tests +cmake --build . --target check-phism +``` diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000000..e3947ca7f48 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,21 @@ +configure_lit_site_cfg( + "${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in" + "${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py" + MAIN_CONFIG + "${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py" + ) + +set(PHISM_TEST_DEPENDS + FileCheck count not + phism-opt + ) + +add_lit_testsuite(check-phism "Running the Phism regression tests" + ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${PHISM_TEST_DEPENDS} + ) +set_target_properties(check-phism PROPERTIES FOLDER "Tests") + +add_lit_testsuites(PHISM ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${PHISM_TEST_DEPS} +) diff --git a/test/lit.cfg.py b/test/lit.cfg.py new file mode 100644 index 00000000000..c57d78da08c --- /dev/null +++ b/test/lit.cfg.py @@ -0,0 +1,52 @@ +# -*- Python -*- + +# Configuration file for the 'lit' test runner. + +import os +import lit.formats + +from lit.llvm import llvm_config + +# Configuration file for the 'lit' test runner. + +# name: The name of this test suite. +config.name = 'phism' + +# testFormat: The test format to use to interpret tests. +config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) + +# suffixes: A list of file extensions to treat as test files. This is overriden +# by individual lit.local.cfg files in the test subdirectories. +config.suffixes = ['.mlir', '.scop'] + +# excludes: A list of directories or files to exclude from the testsuite even +# if they match the suffixes pattern. +config.excludes = [] + +# test_source_root: The root path where tests are located. +config.test_source_root = os.path.dirname(__file__) + +# test_exec_root: The root path where tests should be run. +config.test_exec_root = os.path.join(config.phism_obj_root, 'test') + +# Tweak the PATH to include the tools dir. +llvm_config.with_environment('PATH', config.llvm_tools_dir, append_path=True) + +# Propagate some variables from the host environment. +llvm_config.with_system_environment( + ['HOME', 'INCLUDE', 'LIB', 'TMP', 'TEMP']) + + +llvm_config.use_default_substitutions() + +# For each occurrence of a tool name, replace it with the full path to +# the build directory holding that tool. We explicitly specify the directories +# to search to ensure that we get the tools just built and not some random +# tools that might happen to be in the user's PATH. + +tool_dirs = [config.phism_tools_dir, config.llvm_tools_dir] +tools = [ + 'phism-opt', + # 'phism-translate' +] +llvm_config.add_tool_substitutions(tools, tool_dirs) diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in new file mode 100644 index 00000000000..a73f0ab938c --- /dev/null +++ b/test/lit.site.cfg.py.in @@ -0,0 +1,22 @@ +@LIT_SITE_CFG_IN_HEADER@ + +config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" +config.phism_obj_root = "@PHISM_BINARY_DIR@" +config.phism_tools_dir = "@PHISM_TOOLS_DIR@" +config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" +config.target_triple = "@TARGET_TRIPLE@" + +# Support substitution of the tools and build_mode with user parameters. +# This is used when we can't determine the tool dir at configuration time. +try: + config.llvm_tools_dir = config.llvm_tools_dir % lit_config.params + config.phism_tools_dir = config.phism_tools_dir % lit_config.params +except KeyError as e: + key, = e.args + lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key)) + +import lit.llvm +lit.llvm.initialize(lit_config, config) + +# Let the main config do the real work. +lit_config.load_config(config, "@PHISM_SOURCE_DIR@/test/lit.cfg.py") diff --git a/test/phism-opt/mem2ptr/test-mem2ptr.mlir b/test/phism-opt/mem2ptr/test-mem2ptr.mlir new file mode 100644 index 00000000000..1665e5be302 --- /dev/null +++ b/test/phism-opt/mem2ptr/test-mem2ptr.mlir @@ -0,0 +1,5 @@ +// RUN: phism-opt %s + +func @foo(%A: memref) { + return +} diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 00000000000..62ba326285e --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,4 @@ +# otherwise those tools added by add_llvm_tool won't be installed. +set(LLVM_BUILD_TOOLS ON) + +add_subdirectory(phism-opt) diff --git a/tools/phism-opt/CMakeLists.txt b/tools/phism-opt/CMakeLists.txt new file mode 100644 index 00000000000..22693ad1c71 --- /dev/null +++ b/tools/phism-opt/CMakeLists.txt @@ -0,0 +1,23 @@ +set(LLVM_LINK_COMPONENTS + Support +) + +add_llvm_tool(phism-opt + phism-opt.cc +) +llvm_update_compile_flags(phism-opt) +target_link_libraries(phism-opt + PRIVATE + MLIRStandard + MLIRLoopAnalysis + MLIRAnalysis + MLIRDialect + MLIREDSC + MLIROptLib + MLIRParser + MLIRPass + MLIRTransforms + MLIRTransformUtils + MLIRSupport + MLIRIR + ) diff --git a/tools/phism-opt/phism-opt.cc b/tools/phism-opt/phism-opt.cc new file mode 100644 index 00000000000..e40263a5a0e --- /dev/null +++ b/tools/phism-opt/phism-opt.cc @@ -0,0 +1,110 @@ +//===- phism-opt.cc - The phism optimisation tool -----------*- C++ -*-===// +// +// This file implements the phism optimisation tool, which is the phism +// analog of mlir-opt, used to drive compiler passes, e.g. for testing. +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/Affine/IR/AffineOps.h" +#include "mlir/Dialect/StandardOps/IR/Ops.h" +#include "mlir/IR/AsmState.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" +#include "mlir/Pass/PassRegistry.h" +#include "mlir/Support/FileUtilities.h" +#include "mlir/Support/MlirOptMain.h" +#include "mlir/Transforms/Passes.h" + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/ToolOutputFile.h" + +using namespace llvm; +using namespace mlir; + +static cl::opt inputFilename(cl::Positional, + cl::desc(""), + cl::init("-")); + +static cl::opt outputFilename("o", cl::desc("Output filename"), + cl::value_desc("filename"), + cl::init("-")); + +static cl::opt splitInputFile( + "split-input-file", + cl::desc("Split the input file into pieces and process each " + "chunk independently"), + cl::init(false)); + +static cl::opt verifyDiagnostics( + "verify-diagnostics", + cl::desc("Check that emitted diagnostics match " + "expected-* lines on the corresponding line"), + cl::init(false)); + +static cl::opt verifyPasses( + "verify-each", cl::desc("Run the verifier after each transformation pass"), + cl::init(true)); + +static cl::opt showDialects( + "show-dialects", cl::desc("Print the list of registered dialects"), + cl::init(false)); + +static cl::opt allowUnregisteredDialects( + "allow-unregistered-dialect", + cl::desc("Allow operation with no registered dialects"), cl::init(false)); + +int main(int argc, char *argv[]) { + InitLLVM y(argc, argv); + + DialectRegistry registry; + + // Register MLIR stuff + registry.insert(); + registry.insert(); + +// Register the standard passes we want. +#include "mlir/Transforms/Passes.h.inc" + registerCanonicalizerPass(); + registerCSEPass(); + registerInlinerPass(); + // Register phism specific passes. + + // Register any pass manager command line options. + registerMLIRContextCLOptions(); + registerPassManagerCLOptions(); + + // Register printer command line options. + registerAsmPrinterCLOptions(); + + PassPipelineCLParser passPipeline("", "Compiler passes to run"); + + // Parse pass names in main to ensure static initialization completed. + cl::ParseCommandLineOptions(argc, argv, "circt modular optimizer driver\n"); + + if (showDialects) { + llvm::outs() << "Registered Dialects:\n"; + for (const auto &nameAndRegistrationIt : registry) { + llvm::outs() << nameAndRegistrationIt.first << "\n"; + } + return 0; + } + + // Set up the input file. + std::string errorMessage; + auto file = openInputFile(inputFilename, &errorMessage); + if (!file) { + llvm::errs() << errorMessage << "\n"; + return 1; + } + + auto output = openOutputFile(outputFilename, &errorMessage); + if (!output) { + llvm::errs() << errorMessage << "\n"; + exit(1); + } + + return failed(MlirOptMain(output->os(), std::move(file), passPipeline, + registry, splitInputFile, verifyDiagnostics, + verifyPasses, allowUnregisteredDialects)); +}