[clang] 8b15fc1 - [CIR] Fix FlattenCFG pattern rewriter contract violations (#192359)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 16 11:05:37 PDT 2026
Author: Bruno Cardoso Lopes
Date: 2026-04-16T11:05:31-07:00
New Revision: 8b15fc14f5314ceb8576629f3190d4c740590396
URL: https://github.com/llvm/llvm-project/commit/8b15fc14f5314ceb8576629f3190d4c740590396
DIFF: https://github.com/llvm/llvm-project/commit/8b15fc14f5314ceb8576629f3190d4c740590396.diff
LOG: [CIR] Fix FlattenCFG pattern rewriter contract violations (#192359)
Fix patterns in CIRFlattenCFGPass that modify IR but return failure(),
violating the MLIR greedy pattern rewriter contract. The contract
requires that if a pattern modifies IR, it must return success().
- CIRCleanupScopeOpFlattening: always return success() since IR is
modified (blocks split, regions inlined) before error paths
- Ternary op flattening: return success() instead of falling through
after emitError, since splitBlock/createBlock already modified IR
- Use rewriter.moveOpBefore() instead of direct defOp->moveBefore() to
properly notify the rewriter of IR mutations
Found by MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS=ON.
Test: flatten-cleanup-scope-nyi.cir (a silly one since it's testing an
error, but point still valid)
Added:
Modified:
clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
Removed:
################################################################################
diff --git a/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp b/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
index cae1a771a9694..48c47deb2bc0a 100644
--- a/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
@@ -537,7 +537,10 @@ class CIRTernaryOpFlattening : public mlir::OpRewritePattern<cir::TernaryOp> {
mlir::Operation *trueTerminator = trueRegion.back().getTerminator();
rewriter.setInsertionPointToEnd(&trueRegion.back());
- // Handle both yield and unreachable terminators (throw expressions)
+ // Handle both yield and unreachable terminators (throw expressions).
+ // Note: IR has already been modified (splitBlock, createBlock above), so
+ // we must not return failure() from this point onward per the MLIR pattern
+ // rewriter contract.
if (auto trueYieldOp = dyn_cast<cir::YieldOp>(trueTerminator)) {
rewriter.replaceOpWithNewOp<cir::BrOp>(trueYieldOp, trueYieldOp.getArgs(),
continueBlock);
@@ -547,7 +550,9 @@ class CIRTernaryOpFlattening : public mlir::OpRewritePattern<cir::TernaryOp> {
trueTerminator->emitError("unexpected terminator in ternary true region, "
"expected yield or unreachable, got: ")
<< trueTerminator->getName();
- return mlir::failure();
+ // Return success because IR was already modified
+ // (splitBlock/createBlock).
+ return mlir::success();
}
rewriter.inlineRegionBefore(trueRegion, continueBlock);
@@ -568,7 +573,9 @@ class CIRTernaryOpFlattening : public mlir::OpRewritePattern<cir::TernaryOp> {
falseTerminator->emitError("unexpected terminator in ternary false "
"region, expected yield or unreachable, got: ")
<< falseTerminator->getName();
- return mlir::failure();
+ // Return success because IR was already modified
+ // (splitBlock/createBlock).
+ return mlir::success();
}
rewriter.inlineRegionBefore(falseRegion, continueBlock);
@@ -914,7 +921,7 @@ class CIRCleanupScopeOpFlattening
if (shouldSinkReturnOperand(operand, returnOp)) {
// Sink the defining op to the dispatch block.
mlir::Operation *defOp = operand.getDefiningOp();
- defOp->moveBefore(destBlock, destBlock->end());
+ rewriter.moveOpBefore(defOp, destBlock, destBlock->end());
returnValues.push_back(operand);
} else {
// Create an alloca in the function entry block.
@@ -1385,7 +1392,13 @@ class CIRCleanupScopeOpFlattening
// Erase the original cleanup scope op.
rewriter.eraseOp(cleanupOp);
- return result;
+ // Always return success because the IR has been modified (blocks split,
+ // regions inlined, ops erased, etc.). The MLIR pattern rewriter contract
+ // requires that if a pattern modifies IR, it must return success(). Any
+ // errors from unsupported exit operations (e.g. goto) have already been
+ // reported via emitError and an unreachable terminator was placed as a
+ // placeholder.
+ return mlir::success();
}
mlir::LogicalResult
More information about the cfe-commits
mailing list