From 7c24e59080a635b51220b18bd73e1c69cef47200 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Fri, 13 Sep 2024 17:55:55 -0700 Subject: [PATCH] [CIR][CIRGen][NFCI] Exceptions: change getEHDispatchBlock to create blocks inside calls getEHDispatchBlock result isn't really used to track anything just yet, so this change isn't supposed to affect anything. This is building block for having a cleanup per call. --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 2 +- clang/lib/CIR/CodeGen/CIRGenCall.cpp | 2 ++ clang/lib/CIR/CodeGen/CIRGenException.cpp | 13 +++++--- clang/lib/CIR/CodeGen/CIRGenFunction.h | 1 + .../CIR/Dialect/Transforms/CIRSimplify.cpp | 31 +++++++++++++++++-- 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index bdf748fbbaa1..7ea1a304f823 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -893,7 +893,7 @@ def ConditionOp : CIR_Op<"condition", [ def YieldOp : CIR_Op<"yield", [ReturnLike, Terminator, ParentOneOf<["IfOp", "ScopeOp", "SwitchOp", "WhileOp", "ForOp", "AwaitOp", "TernaryOp", "GlobalOp", "DoWhileOp", "TryOp", "ArrayCtor", - "ArrayDtor"]>]> { + "ArrayDtor", "CallOp"]>]> { let summary = "Represents the default branching behaviour of a region"; let description = [{ The `cir.yield` operation terminates regions on different CIR operations, diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index a446cc641dda..3a36c3338a65 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -505,8 +505,10 @@ buildCallLikeOp(CIRGenFunction &CGF, mlir::Location callLoc, } callOpWithExceptions->setAttr("extra_attrs", extraFnAttrs); + CGF.callWithExceptionCtx = callOpWithExceptions; auto *invokeDest = CGF.getInvokeDest(tryOp); (void)invokeDest; + CGF.callWithExceptionCtx = nullptr; if (tryOp.getSynthetic()) { builder.create(tryOp.getLoc()); diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp index 87a441c64cb9..d91e4c78d61a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenException.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp @@ -742,7 +742,9 @@ mlir::Operation *CIRGenFunction::buildLandingPad(mlir::cir::TryOp tryOp) { // landing pad by generating a branch to the dispatch block. In CIR the same // function is called to gather some state, but this block info it's not // useful per-se. - (void)getEHDispatchBlock(EHStack.getInnermostEHScope(), tryOp); + mlir::Block *dispatch = + getEHDispatchBlock(EHStack.getInnermostEHScope(), tryOp); + (void)dispatch; } return tryOp; @@ -789,9 +791,12 @@ CIRGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si, case EHScope::Cleanup: { assert(tryOp && "expected cir.try available"); - llvm::MutableArrayRef regions = tryOp.getCatchRegions(); - assert(regions.size() == 1 && "expected only one region"); - dispatchBlock = ®ions[0].getBlocks().back(); + assert(callWithExceptionCtx && "expected call information"); + { + mlir::OpBuilder::InsertionGuard guard(getBuilder()); + dispatchBlock = builder.createBlock(&callWithExceptionCtx.getCleanup()); + builder.createYield(callWithExceptionCtx.getLoc()); + } break; } diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index ee6ecfdd3712..1727f43be19c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1748,6 +1748,7 @@ class CIRGenFunction : public CIRGenTypeCache { }; /// Emits try/catch information for the current EH stack. + mlir::cir::CallOp callWithExceptionCtx = nullptr; mlir::Operation *buildLandingPad(mlir::cir::TryOp tryOp); mlir::Block *getEHResumeBlock(bool isCleanup, mlir::cir::TryOp tryOp); mlir::Block *getEHDispatchBlock(EHScopeStack::stable_iterator scope, diff --git a/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp b/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp index b011a8851681..349d51a083f9 100644 --- a/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp @@ -111,6 +111,30 @@ struct RemoveTrivialTry : public OpRewritePattern { } }; +// Remove call exception with empty cleanups +struct SimplifyCallOp : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult match(CallOp op) const final { + // Applicable to cir.call exception ... clean { cir.yield } + mlir::Region *r = &op.getCleanup(); + if (r->empty() || !r->hasOneBlock()) + return failure(); + + mlir::Block *b = &r->getBlocks().back(); + if (&b->back() != &b->front()) + return failure(); + + return success(isa(&b->getOperations().back())); + } + + void rewrite(CallOp op, PatternRewriter &rewriter) const final { + mlir::Block *b = &op.getCleanup().back(); + rewriter.eraseOp(&b->back()); + rewriter.eraseBlock(b); + } +}; + /// Simplify suitable ternary operations into select operations. /// /// For now we only simplify those ternary operations whose true and false @@ -255,7 +279,8 @@ void populateMergeCleanupPatterns(RewritePatternSet &patterns) { RemoveEmptySwitch, RemoveTrivialTry, SimplifyTernary, - SimplifySelect + SimplifySelect, + SimplifyCallOp >(patterns.getContext()); // clang-format on } @@ -271,8 +296,8 @@ void CIRSimplifyPass::runOnOperation() { // CastOp here is to perform a manual `fold` in // applyOpPatternsAndFold if (isa( - op)) + TernaryOp, SelectOp, ComplexCreateOp, ComplexRealOp, ComplexImagOp, + CallOp>(op)) ops.push_back(op); });