[clang] [CIR] Upstream initial support for CIR flattening (PR #130648)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 10 11:00:07 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Andy Kaylor (andykaylor)
<details>
<summary>Changes</summary>
The ClangIR CFG has to be flat before it can be lowered to LLVM IR. That is, there can be no nested regions and all blocks in a region must belong to the parent region. Currently only cir.scope operations violate these rules, so the initial implementation of the cir-flatten-cfg pass only has to transform scope operations.
---
Patch is 25.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/130648.diff
18 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/CMakeLists.txt (+6)
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+40)
- (added) clang/include/clang/CIR/Dialect/Passes.h (+39)
- (added) clang/include/clang/CIR/Dialect/Passes.td (+28)
- (modified) clang/include/clang/CIR/MissingFeatures.h (+1)
- (modified) clang/lib/CIR/Dialect/CMakeLists.txt (+1)
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+13)
- (modified) clang/lib/CIR/Dialect/IR/CMakeLists.txt (+1)
- (added) clang/lib/CIR/Dialect/Transforms/CMakeLists.txt (+18)
- (added) clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp (+114)
- (added) clang/lib/CIR/Dialect/Transforms/PassDetail.h (+29)
- (added) clang/lib/CIR/Lowering/CIRPasses.cpp (+24)
- (modified) clang/lib/CIR/Lowering/CMakeLists.txt (+19)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt (+3-1)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+99-3)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+18)
- (added) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp (+77)
- (modified) clang/test/CIR/Lowering/func-simple.cpp (+20)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/CMakeLists.txt b/clang/include/clang/CIR/Dialect/CMakeLists.txt
index f33061b2d87cf..3d4e6586e1c62 100644
--- a/clang/include/clang/CIR/Dialect/CMakeLists.txt
+++ b/clang/include/clang/CIR/Dialect/CMakeLists.txt
@@ -1 +1,7 @@
add_subdirectory(IR)
+
+set(LLVM_TARGET_DEFINITIONS Passes.td)
+mlir_tablegen(Passes.h.inc -gen-pass-decls -name CIR)
+mlir_tablegen(Passes.capi.h.inc -gen-pass-capi-header --prefix CIR)
+mlir_tablegen(Passes.capi.cpp.inc -gen-pass-capi-impl --prefix CIR)
+add_public_tablegen_target(MLIRCIRPassIncGen)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index e2ab50c78ec2d..77c43e5ace64a 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -428,6 +428,46 @@ def ScopeOp : CIR_Op<"scope", [
];
}
+//===----------------------------------------------------------------------===//
+// BrOp
+//===----------------------------------------------------------------------===//
+
+def BrOp : CIR_Op<"br",
+ [DeclareOpInterfaceMethods<BranchOpInterface, ["getSuccessorForOperands"]>,
+ Pure, Terminator]> {
+ let summary = "Unconditional branch";
+ let description = [{
+ The `cir.br` branches unconditionally to a block. Used to represent C/C++
+ goto's and general block branching.
+
+ Note that for source level `goto`'s crossing scope boundaries, those are
+ usually represented with the "symbolic" `cir.goto` operation.
+
+ Example:
+
+ ```mlir
+ ...
+ cir.br ^bb3
+ ^bb3:
+ cir.return
+ ```
+ }];
+
+ let builders = [
+ OpBuilder<(ins "mlir::Block *":$dest,
+ CArg<"mlir::ValueRange", "{}">:$destOperands), [{
+ $_state.addSuccessors(dest);
+ $_state.addOperands(destOperands);
+ }]>
+ ];
+
+ let arguments = (ins Variadic<CIR_AnyType>:$destOperands);
+ let successors = (successor AnySuccessor:$dest);
+ let assemblyFormat = [{
+ $dest (`(` $destOperands^ `:` type($destOperands) `)`)? attr-dict
+ }];
+}
+
//===----------------------------------------------------------------------===//
// GlobalOp
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/Passes.h b/clang/include/clang/CIR/Dialect/Passes.h
new file mode 100644
index 0000000000000..b691849dfc563
--- /dev/null
+++ b/clang/include/clang/CIR/Dialect/Passes.h
@@ -0,0 +1,39 @@
+//===- Passes.h - CIR pass entry points -------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This header file defines prototypes that expose pass constructors.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CIR_DIALECT_PASSES_H
+#define CLANG_CIR_DIALECT_PASSES_H
+
+#include "mlir/Pass/Pass.h"
+
+namespace clang {
+class ASTContext;
+}
+namespace mlir {
+
+std::unique_ptr<Pass> createCIRFlattenCFGPass();
+
+void populateCIRPreLoweringPasses(mlir::OpPassManager &pm);
+
+//===----------------------------------------------------------------------===//
+// Registration
+//===----------------------------------------------------------------------===//
+
+void registerCIRDialectTranslation(mlir::MLIRContext &context);
+
+/// Generate the code for registering passes.
+#define GEN_PASS_REGISTRATION
+#include "clang/CIR/Dialect/Passes.h.inc"
+
+} // namespace mlir
+
+#endif // CLANG_CIR_DIALECT_PASSES_H
diff --git a/clang/include/clang/CIR/Dialect/Passes.td b/clang/include/clang/CIR/Dialect/Passes.td
new file mode 100644
index 0000000000000..260bbd51062ad
--- /dev/null
+++ b/clang/include/clang/CIR/Dialect/Passes.td
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 CLANG_CIR_DIALECT_PASSES_TD
+#define CLANG_CIR_DIALECT_PASSES_TD
+
+include "mlir/Pass/PassBase.td"
+
+def CIRFlattenCFG : Pass<"cir-flatten-cfg"> {
+ let summary = "Produces flatten CFG";
+ let description = [{
+ This pass transforms CIR and inline all the nested regions. Thus,
+ the next post condtions are met after the pass applied:
+ - there is not any nested region in a function body
+ - all the blocks in a function belong to the parent region
+ In other words, this pass removes such CIR operations like IfOp, LoopOp,
+ ScopeOp and etc. and produces a flat CIR.
+ }];
+ let constructor = "mlir::createCIRFlattenCFGPass()";
+ let dependentDialects = ["cir::CIRDialect"];
+}
+
+#endif // CLANG_CIR_DIALECT_PASSES_TD
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index d20cd0560a7c1..ddfe654009644 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -82,6 +82,7 @@ struct MissingFeatures {
static bool objCLifetime() { return false; }
static bool emitNullabilityCheck() { return false; }
static bool astVarDeclInterface() { return false; }
+ static bool stackSaveOp() { return false; }
};
} // namespace cir
diff --git a/clang/lib/CIR/Dialect/CMakeLists.txt b/clang/lib/CIR/Dialect/CMakeLists.txt
index f33061b2d87cf..9f57627c321fb 100644
--- a/clang/lib/CIR/Dialect/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/CMakeLists.txt
@@ -1 +1,2 @@
add_subdirectory(IR)
+add_subdirectory(Transforms)
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 5ad369b40cda1..d041791770d82 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -268,6 +268,19 @@ LogicalResult cir::ScopeOp::verify() {
return success();
}
+//===----------------------------------------------------------------------===//
+// BrOp
+//===----------------------------------------------------------------------===//
+
+mlir::SuccessorOperands cir::BrOp::getSuccessorOperands(unsigned index) {
+ assert(index == 0 && "invalid successor index");
+ return mlir::SuccessorOperands(getDestOperandsMutable());
+}
+
+Block *cir::BrOp::getSuccessorForOperands(ArrayRef<Attribute>) {
+ return getDest();
+}
+
//===----------------------------------------------------------------------===//
// GlobalOp
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CMakeLists.txt b/clang/lib/CIR/Dialect/IR/CMakeLists.txt
index e3a6fc6e80ecc..aa5ea52a5e93f 100644
--- a/clang/lib/CIR/Dialect/IR/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/IR/CMakeLists.txt
@@ -11,6 +11,7 @@ add_clang_library(MLIRCIR
LINK_LIBS PUBLIC
MLIRIR
+ MLIRCIRInterfaces
MLIRDLTIDialect
MLIRDataLayoutInterfaces
MLIRFuncDialect
diff --git a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
new file mode 100644
index 0000000000000..aa27074cc6131
--- /dev/null
+++ b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_clang_library(MLIRCIRTransforms
+ FlattenCFG.cpp
+
+ DEPENDS
+ MLIRCIRPassIncGen
+
+ LINK_LIBS PUBLIC
+ clangAST
+ clangBasic
+
+ MLIRAnalysis
+ MLIRIR
+ MLIRPass
+ MLIRTransformUtils
+
+ MLIRCIR
+ MLIRCIRInterfaces
+)
diff --git a/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp b/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
new file mode 100644
index 0000000000000..dfe33beb0ae1a
--- /dev/null
+++ b/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
@@ -0,0 +1,114 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 implements pass that inlines CIR operations regions into the parent
+// function region.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PassDetail.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/Support/LogicalResult.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/Passes.h"
+#include "clang/CIR/MissingFeatures.h"
+
+using namespace mlir;
+using namespace cir;
+
+namespace {
+
+struct CIRFlattenCFGPass : public CIRFlattenCFGBase<CIRFlattenCFGPass> {
+
+ CIRFlattenCFGPass() = default;
+ void runOnOperation() override;
+};
+
+class CIRScopeOpFlattening : public mlir::OpRewritePattern<cir::ScopeOp> {
+public:
+ using OpRewritePattern<cir::ScopeOp>::OpRewritePattern;
+
+ mlir::LogicalResult
+ matchAndRewrite(cir::ScopeOp scopeOp,
+ mlir::PatternRewriter &rewriter) const override {
+ mlir::OpBuilder::InsertionGuard guard(rewriter);
+ mlir::Location loc = scopeOp.getLoc();
+
+ // Empty scope: just remove it.
+ // TODO: Remove this logic once CIR uses MLIR infrastructure to remove
+ // trivially dead operations
+ if (scopeOp.isEmpty()) {
+ rewriter.eraseOp(scopeOp);
+ return mlir::success();
+ }
+
+ // Split the current block before the ScopeOp to create the inlining
+ // point.
+ mlir::Block *currentBlock = rewriter.getInsertionBlock();
+ mlir::Block *continueBlock =
+ rewriter.splitBlock(currentBlock, rewriter.getInsertionPoint());
+ if (scopeOp.getNumResults() > 0)
+ continueBlock->addArguments(scopeOp.getResultTypes(), loc);
+
+ // Inline body region.
+ mlir::Block *beforeBody = &scopeOp.getScopeRegion().front();
+ mlir::Block *afterBody = &scopeOp.getScopeRegion().back();
+ rewriter.inlineRegionBefore(scopeOp.getScopeRegion(), continueBlock);
+
+ // Save stack and then branch into the body of the region.
+ rewriter.setInsertionPointToEnd(currentBlock);
+ assert(!cir::MissingFeatures::stackSaveOp());
+ rewriter.create<cir::BrOp>(loc, mlir::ValueRange(), beforeBody);
+
+ // Replace the scopeop return with a branch that jumps out of the body.
+ // Stack restore before leaving the body region.
+ rewriter.setInsertionPointToEnd(afterBody);
+ if (auto yieldOp = dyn_cast<cir::YieldOp>(afterBody->getTerminator())) {
+ rewriter.replaceOpWithNewOp<cir::BrOp>(yieldOp, yieldOp.getArgs(),
+ continueBlock);
+ }
+
+ // Replace the op with values return from the body region.
+ rewriter.replaceOp(scopeOp, continueBlock->getArguments());
+
+ return mlir::success();
+ }
+};
+
+void populateFlattenCFGPatterns(RewritePatternSet &patterns) {
+ patterns.add<CIRScopeOpFlattening>(patterns.getContext());
+}
+
+void CIRFlattenCFGPass::runOnOperation() {
+ RewritePatternSet patterns(&getContext());
+ populateFlattenCFGPatterns(patterns);
+
+ // Collect operations to apply patterns.
+ llvm::SmallVector<Operation *, 16> ops;
+ getOperation()->walk<mlir::WalkOrder::PostOrder>([&](Operation *op) {
+ if (isa<ScopeOp>(op))
+ ops.push_back(op);
+ });
+
+ // Apply patterns.
+ if (applyOpPatternsGreedily(ops, std::move(patterns)).failed())
+ signalPassFailure();
+}
+
+} // namespace
+
+namespace mlir {
+
+std::unique_ptr<Pass> createCIRFlattenCFGPass() {
+ return std::make_unique<CIRFlattenCFGPass>();
+}
+
+} // namespace mlir
diff --git a/clang/lib/CIR/Dialect/Transforms/PassDetail.h b/clang/lib/CIR/Dialect/Transforms/PassDetail.h
new file mode 100644
index 0000000000000..600dde56d679f
--- /dev/null
+++ b/clang/lib/CIR/Dialect/Transforms/PassDetail.h
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 CIR_DIALECT_TRANSFORMS_PASSDETAIL_H
+#define CIR_DIALECT_TRANSFORMS_PASSDETAIL_H
+
+#include "mlir/IR/Dialect.h"
+#include "mlir/Pass/Pass.h"
+
+namespace cir {
+class CIRDialect;
+} // namespace cir
+
+namespace mlir {
+// Forward declaration from Dialect.h
+template <typename ConcreteDialect>
+void registerDialect(DialectRegistry ®istry);
+
+#define GEN_PASS_CLASSES
+#include "clang/CIR/Dialect/Passes.h.inc"
+
+} // namespace mlir
+
+#endif // CIR_DIALECT_TRANSFORMS_PASSDETAIL_H
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
new file mode 100644
index 0000000000000..235acbfee8967
--- /dev/null
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 implements machinery for any CIR <-> CIR passes used by clang.
+//
+//===----------------------------------------------------------------------===//
+
+// #include "clang/AST/ASTContext.h"
+#include "clang/CIR/Dialect/Passes.h"
+
+#include "mlir/Pass/PassManager.h"
+
+namespace mlir {
+
+void populateCIRPreLoweringPasses(OpPassManager &pm) {
+ pm.addPass(createCIRFlattenCFGPass());
+}
+
+} // namespace mlir
diff --git a/clang/lib/CIR/Lowering/CMakeLists.txt b/clang/lib/CIR/Lowering/CMakeLists.txt
index 95c304ded9183..09e48862df63c 100644
--- a/clang/lib/CIR/Lowering/CMakeLists.txt
+++ b/clang/lib/CIR/Lowering/CMakeLists.txt
@@ -1 +1,20 @@
+set(LLVM_LINK_COMPONENTS
+ Core
+ Support
+ )
+
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+
+add_clang_library(clangCIRLoweringCommon
+ CIRPasses.cpp
+
+ LINK_LIBS
+ clangCIR
+ ${dialect_libs}
+ MLIRCIR
+ MLIRCIRTransforms
+ MLIRTransforms
+ MLIRSupport
+ )
+
add_subdirectory(DirectToLLVM)
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
index c11ecb82183d0..7baff3412a84e 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
@@ -7,6 +7,7 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
add_clang_library(clangCIRLoweringDirectToLLVM
LowerToLLVM.cpp
+ LowerToLLVMIR.cpp
DEPENDS
MLIRCIREnumsGen
@@ -14,9 +15,10 @@ add_clang_library(clangCIRLoweringDirectToLLVM
MLIRCIROpInterfacesIncGen
LINK_LIBS
- MLIRIR
+ clangCIRLoweringCommon
${dialect_libs}
MLIRCIR
MLIRBuiltinToLLVMIRTranslation
MLIRLLVMToLLVMIRTranslation
+ MLIRIR
)
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 3200527bd03af..b320dae4c1b9f 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -12,6 +12,8 @@
#include "LowerToLLVM.h"
+#include <deque>
+
#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
#include "mlir/Dialect/DLTI/DLTI.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
@@ -25,6 +27,7 @@
#include "mlir/Target/LLVMIR/Export.h"
#include "mlir/Transforms/DialectConversion.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/Passes.h"
#include "clang/CIR/MissingFeatures.h"
#include "clang/CIR/Passes.h"
#include "llvm/ADT/TypeSwitch.h"
@@ -603,6 +606,64 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
});
}
+// The unreachable code is not lowered by applyPartialConversion function
+// since it traverses blocks in the dominance order. At the same time we
+// do need to lower such code - otherwise verification errors occur.
+// For instance, the next CIR code:
+//
+// cir.func @foo(%arg0: !s32i) -> !s32i {
+// %4 = cir.cast(int_to_bool, %arg0 : !s32i), !cir.bool
+// cir.if %4 {
+// %5 = cir.const #cir.int<1> : !s32i
+// cir.return %5 : !s32i
+// } else {
+// %5 = cir.const #cir.int<0> : !s32i
+// cir.return %5 : !s32i
+// }
+// cir.return %arg0 : !s32i
+// }
+//
+// contains an unreachable return operation (the last one). After the flattening
+// pass it will be placed into the unreachable block. And the possible error
+// after the lowering pass is: error: 'cir.return' op expects parent op to be
+// one of 'cir.func, cir.scope, cir.if ... The reason that this operation was
+// not lowered and the new parent is llvm.func.
+//
+// In the future we may want to get rid of this function and use DCE pass or
+// something similar. But now we need to guarantee the absence of the dialect
+// verification errors.
+static void collectUnreachable(mlir::Operation *parent,
+ llvm::SmallVector<mlir::Operation *> &ops) {
+
+ llvm::SmallVector<mlir::Block *> unreachableBlocks;
+ parent->walk([&](mlir::Block *blk) { // check
+ if (blk->hasNoPredecessors() && !blk->isEntryBlock())
+ unreachableBlocks.push_back(blk);
+ });
+
+ std::set<mlir::Block *> visited;
+ for (mlir::Block *root : unreachableBlocks) {
+ // We create a work list for each unreachable block.
+ // Thus we traverse operations in some order.
+ std::deque<mlir::Block *> workList;
+ workList.push_back(root);
+
+ while (!workList.empty()) {
+ mlir::Block *blk = workList.back();
+ workList.pop_back();
+ if (visited.count(blk))
+ continue;
+ visited.emplace(blk);
+
+ for (mlir::Operation &op : *blk)
+ ops.push_back(&op);
+
+ for (mlir::Block *succ : blk->getSuccessors())
+ workList.push_back(succ);
+ }
+ }
+}
+
void ConvertCIRToLLVMPass::processCIRAttrs(mlir::ModuleOp module) {
// Lower the module attributes to LLVM equivalents.
if (mlir::Attribute tripleAttr =
@@ -630,7 +691,13 @@ void ConvertCIRToLLVMPass::runOnOperation() {
patterns.add<CIRToLLVMGlobalOpLowering>(converter, patterns.getContext(), dl);
patterns.add<CIRToLLVMConstantOpLowering>(converter, patterns.getContext(),
dl);
- patterns.add<CIRToLLVMFuncOpLowering>(converter, patterns.getContext());
+ patterns.add<
+ // clang-format off
+ CIRToLLVMBrOpLowering,
+ CIRToLLVMFuncOpLowering,
+ CIRToLLVMTrapOpLowering
+ // clang-format on
+ >(converter, patterns.getContext());
processCIRAttrs(module);
@@ -640,9 +707,36 @@ void ConvertCIRToLLVMPass::runOnOperation() {
target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
mlir::func::FuncDialect>();
- if (failed(applyPartialConversion(module, target, std::move(patterns)))) {
+ llvm::SmallVector<mlir::Operation *> ops;
+ ops.push_back(module);
+ collectUnreachable(module, ops);
+
+ if (failed(applyPartialConversion(ops, target, std::move(patterns))))
signalPassFailure();
- }
+}
+
+mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
+ cir::BrOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(op, adaptor.getOperands(),
+ op.getDest());
+ return mlir::LogicalResult::success();
+}
+
+mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
+ cir::TrapOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ mlir::Location loc = op->getLoc();
+ rewriter.eraseOp(op);
+
+ rewriter.create<mlir::LLVM::Trap>(loc);
+
+ // Note that the call to llvm.trap is not a terminator in LLVM dialect.
+ // So we must emit an additional llvm.unreachable to terminate the current
+ //...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/130648
More information about the cfe-commits
mailing list