diff --git a/clang/include/clang/CIR/Passes.h b/clang/include/clang/CIR/Passes.h new file mode 100644 index 0000000000000..1d202ce5bfb52 --- /dev/null +++ b/clang/include/clang/CIR/Passes.h @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, 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 +// +//===----------------------------------------------------------------------===// +// +// This file exposes the entry points to create compiler passes for ClangIR. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CIR_PASSES_H +#define CLANG_CIR_PASSES_H + +#include "mlir/Pass/Pass.h" + +#include + +namespace cir { +namespace direct { +/// Create a pass that fully lowers CIR to the LLVMIR dialect. +std::unique_ptr createConvertCIRToLLVMPass(); + +/// Adds passes that fully lower CIR to the LLVMIR dialect. +void populateCIRToLLVMPasses(mlir::OpPassManager &pm); + +} // namespace direct +} // end namespace cir + +#endif // CLANG_CIR_PASSES_H diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 235b5a057852a..ba7fab2865116 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -27,6 +27,7 @@ #include "clang/CIR/Dialect/IR/CIRAttrVisitor.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/MissingFeatures.h" +#include "clang/CIR/Passes.h" #include "llvm/IR/Module.h" #include "llvm/Support/TimeProfiler.h" @@ -304,11 +305,11 @@ void ConvertCIRToLLVMPass::runOnOperation() { signalPassFailure(); } -static std::unique_ptr createConvertCIRToLLVMPass() { +std::unique_ptr createConvertCIRToLLVMPass() { return std::make_unique(); } -static void populateCIRToLLVMPasses(mlir::OpPassManager &pm) { +void populateCIRToLLVMPasses(mlir::OpPassManager &pm) { pm.addPass(createConvertCIRToLLVMPass()); } diff --git a/clang/test/CIR/IR/func.cir b/clang/test/CIR/IR/func.cir new file mode 100644 index 0000000000000..a32c3e697ed25 --- /dev/null +++ b/clang/test/CIR/IR/func.cir @@ -0,0 +1,85 @@ +// RUN: cir-opt %s | FileCheck %s + +module { +// void empty() { } +cir.func @empty() -> !cir.void { + cir.return +} +// CHECK: cir.func @empty() -> !cir.void { +// CHECK: cir.return +// CHECK: } + +// void voidret() { return; } +cir.func @voidret() -> !cir.void { + cir.return +} +// CHECK: cir.func @voidret() -> !cir.void { +// CHECK: cir.return +// CHECK: } + +// int intfunc() { return 42; } +cir.func @intfunc() -> !cir.int { + %0 = cir.const #cir.int<42> : !cir.int + cir.return %0 : !cir.int +} +// CHECK: cir.func @intfunc() -> !cir.int { +// CHECK: %[[VAL:.*]] = cir.const #cir.int<42> : !cir.int +// CHECK: cir.return %[[VAL]] : !cir.int +// CHECK: } + +// int scopes() { +// { +// { +// return 99; +// } +// } +//} +cir.func @scopes() -> !cir.int { + cir.scope { + cir.scope { + %0 = cir.const #cir.int<99> : !cir.int + cir.return %0 : !cir.int + } + } + cir.trap +} +// CHECK: cir.func @scopes() -> !cir.int { +// CHECK: cir.scope { +// CHECK: cir.scope { +// CHECK: %[[VAL:.*]] = cir.const #cir.int<99> : !cir.int +// CHECK: cir.return %[[VAL]] : !cir.int +// CHECK: } +// CHECK: } +// CHECK: cir.trap +// CHECK: } + +// long longfunc() { return 42l; } +cir.func @longfunc() -> !cir.int { + %0 = cir.const #cir.int<42> : !cir.int + cir.return %0 : !cir.int +} +// CHECK: cir.func @longfunc() -> !cir.int +// CHECK: %0 = cir.const #cir.int<42> : !cir.int +// CHECK: cir.return %0 : !cir.int +// CHECK: } + +// unsigned unsignedfunc() { return 42u; } +cir.func @unsignedfunc() -> !cir.int { + %0 = cir.const #cir.int<42> : !cir.int + cir.return %0 : !cir.int +} +// CHECK: cir.func @unsignedfunc() -> !cir.int +// CHECK: %[[VAL:.*]] = cir.const #cir.int<42> : !cir.int +// CHECK: cir.return %[[VAL]] : !cir.int +// CHECK: } + +// unsigned long long ullfunc() { return 42ull; } +cir.func @ullfunc() -> !cir.int { + %0 = cir.const #cir.int<42> : !cir.int + cir.return %0 : !cir.int +} +// CHECK: cir.func @ullfunc() -> !cir.int +// CHECK: %[[VAL:.*]] = cir.const #cir.int<42> : !cir.int +// CHECK: cir.return %[[VAL:.*]] : !cir.int +// CHECK: } +} diff --git a/clang/test/CIR/IR/global.cir b/clang/test/CIR/IR/global.cir new file mode 100644 index 0000000000000..6c68ab0a501ff --- /dev/null +++ b/clang/test/CIR/IR/global.cir @@ -0,0 +1,69 @@ +// RUN: cir-opt %s -o - | FileCheck %s + +module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { + cir.global @c : !cir.int + cir.global @sc : !cir.int + cir.global @uc : !cir.int + cir.global @ss : !cir.int + cir.global @us = #cir.int<100> : !cir.int + cir.global @si = #cir.int<42> : !cir.int + cir.global @ui : !cir.int + cir.global @sl : !cir.int + cir.global @ul : !cir.int + cir.global @sll : !cir.int + cir.global @ull = #cir.int<123456> : !cir.int + cir.global @s128 : !cir.int + cir.global @u128 : !cir.int + cir.global @wc : !cir.int + cir.global @c8 : !cir.int + cir.global @c16 : !cir.int + cir.global @c32 : !cir.int + cir.global @sb20 : !cir.int + cir.global @ub48 : !cir.int + cir.global @f16 : !cir.f16 + cir.global @bf16 : !cir.bf16 + cir.global @f : !cir.float + cir.global @d = #cir.fp<1.250000e+00> : !cir.double + cir.global @ld : !cir.long_double + cir.global @f128 : !cir.f128 + cir.global @vp : !cir.ptr + cir.global @ip = #cir.ptr : !cir.ptr> + cir.global @dp : !cir.ptr + cir.global @cpp : !cir.ptr>> + cir.global @fp : !cir.ptr> + cir.global @fpii = #cir.ptr : !cir.ptr (!cir.int)>> + cir.global @fpvar : !cir.ptr, ...)>> +} + +// CHECK: cir.global @c : !cir.int +// CHECK: cir.global @sc : !cir.int +// CHECK: cir.global @uc : !cir.int +// CHECK: cir.global @ss : !cir.int +// CHECK: cir.global @us = #cir.int<100> +// CHECK: cir.global @si = #cir.int<42> +// CHECK: cir.global @ui : !cir.int +// CHECK: cir.global @sl : !cir.int +// CHECK: cir.global @ul : !cir.int +// CHECK: cir.global @sll : !cir.int +// CHECK: cir.global @ull = #cir.int<123456> : !cir.int +// CHECK: cir.global @s128 : !cir.int +// CHECK: cir.global @u128 : !cir.int +// CHECK: cir.global @wc : !cir.int +// CHECK: cir.global @c8 : !cir.int +// CHECK: cir.global @c16 : !cir.int +// CHECK: cir.global @c32 : !cir.int +// CHECK: cir.global @sb20 : !cir.int +// CHECK: cir.global @ub48 : !cir.int +// CHECK: cir.global @f16 : !cir.f16 +// CHECK: cir.global @bf16 : !cir.bf16 +// CHECK: cir.global @f : !cir.float +// CHECK: cir.global @d = #cir.fp<1.250000e+00> : !cir.double +// CHECK: cir.global @ld : !cir.long_double +// CHECK: cir.global @f128 : !cir.f128 +// CHECK: cir.global @vp : !cir.ptr +// CHECK: cir.global @ip = #cir.ptr : !cir.ptr> +// CHECK: cir.global @dp : !cir.ptr +// CHECK: cir.global @cpp : !cir.ptr>> +// CHECK: cir.global @fp : !cir.ptr> +// CHECK: cir.global @fpii = #cir.ptr : !cir.ptr (!cir.int)>> +// CHECK: cir.global @fpvar : !cir.ptr, ...)>> diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index 4ff81e7055c57..1c93e2b0d9844 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -85,7 +85,13 @@ list(APPEND CLANG_TEST_DEPS diagtool hmaptool ) - + +if(CLANG_ENABLE_CIR) + list(APPEND CLANG_TEST_DEPS + cir-opt + ) +endif() + if(CLANG_ENABLE_STATIC_ANALYZER) list(APPEND CLANG_TEST_DEPS clang-check diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py index e4b39c4f71597..9820ddd1f14af 100644 --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -29,6 +29,7 @@ ".c", ".cpp", ".i", + ".cir", ".cppm", ".m", ".mm", @@ -85,6 +86,7 @@ tools = [ "apinotes-test", "c-index-test", + "cir-opt", "clang-diff", "clang-format", "clang-repl", diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt index de0b47f3751f1..ae3414e177192 100644 --- a/clang/tools/CMakeLists.txt +++ b/clang/tools/CMakeLists.txt @@ -3,6 +3,9 @@ create_subdirectory_options(CLANG TOOL) add_clang_subdirectory(diagtool) add_clang_subdirectory(driver) add_clang_subdirectory(apinotes-test) +if(CLANG_ENABLE_CIR) + add_clang_subdirectory(cir-opt) +endif() add_clang_subdirectory(clang-diff) add_clang_subdirectory(clang-format) add_clang_subdirectory(clang-fuzzer) diff --git a/clang/tools/cir-opt/CMakeLists.txt b/clang/tools/cir-opt/CMakeLists.txt new file mode 100644 index 0000000000000..75bec5f4e1b0b --- /dev/null +++ b/clang/tools/cir-opt/CMakeLists.txt @@ -0,0 +1,32 @@ +get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) +get_property(conversion_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS) + +include_directories(${LLVM_MAIN_SRC_DIR}/../mlir/include) +include_directories(${CMAKE_BINARY_DIR}/tools/mlir/include) + +add_clang_tool(cir-opt + cir-opt.cpp +) + +clang_target_link_libraries(cir-opt + PRIVATE + clangCIR + clangCIRLoweringDirectToLLVM + MLIRCIR +) + +target_link_libraries(cir-opt + PRIVATE + ${dialect_libs} + ${conversion_libs} + MLIRAnalysis + MLIRDialect + MLIRIR + MLIRMemRefDialect + MLIROptLib + MLIRParser + MLIRPass + MLIRSideEffectInterfaces + MLIRTransforms + MLIRTransformUtils +) diff --git a/clang/tools/cir-opt/cir-opt.cpp b/clang/tools/cir-opt/cir-opt.cpp new file mode 100644 index 0000000000000..0c0f6dcd9eecf --- /dev/null +++ b/clang/tools/cir-opt/cir-opt.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, 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 +// +//===----------------------------------------------------------------------===// +// +// Similar to MLIR/LLVM's "opt" tools but also deals with analysis and custom +// arguments. TODO: this is basically a copy from MlirOptMain.cpp, but capable +// of module emission as specified by the user. +// +//===----------------------------------------------------------------------===// + +#include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/InitAllPasses.h" +#include "mlir/Pass/PassManager.h" +#include "mlir/Pass/PassOptions.h" +#include "mlir/Pass/PassRegistry.h" +#include "mlir/Tools/mlir-opt/MlirOptMain.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/Passes.h" + +struct CIRToLLVMPipelineOptions + : public mlir::PassPipelineOptions {}; + +int main(int argc, char **argv) { + // TODO: register needed MLIR passes for CIR? + mlir::DialectRegistry registry; + registry.insert(); + + mlir::PassPipelineRegistration pipeline( + "cir-to-llvm", "", + [](mlir::OpPassManager &pm, const CIRToLLVMPipelineOptions &options) { + cir::direct::populateCIRToLLVMPasses(pm); + }); + + mlir::registerTransformsPasses(); + + return mlir::asMainReturnCode(MlirOptMain( + argc, argv, "Clang IR analysis and optimization tool\n", registry)); +}