diff --git a/mlir/include/mlir/Dialect/ControlFlow/CMakeLists.txt b/mlir/include/mlir/Dialect/ControlFlow/CMakeLists.txt --- a/mlir/include/mlir/Dialect/ControlFlow/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/ControlFlow/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(IR) +add_subdirectory(Transforms) \ No newline at end of file diff --git a/mlir/include/mlir/Dialect/ControlFlow/IR/ControlFlowOps.td b/mlir/include/mlir/Dialect/ControlFlow/IR/ControlFlowOps.td --- a/mlir/include/mlir/Dialect/ControlFlow/IR/ControlFlowOps.td +++ b/mlir/include/mlir/Dialect/ControlFlow/IR/ControlFlowOps.td @@ -45,6 +45,14 @@ program execution will abort. The provided error message may be used by a runtime to propagate the error to the user. + Asserts can be removed (e.g., in case of release builds) with + `--strip-asserts. + + Asserts can be used to check error conditions to help during debugging. + They may also be analyzed by other transforms/analyses/passes to infer + additional static program information. For this reason, asserts should be + removed as late as possible in the compilation pipeline. + Example: ```mlir diff --git a/mlir/include/mlir/Dialect/ControlFlow/Transforms/CMakeLists.txt b/mlir/include/mlir/Dialect/ControlFlow/Transforms/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/ControlFlow/Transforms/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_TARGET_DEFINITIONS Passes.td) +mlir_tablegen(Passes.h.inc -gen-pass-decls -name ControlFlow) +add_public_tablegen_target(MLIRControlFlowPassIncGen) +add_dependencies(mlir-headers MLIRControlFlowPassIncGen) + +add_mlir_doc(Passes ControlFlowPasses ./ -gen-pass-doc) diff --git a/mlir/include/mlir/Dialect/ControlFlow/Transforms/Passes.h b/mlir/include/mlir/Dialect/ControlFlow/Transforms/Passes.h new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/ControlFlow/Transforms/Passes.h @@ -0,0 +1,32 @@ +//===- Passes.h - ControlFlow passes ----------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_CONTROLFLOW_TRANSFORMS_PASSES_H +#define MLIR_DIALECT_CONTROLFLOW_TRANSFORMS_PASSES_H + +#include "mlir/Pass/Pass.h" + +namespace mlir { + +//===----------------------------------------------------------------------===// +// Passes +//===----------------------------------------------------------------------===// + +#define GEN_PASS_DECL +#include "mlir/Dialect/ControlFlow/Transforms/Passes.h.inc" + +/// Creates a pass that removed cf.assert ops. +std::unique_ptr createStripAssertsPass(); + +/// Generate the code for registering passes. +#define GEN_PASS_REGISTRATION +#include "mlir/Dialect/ControlFlow/Transforms/Passes.h.inc" + +} // namespace mlir + +#endif // MLIR_DIALECT_CONTROLFLOW_TRANSFORMS_PASSES_H diff --git a/mlir/include/mlir/Dialect/ControlFlow/Transforms/Passes.td b/mlir/include/mlir/Dialect/ControlFlow/Transforms/Passes.td new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Dialect/ControlFlow/Transforms/Passes.td @@ -0,0 +1,25 @@ +//===-- Passes.td - ControlFlow passes definition file -----*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_CONTROLFLOW_TRANSFORMS_PASSES +#define MLIR_DIALECT_CONTROLFLOW_TRANSFORMS_PASSES + +include "mlir/Pass/PassBase.td" + +def StripAsserts : Pass<"strip-asserts", "func::FuncOp"> { + let summary = "Strip cf.assert ops"; + let description = [{ + This pass removes `cf.assert` ops. This pass is for release builds and + should be run as late as possible in the compilation pipeline, as other + transforms may analyze `cf.assert` ops throughout the program to gather + additional static program information. + }]; + let constructor = "mlir::createStripAssertsPass()"; +} + +#endif // MLIR_DIALECT_CONTROLFLOW_TRANSFORMS_PASSES diff --git a/mlir/include/mlir/InitAllPasses.h b/mlir/include/mlir/InitAllPasses.h --- a/mlir/include/mlir/InitAllPasses.h +++ b/mlir/include/mlir/InitAllPasses.h @@ -19,6 +19,7 @@ #include "mlir/Dialect/Arith/Transforms/Passes.h" #include "mlir/Dialect/Async/Passes.h" #include "mlir/Dialect/Bufferization/Transforms/Passes.h" +#include "mlir/Dialect/ControlFlow/Transforms/Passes.h" #include "mlir/Dialect/Func/Transforms/Passes.h" #include "mlir/Dialect/GPU/Transforms/Passes.h" #include "mlir/Dialect/LLVMIR/Transforms/Passes.h" @@ -59,6 +60,7 @@ registerAsyncPasses(); arith::registerArithPasses(); bufferization::registerBufferizationPasses(); + registerControlFlowPasses(); func::registerFuncPasses(); registerGPUPasses(); registerGpuSerializeToCubinPass(); diff --git a/mlir/lib/Dialect/ControlFlow/CMakeLists.txt b/mlir/lib/Dialect/ControlFlow/CMakeLists.txt --- a/mlir/lib/Dialect/ControlFlow/CMakeLists.txt +++ b/mlir/lib/Dialect/ControlFlow/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(IR) +add_subdirectory(Transforms) diff --git a/mlir/lib/Dialect/ControlFlow/Transforms/CMakeLists.txt b/mlir/lib/Dialect/ControlFlow/Transforms/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/mlir/lib/Dialect/ControlFlow/Transforms/CMakeLists.txt @@ -0,0 +1,16 @@ +add_mlir_dialect_library(MLIRControlFlowTransforms + Transforms.cpp + + ADDITIONAL_HEADER_DIRS + ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/ControlFlow + + DEPENDS + MLIRControlFlowPassIncGen + + LINK_LIBS PUBLIC + MLIRControlFlowDialect + MLIRFuncDialect + MLIRIR + MLIRPass + MLIRTransforms +) diff --git a/mlir/lib/Dialect/ControlFlow/Transforms/Transforms.cpp b/mlir/lib/Dialect/ControlFlow/Transforms/Transforms.cpp new file mode 100644 --- /dev/null +++ b/mlir/lib/Dialect/ControlFlow/Transforms/Transforms.cpp @@ -0,0 +1,33 @@ +//===- Transforms.cpp - ControlFlow transforms ----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/ControlFlow/Transforms/Passes.h" + +#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/Visitors.h" + +namespace mlir { +#define GEN_PASS_DEF_STRIPASSERTS +#include "mlir/Dialect/ControlFlow/Transforms/Passes.h.inc" +} // namespace mlir + +namespace { +using namespace mlir; + +struct StripAssertsPass : public impl::StripAssertsBase { + void runOnOperation() override { + getOperation()->walk( + [](cf::AssertOp assertOp) { assertOp->erase(); }); + } +}; +} // namespace + +std::unique_ptr mlir::createStripAssertsPass() { + return std::make_unique(); +} diff --git a/mlir/test/Dialect/ControlFlow/Transforms/strip-asserts.mlir b/mlir/test/Dialect/ControlFlow/Transforms/strip-asserts.mlir new file mode 100644 --- /dev/null +++ b/mlir/test/Dialect/ControlFlow/Transforms/strip-asserts.mlir @@ -0,0 +1,8 @@ +// RUN: mlir-opt %s --strip-asserts | FileCheck %s + +// CHECK-LABEL: @test +// CHECK-NOT: cf.assert +func.func @test(%arg: i1) { + cf.assert %arg, "Some message in case this assertion fails." + return +} diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -3196,6 +3196,42 @@ ], ) +gentbl_cc_library( + name = "ControlFlowPassIncGen", + strip_include_prefix = "include", + tbl_outs = [ + ( + [ + "-gen-pass-decls", + "-name=ControlFlow", + ], + "include/mlir/Dialect/ControlFlow/Transforms/Passes.h.inc", + ), + ], + tblgen = ":mlir-tblgen", + td_file = "include/mlir/Dialect/ControlFlow/Transforms/Passes.td", + deps = [":PassBaseTdFiles"], +) + +cc_library( + name = "ControlFlowTransforms", + srcs = glob( + [ + "lib/Dialect/ControlFlow/Transforms/*.cpp", + "lib/Dialect/ControlFlow/Transforms/*.h", + ], + ), + hdrs = glob(["include/mlir/Dialect/ControlFlow/Transforms/*.h"]), + includes = ["include"], + deps = [ + ":ControlFlowDialect", + ":ControlFlowPassIncGen", + ":FuncDialect", + ":IR", + ":Pass", + ], +) + cc_library( name = "FuncDialect", srcs = glob( @@ -6657,6 +6693,7 @@ ":ComplexToLLVM", ":ComplexToLibm", ":ControlFlowDialect", + ":ControlFlowTransforms", ":ConversionPasses", ":DLTIDialect", ":EmitCDialect",