Skip to content

Commit

Permalink
[CIR][CIRGen][NFCI] Exceptions: change getEHDispatchBlock to create b…
Browse files Browse the repository at this point in the history
…locks 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.
  • Loading branch information
bcardosolopes committed Sep 14, 2024
1 parent fd3ba1d commit 7c24e59
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 8 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<mlir::cir::YieldOp>(tryOp.getLoc());
Expand Down
13 changes: 9 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -789,9 +791,12 @@ CIRGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si,

case EHScope::Cleanup: {
assert(tryOp && "expected cir.try available");
llvm::MutableArrayRef<mlir::Region> regions = tryOp.getCatchRegions();
assert(regions.size() == 1 && "expected only one region");
dispatchBlock = &regions[0].getBlocks().back();
assert(callWithExceptionCtx && "expected call information");
{
mlir::OpBuilder::InsertionGuard guard(getBuilder());
dispatchBlock = builder.createBlock(&callWithExceptionCtx.getCleanup());
builder.createYield(callWithExceptionCtx.getLoc());
}
break;
}

Expand Down
1 change: 1 addition & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
31 changes: 28 additions & 3 deletions clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,30 @@ struct RemoveTrivialTry : public OpRewritePattern<TryOp> {
}
};

// Remove call exception with empty cleanups
struct SimplifyCallOp : public OpRewritePattern<CallOp> {
using OpRewritePattern<CallOp>::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<YieldOp>(&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
Expand Down Expand Up @@ -255,7 +279,8 @@ void populateMergeCleanupPatterns(RewritePatternSet &patterns) {
RemoveEmptySwitch,
RemoveTrivialTry,
SimplifyTernary,
SimplifySelect
SimplifySelect,
SimplifyCallOp
>(patterns.getContext());
// clang-format on
}
Expand All @@ -271,8 +296,8 @@ void CIRSimplifyPass::runOnOperation() {
// CastOp here is to perform a manual `fold` in
// applyOpPatternsAndFold
if (isa<BrOp, BrCondOp, ScopeOp, SwitchOp, CastOp, TryOp, UnaryOp,
TernaryOp, SelectOp, ComplexCreateOp, ComplexRealOp, ComplexImagOp>(
op))
TernaryOp, SelectOp, ComplexCreateOp, ComplexRealOp, ComplexImagOp,
CallOp>(op))
ops.push_back(op);
});

Expand Down

0 comments on commit 7c24e59

Please sign in to comment.