https://github.com/erichkeane updated https://github.com/llvm/llvm-project/pull/186869
>From f8059fc05fb8095a710954817298aa8fe99d9bcc Mon Sep 17 00:00:00 2001 From: erichkeane <[email protected]> Date: Mon, 16 Mar 2026 11:46:52 -0700 Subject: [PATCH 1/2] [CIR] Fix bug where block after-unreachable wasn't CXXABILowered If a TU has an 'unreachable' block, it wouldn't be CXXABILower'ed, which would cause a legalization failure. This patch adds the same solution we do in LowerToLLVM, which is to make sure we transform those sections separately. --- .../CIR/Dialect/Transforms/CXXABILowering.cpp | 69 ++++++++++++++++++- .../CodeGen/abi-lower-after-unreachable.cpp | 31 +++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 clang/test/CIR/CodeGen/abi-lower-after-unreachable.cpp diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp index d2c7ac37e8a96..fcaa38683c396 100644 --- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp @@ -538,6 +538,69 @@ populateCXXABIConversionTarget(mlir::ConversionTarget &target, // The Pass //===----------------------------------------------------------------------===// +// The applyPartialConversion function traverses blocks in the dominance order, +// so it does not lower and operations that are not reachachable from the +// operations passed in as arguments. Since we do need to lower such code in +// order to avoid verification errors occur, we cannot just pass the module op +// to applyPartialConversion. We must build a set of unreachable ops and +// explicitly add them, along with the module, to the vector we pass to +// applyPartialConversion. +// +// For instance, this 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 CXXABI +// pass it will be placed into the unreachable block. This will error because +// it will have not converted the types in the block, making the legalizer fail. +// +// In the future we may want to get rid of this function and use a DCE pass or +// something similar. But for now we need to guarantee the absence of the +// dialect verification errors. Note: We do the same in LowerToLLVM as well, +// this is a striaght copy/paste including most of the comment. We might wi sh +// to combine these if we don't want to do a DCE pass/etc. +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 CXXABILoweringPass::runOnOperation() { auto mod = mlir::cast<mlir::ModuleOp>(getOperation()); mlir::MLIRContext *ctx = mod.getContext(); @@ -566,7 +629,11 @@ void CXXABILoweringPass::runOnOperation() { mlir::ConversionTarget target(*ctx); populateCXXABIConversionTarget(target, typeConverter); - if (failed(mlir::applyPartialConversion(mod, target, std::move(patterns)))) + llvm::SmallVector<mlir::Operation *> ops; + ops.push_back(mod); + collectUnreachable(mod, ops); + + if (failed(mlir::applyPartialConversion(ops, target, std::move(patterns)))) signalPassFailure(); } diff --git a/clang/test/CIR/CodeGen/abi-lower-after-unreachable.cpp b/clang/test/CIR/CodeGen/abi-lower-after-unreachable.cpp new file mode 100644 index 0000000000000..180bf365940ef --- /dev/null +++ b/clang/test/CIR/CodeGen/abi-lower-after-unreachable.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -I%S/Inputs %s -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-cxxabi-lowering -o %t.cir 2> %t-before.cir +// RUN: FileCheck %s --input-file=%t-before.cir --check-prefixes=CIR,CIR-BEFORE +// RUN: FileCheck %s --input-file=%t.cir --check-prefixes=CIR,CIR-AFTER +struct Base1 { + virtual ~Base1(); +}; + +struct Base2 { + virtual ~Base2(); +}; + +struct Derived final : Base1 {}; + +using PMFTy = void(Derived::*)(void); + +void untransformed_after_unreachable(Base2 &ref, PMFTy pmf) { + auto badcast = dynamic_cast<Derived &>(ref); + (badcast.*pmf)(); + +// CIR-LABEL: cir.func {{.*}}@_Z31untransformed_after_unreachableR5Base2M7DerivedFvvE +// CIR: %[[PMF:.*]] = cir.alloca !{{.*}} ["pmf", init] +// CIR: %[[DERIVED:.*]] = cir.alloca !rec_Derived +// CIR: cir.load %{{.*}} : !cir.ptr<!cir.ptr<!rec_Base2>>, !cir.ptr<!rec_Base2> +// CIR-NEXT: cir.call @__cxa_bad_cast() : () -> () +// CIR-NEXT: cir.unreachable +// CIR-BEFORE: %[[PMF_LOAD:.*]] = cir.load{{.*}} %[[PMF]] +// CIR-BEFORE: cir.get_method %[[PMF_LOAD]], %[[DERIVED]] +// CIR-AFTER: %[[PMF_LOAD:.*]] = cir.load{{.*}} %[[PMF]] +// CIR-AFTER: %[[PMF_EXTRACT:.*]] = cir.extract_member %[[PMF_LOAD]][1] +// CIR-AFTER: %[[PMF_EXTRACT:.*]] = cir.extract_member %[[PMF_LOAD]][0] +} >From e216f502cb549b096ec080f4ed91bebaaa6a025e Mon Sep 17 00:00:00 2001 From: erichkeane <[email protected]> Date: Mon, 16 Mar 2026 12:57:22 -0700 Subject: [PATCH 2/2] Add 'deque' include, since apparently it was transitively included on my computer but not on one of the CI bots --- clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp index fcaa38683c396..a68256ed76b6f 100644 --- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include <deque> + #include "PassDetail.h" #include "TargetLowering/LowerModule.h" _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
