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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits