From ef76e39c5904c22ee8895ae00047960f2a43a9bf Mon Sep 17 00:00:00 2001 From: Amr Hesham Date: Mon, 27 Oct 2025 19:55:44 +0100 Subject: [PATCH 1/5] [CIR] Upstream TryCallOp --- .../clang/CIR/Dialect/IR/CIRDialect.td | 1 + clang/include/clang/CIR/Dialect/IR/CIROps.td | 94 ++++++++- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 197 +++++++++++++++++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 24 ++- clang/test/CIR/IR/try-call.cir | 31 +++ 5 files changed, 335 insertions(+), 12 deletions(-) create mode 100644 clang/test/CIR/IR/try-call.cir diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td index e91537186df59..34df9af7fc06d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td @@ -44,6 +44,7 @@ def CIR_Dialect : Dialect { static llvm::StringRef getModuleLevelAsmAttrName() { return "cir.module_asm"; } static llvm::StringRef getGlobalCtorsAttrName() { return "cir.global_ctors"; } static llvm::StringRef getGlobalDtorsAttrName() { return "cir.global_dtors"; } + static llvm::StringRef getOperandSegmentSizesAttrName() { return "operandSegmentSizes"; } void registerAttributes(); void registerTypes(); diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 777b49434f119..c483764632bf3 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2728,7 +2728,7 @@ def CIR_LLVMIntrinsicCallOp : CIR_Op<"call_llvm_intrinsic"> { } //===----------------------------------------------------------------------===// -// CallOp +// CallOp and TryCallOp //===----------------------------------------------------------------------===// def CIR_SideEffect : CIR_I32EnumAttr< @@ -2855,6 +2855,98 @@ def CIR_CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> { ]; } +def CIR_TryCallOp : CIR_CallOpBase<"try_call",[ + DeclareOpInterfaceMethods, + Terminator, AttrSizedOperandSegments +]> { + let summary = "try_call operation"; + + let description = [{ + Mostly similar to cir.call but requires two destination + branches, one for handling exceptions in case its thrown and + the other one to follow on regular control-flow. + + Example: + + ```mlir + // Direct call + %result = cir.try_call @division(%a, %b) ^continue, ^landing_pad + : (f32, f32) -> f32 + ``` + }]; + + let arguments = !con((ins + Variadic:$contOperands, + Variadic:$landingPadOperands + ), commonArgs); + + let results = (outs Optional:$result); + let successors = (successor AnySuccessor:$cont, AnySuccessor:$landing_pad); + + let skipDefaultBuilders = 1; + + let builders = [ + OpBuilder<(ins "mlir::SymbolRefAttr":$callee, "mlir::Type":$resType, + "mlir::Block *":$cont, "mlir::Block *":$landing_pad, + CArg<"mlir::ValueRange", "{}">:$operands, + CArg<"mlir::ValueRange", "{}">:$contOperands, + CArg<"mlir::ValueRange", "{}">:$landingPadOperands, + CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{ + $_state.addOperands(operands); + if (callee) + $_state.addAttribute("callee", callee); + if (resType && !isa(resType)) + $_state.addTypes(resType); + + $_state.addAttribute("side_effect", + SideEffectAttr::get($_builder.getContext(), sideEffect)); + + // Handle branches + $_state.addOperands(contOperands); + $_state.addOperands(landingPadOperands); + // The TryCall ODS layout is: cont, landing_pad, operands. + llvm::copy(::llvm::ArrayRef({ + static_cast(contOperands.size()), + static_cast(landingPadOperands.size()), + static_cast(operands.size()) + }), + odsState.getOrAddProperties().operandSegmentSizes.begin()); + $_state.addSuccessors(cont); + $_state.addSuccessors(landing_pad); + }]>, + OpBuilder<(ins "mlir::Value":$ind_target, + "FuncType":$fn_type, + "mlir::Block *":$cont, "mlir::Block *":$landing_pad, + CArg<"mlir::ValueRange", "{}">:$operands, + CArg<"mlir::ValueRange", "{}">:$contOperands, + CArg<"mlir::ValueRange", "{}">:$landingPadOperands, + CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{ + ::llvm::SmallVector finalCallOperands({ind_target}); + finalCallOperands.append(operands.begin(), operands.end()); + $_state.addOperands(finalCallOperands); + + if (!fn_type.hasVoidReturn()) + $_state.addTypes(fn_type.getReturnType()); + + $_state.addAttribute("side_effect", + SideEffectAttr::get($_builder.getContext(), sideEffect)); + + // Handle branches + $_state.addOperands(contOperands); + $_state.addOperands(landingPadOperands); + // The TryCall ODS layout is: cont, landing_pad, operands. + llvm::copy(::llvm::ArrayRef({ + static_cast(contOperands.size()), + static_cast(landingPadOperands.size()), + static_cast(finalCallOperands.size()) + }), + odsState.getOrAddProperties().operandSegmentSizes.begin()); + $_state.addSuccessors(cont); + $_state.addSuccessors(landing_pad); + }]> + ]; +} + //===----------------------------------------------------------------------===// // AwaitOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index f1bacff7fc691..32e42203c880a 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -721,13 +721,78 @@ unsigned cir::CallOp::getNumArgOperands() { return this->getOperation()->getNumOperands(); } +static mlir::ParseResult +parseTryCallBranches(mlir::OpAsmParser &parser, mlir::OperationState &result, + llvm::SmallVectorImpl + &continueOperands, + llvm::SmallVectorImpl + &landingPadOperands, + llvm::SmallVectorImpl &continueTypes, + llvm::SmallVectorImpl &landingPadTypes, + llvm::SMLoc &continueOperandsLoc, + llvm::SMLoc &landingPadOperandsLoc) { + mlir::Block *continueSuccessor = nullptr; + mlir::Block *landingPadSuccessor = nullptr; + + if (parser.parseSuccessor(continueSuccessor)) + return mlir::failure(); + + if (mlir::succeeded(parser.parseOptionalLParen())) { + continueOperandsLoc = parser.getCurrentLocation(); + if (parser.parseOperandList(continueOperands)) + return mlir::failure(); + if (parser.parseColon()) + return mlir::failure(); + + if (parser.parseTypeList(continueTypes)) + return mlir::failure(); + if (parser.parseRParen()) + return mlir::failure(); + } + + if (parser.parseComma()) + return mlir::failure(); + + if (parser.parseSuccessor(landingPadSuccessor)) + return mlir::failure(); + + if (mlir::succeeded(parser.parseOptionalLParen())) { + landingPadOperandsLoc = parser.getCurrentLocation(); + if (parser.parseOperandList(landingPadOperands)) + return mlir::failure(); + if (parser.parseColon()) + return mlir::failure(); + + if (parser.parseTypeList(landingPadTypes)) + return mlir::failure(); + if (parser.parseRParen()) + return mlir::failure(); + } + + if (parser.parseOptionalAttrDict(result.attributes)) + return mlir::failure(); + + result.addSuccessors(continueSuccessor); + result.addSuccessors(landingPadSuccessor); + return mlir::success(); +} + static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, - mlir::OperationState &result) { + mlir::OperationState &result, + bool hasDestinationBlocks = false) { llvm::SmallVector ops; llvm::SMLoc opsLoc; mlir::FlatSymbolRefAttr calleeAttr; llvm::ArrayRef allResultTypes; + // TryCall control flow related + llvm::SmallVector continueOperands; + llvm::SMLoc continueOperandsLoc; + llvm::SmallVector continueTypes; + llvm::SmallVector landingPadOperands; + llvm::SMLoc landingPadOperandsLoc; + llvm::SmallVector landingPadTypes; + // If we cannot parse a string callee, it means this is an indirect call. if (!parser .parseOptionalAttribute(calleeAttr, CIRDialect::getCalleeAttrName(), @@ -749,6 +814,14 @@ static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, if (parser.parseRParen()) return mlir::failure(); + if (hasDestinationBlocks && + parseTryCallBranches(parser, result, continueOperands, landingPadOperands, + continueTypes, landingPadTypes, continueOperandsLoc, + landingPadOperandsLoc) + .failed()) { + return ::mlir::failure(); + } + if (parser.parseOptionalKeyword("nothrow").succeeded()) result.addAttribute(CIRDialect::getNoThrowAttrName(), mlir::UnitAttr::get(parser.getContext())); @@ -781,6 +854,24 @@ static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, if (parser.resolveOperands(ops, opsFnTy.getInputs(), opsLoc, result.operands)) return mlir::failure(); + if (hasDestinationBlocks) { + // The TryCall ODS layout is: cont, landing_pad, operands. + llvm::copy(::llvm::ArrayRef( + {static_cast(continueOperands.size()), + static_cast(landingPadOperands.size()), + static_cast(ops.size())}), + result.getOrAddProperties() + .operandSegmentSizes.begin()); + + if (parser.resolveOperands(continueOperands, continueTypes, + continueOperandsLoc, result.operands)) + return ::mlir::failure(); + + if (parser.resolveOperands(landingPadOperands, landingPadTypes, + landingPadOperandsLoc, result.operands)) + return ::mlir::failure(); + } + return mlir::success(); } @@ -788,7 +879,9 @@ static void printCallCommon(mlir::Operation *op, mlir::FlatSymbolRefAttr calleeSym, mlir::Value indirectCallee, mlir::OpAsmPrinter &printer, bool isNothrow, - cir::SideEffect sideEffect) { + cir::SideEffect sideEffect, + mlir::Block *cont = nullptr, + mlir::Block *landingPad = nullptr) { printer << ' '; auto callLikeOp = mlir::cast(op); @@ -802,8 +895,35 @@ static void printCallCommon(mlir::Operation *op, assert(indirectCallee); printer << indirectCallee; } + printer << "(" << ops << ")"; + if (cont) { + assert(landingPad && "expected two successors"); + auto tryCall = dyn_cast(op); + assert(tryCall && "regular calls do not branch"); + printer << ' ' << tryCall.getCont(); + if (!tryCall.getContOperands().empty()) { + printer << "("; + printer << tryCall.getContOperands(); + printer << ' ' << ":"; + printer << ' '; + printer << tryCall.getContOperands().getTypes(); + printer << ")"; + } + printer << ","; + printer << ' '; + printer << tryCall.getLandingPad(); + if (!tryCall.getLandingPadOperands().empty()) { + printer << "("; + printer << tryCall.getLandingPadOperands(); + printer << ' ' << ":"; + printer << ' '; + printer << tryCall.getLandingPadOperands().getTypes(); + printer << ")"; + } + } + if (isNothrow) printer << " nothrow"; @@ -813,10 +933,11 @@ static void printCallCommon(mlir::Operation *op, printer << ")"; } - printer.printOptionalAttrDict(op->getAttrs(), - {CIRDialect::getCalleeAttrName(), - CIRDialect::getNoThrowAttrName(), - CIRDialect::getSideEffectAttrName()}); + llvm::SmallVector<::llvm::StringRef, 4> elidedAttrs = { + CIRDialect::getCalleeAttrName(), CIRDialect::getNoThrowAttrName(), + CIRDialect::getSideEffectAttrName(), + CIRDialect::getOperandSegmentSizesAttrName()}; + printer.printOptionalAttrDict(op->getAttrs(), elidedAttrs); printer << " : "; printer.printFunctionalType(op->getOperands().getTypes(), @@ -898,6 +1019,70 @@ cir::CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) { return verifyCallCommInSymbolUses(*this, symbolTable); } +//===----------------------------------------------------------------------===// +// TryCallOp +//===----------------------------------------------------------------------===// + +mlir::OperandRange cir::TryCallOp::getArgOperands() { + if (isIndirect()) + return getArgs().drop_front(1); + return getArgs(); +} + +mlir::MutableOperandRange cir::TryCallOp::getArgOperandsMutable() { + mlir::MutableOperandRange args = getArgsMutable(); + if (isIndirect()) + return args.slice(1, args.size() - 1); + return args; +} + +mlir::Value cir::TryCallOp::getIndirectCall() { + assert(isIndirect()); + return getOperand(0); +} + +/// Return the operand at index 'i'. +Value cir::TryCallOp::getArgOperand(unsigned i) { + if (isIndirect()) + ++i; + return getOperand(i); +} + +/// Return the number of operands. +unsigned cir::TryCallOp::getNumArgOperands() { + if (isIndirect()) + return this->getOperation()->getNumOperands() - 1; + return this->getOperation()->getNumOperands(); +} + +LogicalResult +cir::TryCallOp::verifySymbolUses(SymbolTableCollection &symbolTable) { + return verifyCallCommInSymbolUses(*this, symbolTable); +} + +mlir::ParseResult cir::TryCallOp::parse(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + return parseCallCommon(parser, result, /*hasDestinationBlocks=*/true); +} + +void cir::TryCallOp::print(::mlir::OpAsmPrinter &p) { + mlir::Value indirectCallee = isIndirect() ? getIndirectCall() : nullptr; + cir::SideEffect sideEffect = getSideEffect(); + printCallCommon(*this, getCalleeAttr(), indirectCallee, p, getNothrow(), + sideEffect, getCont(), getLandingPad()); +} + +mlir::SuccessorOperands cir::TryCallOp::getSuccessorOperands(unsigned index) { + assert(index < getNumSuccessors() && "invalid successor index"); + if (index == 0) + return SuccessorOperands(getContOperandsMutable()); + if (index == 1) + return SuccessorOperands(getLandingPadOperandsMutable()); + + // index == 2 + return SuccessorOperands(getArgOperandsMutable()); +} + //===----------------------------------------------------------------------===// // ReturnOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 0c34d87734c3e..e1d3674b294eb 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1494,7 +1494,9 @@ static mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, - mlir::FlatSymbolRefAttr calleeAttr) { + mlir::FlatSymbolRefAttr calleeAttr, + mlir::Block *continueBlock = nullptr, + mlir::Block *landingPadBlock = nullptr) { llvm::SmallVector llvmResults; mlir::ValueTypeRange cirResults = op->getResultTypes(); auto call = cast(op); @@ -1523,7 +1525,7 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, llvmFnTy = converter->convertType( fn.getFunctionType()); assert(llvmFnTy && "Failed to convert function type"); - } else if (auto alias = mlir::cast(callee)) { + } else if (auto alias = mlir::dyn_cast(callee)) { // If the callee was an alias. In that case, // we need to prepend the address of the alias to the operands. The // way aliases work in the LLVM dialect is a little counter-intuitive. @@ -1561,17 +1563,21 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, converter->convertType(calleeFuncTy)); } - assert(!cir::MissingFeatures::opCallLandingPad()); - assert(!cir::MissingFeatures::opCallContinueBlock()); assert(!cir::MissingFeatures::opCallCallConv()); + if (landingPadBlock) { + rewriter.replaceOpWithNewOp( + op, llvmFnTy, calleeAttr, callOperands, continueBlock, + mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{}); + return mlir::success(); + } + auto newOp = rewriter.replaceOpWithNewOp( op, llvmFnTy, calleeAttr, callOperands); if (memoryEffects) newOp.setMemoryEffectsAttr(memoryEffects); newOp.setNoUnwind(noUnwind); newOp.setWillReturn(willReturn); - return mlir::success(); } @@ -1582,6 +1588,14 @@ mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite( getTypeConverter(), op.getCalleeAttr()); } +mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite( + cir::TryCallOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + return rewriteCallOrInvoke(op.getOperation(), adaptor.getOperands(), rewriter, + getTypeConverter(), op.getCalleeAttr(), + op.getCont(), op.getLandingPad()); +} + mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite( cir::ReturnAddrOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/test/CIR/IR/try-call.cir b/clang/test/CIR/IR/try-call.cir new file mode 100644 index 0000000000000..6c23d3add15c8 --- /dev/null +++ b/clang/test/CIR/IR/try-call.cir @@ -0,0 +1,31 @@ +// RUN: cir-opt %s --verify-roundtrip | FileCheck %s + +!s32i = !cir.int + +module { + +cir.func private @division(%a: !s32i, %b: !s32i) -> !s32i + +cir.func @flatten_structure_with_try_call_op() { + %a = cir.const #cir.int<1> : !s32i + %b = cir.const #cir.int<2> : !s32i + %3 = cir.try_call @division(%a, %b) ^continue, ^landing_pad : (!s32i, !s32i) -> !s32i + ^continue: + cir.br ^landing_pad + ^landing_pad: + cir.return +} + +// CHECK: cir.func private @division(!s32i, !s32i) -> !s32i + +// CHECK: cir.func @flatten_structure_with_try_call_op() { +// CHECK-NEXT: %[[CONST_0:.*]] = cir.const #cir.int<1> : !s32i +// CHECK-NEXT: %[[CONST_1:.*]] = cir.const #cir.int<2> : !s32i +// CHECK-NEXT: %[[CALL:.*]] = cir.try_call @division(%0, %1) ^[[CONTINUE:.*]], ^[[LANDING_PAD:.*]] : (!s32i, !s32i) -> !s32i +// CHECK-NEXT: ^[[CONTINUE]]: +// CHECK-NEXT: cir.br ^[[LANDING_PAD]] +// CHECK-NEXT: ^[[LANDING_PAD]]: +// CHECK-NEXT: cir.return +// CHECK-NEXT: } + +} From fd5c5004c56b95e537c72271651a2ce93be5e19c Mon Sep 17 00:00:00 2001 From: Amr Hesham Date: Thu, 20 Nov 2025 18:42:47 +0100 Subject: [PATCH 2/5] WIP --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 47 +++++----- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 86 +++++-------------- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 24 ++---- 3 files changed, 53 insertions(+), 104 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index c483764632bf3..e2c6d4b4b771f 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2870,27 +2870,29 @@ def CIR_TryCallOp : CIR_CallOpBase<"try_call",[ ```mlir // Direct call - %result = cir.try_call @division(%a, %b) ^continue, ^landing_pad + %result = cir.try_call @division(%a, %b) ^normalDest, ^unwindDest : (f32, f32) -> f32 ``` }]; let arguments = !con((ins - Variadic:$contOperands, - Variadic:$landingPadOperands + Variadic:$normalDestOperands, + Variadic:$unwindDestOperands ), commonArgs); let results = (outs Optional:$result); - let successors = (successor AnySuccessor:$cont, AnySuccessor:$landing_pad); + let successors = (successor AnySuccessor:$normalDest, AnySuccessor:$unwindDest); let skipDefaultBuilders = 1; + let hasLLVMLowering = false; let builders = [ OpBuilder<(ins "mlir::SymbolRefAttr":$callee, "mlir::Type":$resType, - "mlir::Block *":$cont, "mlir::Block *":$landing_pad, + "mlir::Block *":$normalDest, + "mlir::Block *":$unwindDest, CArg<"mlir::ValueRange", "{}">:$operands, - CArg<"mlir::ValueRange", "{}">:$contOperands, - CArg<"mlir::ValueRange", "{}">:$landingPadOperands, + CArg<"mlir::ValueRange", "{}">:$normalDestOperands, + CArg<"mlir::ValueRange", "{}">:$unwindDestOperands, CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{ $_state.addOperands(operands); if (callee) @@ -2902,24 +2904,25 @@ def CIR_TryCallOp : CIR_CallOpBase<"try_call",[ SideEffectAttr::get($_builder.getContext(), sideEffect)); // Handle branches - $_state.addOperands(contOperands); - $_state.addOperands(landingPadOperands); + $_state.addOperands(normalDestOperands); + $_state.addOperands(unwindDestOperands); // The TryCall ODS layout is: cont, landing_pad, operands. llvm::copy(::llvm::ArrayRef({ - static_cast(contOperands.size()), - static_cast(landingPadOperands.size()), + static_cast(normalDestOperands.size()), + static_cast(unwindDestOperands.size()), static_cast(operands.size()) }), odsState.getOrAddProperties().operandSegmentSizes.begin()); - $_state.addSuccessors(cont); - $_state.addSuccessors(landing_pad); + $_state.addSuccessors(normalDest); + $_state.addSuccessors(unwindDest); }]>, OpBuilder<(ins "mlir::Value":$ind_target, "FuncType":$fn_type, - "mlir::Block *":$cont, "mlir::Block *":$landing_pad, + "mlir::Block *":$normalDest, + "mlir::Block *":$unwindDest, CArg<"mlir::ValueRange", "{}">:$operands, - CArg<"mlir::ValueRange", "{}">:$contOperands, - CArg<"mlir::ValueRange", "{}">:$landingPadOperands, + CArg<"mlir::ValueRange", "{}">:$normalDestOperands, + CArg<"mlir::ValueRange", "{}">:$unwindDestOperands, CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{ ::llvm::SmallVector finalCallOperands({ind_target}); finalCallOperands.append(operands.begin(), operands.end()); @@ -2932,17 +2935,17 @@ def CIR_TryCallOp : CIR_CallOpBase<"try_call",[ SideEffectAttr::get($_builder.getContext(), sideEffect)); // Handle branches - $_state.addOperands(contOperands); - $_state.addOperands(landingPadOperands); + $_state.addOperands(normalDestOperands); + $_state.addOperands(unwindDestOperands); // The TryCall ODS layout is: cont, landing_pad, operands. llvm::copy(::llvm::ArrayRef({ - static_cast(contOperands.size()), - static_cast(landingPadOperands.size()), + static_cast(normalDestOperands.size()), + static_cast(unwindDestOperands.size()), static_cast(finalCallOperands.size()) }), odsState.getOrAddProperties().operandSegmentSizes.begin()); - $_state.addSuccessors(cont); - $_state.addSuccessors(landing_pad); + $_state.addSuccessors(normalDest); + $_state.addSuccessors(unwindDest); }]> ]; } diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 32e42203c880a..a8ccd1b559360 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -722,58 +722,21 @@ unsigned cir::CallOp::getNumArgOperands() { } static mlir::ParseResult -parseTryCallBranches(mlir::OpAsmParser &parser, mlir::OperationState &result, - llvm::SmallVectorImpl - &continueOperands, - llvm::SmallVectorImpl - &landingPadOperands, - llvm::SmallVectorImpl &continueTypes, - llvm::SmallVectorImpl &landingPadTypes, - llvm::SMLoc &continueOperandsLoc, - llvm::SMLoc &landingPadOperandsLoc) { - mlir::Block *continueSuccessor = nullptr; - mlir::Block *landingPadSuccessor = nullptr; - - if (parser.parseSuccessor(continueSuccessor)) +parseTryCallDestinations(mlir::OpAsmParser &parser, + mlir::OperationState &result) { + mlir::Block *normalDestSuccessor; + if (parser.parseSuccessor(normalDestSuccessor)) return mlir::failure(); - if (mlir::succeeded(parser.parseOptionalLParen())) { - continueOperandsLoc = parser.getCurrentLocation(); - if (parser.parseOperandList(continueOperands)) - return mlir::failure(); - if (parser.parseColon()) - return mlir::failure(); - - if (parser.parseTypeList(continueTypes)) - return mlir::failure(); - if (parser.parseRParen()) - return mlir::failure(); - } - if (parser.parseComma()) return mlir::failure(); - if (parser.parseSuccessor(landingPadSuccessor)) - return mlir::failure(); - - if (mlir::succeeded(parser.parseOptionalLParen())) { - landingPadOperandsLoc = parser.getCurrentLocation(); - if (parser.parseOperandList(landingPadOperands)) - return mlir::failure(); - if (parser.parseColon()) - return mlir::failure(); - - if (parser.parseTypeList(landingPadTypes)) - return mlir::failure(); - if (parser.parseRParen()) - return mlir::failure(); - } - - if (parser.parseOptionalAttrDict(result.attributes)) + mlir::Block *unwindDestSuccessor; + if (parser.parseSuccessor(unwindDestSuccessor)) return mlir::failure(); - result.addSuccessors(continueSuccessor); - result.addSuccessors(landingPadSuccessor); + result.addSuccessors(normalDestSuccessor); + result.addSuccessors(unwindDestSuccessor); return mlir::success(); } @@ -815,10 +778,7 @@ static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, return mlir::failure(); if (hasDestinationBlocks && - parseTryCallBranches(parser, result, continueOperands, landingPadOperands, - continueTypes, landingPadTypes, continueOperandsLoc, - landingPadOperandsLoc) - .failed()) { + parseTryCallDestinations(parser, result).failed()) { return ::mlir::failure(); } @@ -880,8 +840,8 @@ static void printCallCommon(mlir::Operation *op, mlir::Value indirectCallee, mlir::OpAsmPrinter &printer, bool isNothrow, cir::SideEffect sideEffect, - mlir::Block *cont = nullptr, - mlir::Block *landingPad = nullptr) { + mlir::Block *normalDest = nullptr, + mlir::Block *unwindDest = nullptr) { printer << ' '; auto callLikeOp = mlir::cast(op); @@ -898,28 +858,28 @@ static void printCallCommon(mlir::Operation *op, printer << "(" << ops << ")"; - if (cont) { + if (normalDest) { assert(landingPad && "expected two successors"); auto tryCall = dyn_cast(op); assert(tryCall && "regular calls do not branch"); - printer << ' ' << tryCall.getCont(); - if (!tryCall.getContOperands().empty()) { + printer << ' ' << tryCall.getNormalDest(); + if (!tryCall.getNormalDestOperands().empty()) { printer << "("; - printer << tryCall.getContOperands(); + printer << tryCall.getNormalDestOperands(); printer << ' ' << ":"; printer << ' '; - printer << tryCall.getContOperands().getTypes(); + printer << tryCall.getNormalDestOperands().getTypes(); printer << ")"; } printer << ","; printer << ' '; - printer << tryCall.getLandingPad(); - if (!tryCall.getLandingPadOperands().empty()) { + printer << tryCall.getUnwindDest(); + if (!tryCall.getUnwindDestOperands().empty()) { printer << "("; - printer << tryCall.getLandingPadOperands(); + printer << tryCall.getUnwindDestOperands(); printer << ' ' << ":"; printer << ' '; - printer << tryCall.getLandingPadOperands().getTypes(); + printer << tryCall.getUnwindDestOperands().getTypes(); printer << ")"; } } @@ -1069,15 +1029,15 @@ void cir::TryCallOp::print(::mlir::OpAsmPrinter &p) { mlir::Value indirectCallee = isIndirect() ? getIndirectCall() : nullptr; cir::SideEffect sideEffect = getSideEffect(); printCallCommon(*this, getCalleeAttr(), indirectCallee, p, getNothrow(), - sideEffect, getCont(), getLandingPad()); + sideEffect, getNormalDest(), getUnwindDest()); } mlir::SuccessorOperands cir::TryCallOp::getSuccessorOperands(unsigned index) { assert(index < getNumSuccessors() && "invalid successor index"); if (index == 0) - return SuccessorOperands(getContOperandsMutable()); + return SuccessorOperands(getNormalDestOperandsMutable()); if (index == 1) - return SuccessorOperands(getLandingPadOperandsMutable()); + return SuccessorOperands(getUnwindDestOperandsMutable()); // index == 2 return SuccessorOperands(getArgOperandsMutable()); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index e1d3674b294eb..0c34d87734c3e 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1494,9 +1494,7 @@ static mlir::LogicalResult rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, - mlir::FlatSymbolRefAttr calleeAttr, - mlir::Block *continueBlock = nullptr, - mlir::Block *landingPadBlock = nullptr) { + mlir::FlatSymbolRefAttr calleeAttr) { llvm::SmallVector llvmResults; mlir::ValueTypeRange cirResults = op->getResultTypes(); auto call = cast(op); @@ -1525,7 +1523,7 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, llvmFnTy = converter->convertType( fn.getFunctionType()); assert(llvmFnTy && "Failed to convert function type"); - } else if (auto alias = mlir::dyn_cast(callee)) { + } else if (auto alias = mlir::cast(callee)) { // If the callee was an alias. In that case, // we need to prepend the address of the alias to the operands. The // way aliases work in the LLVM dialect is a little counter-intuitive. @@ -1563,21 +1561,17 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, converter->convertType(calleeFuncTy)); } + assert(!cir::MissingFeatures::opCallLandingPad()); + assert(!cir::MissingFeatures::opCallContinueBlock()); assert(!cir::MissingFeatures::opCallCallConv()); - if (landingPadBlock) { - rewriter.replaceOpWithNewOp( - op, llvmFnTy, calleeAttr, callOperands, continueBlock, - mlir::ValueRange{}, landingPadBlock, mlir::ValueRange{}); - return mlir::success(); - } - auto newOp = rewriter.replaceOpWithNewOp( op, llvmFnTy, calleeAttr, callOperands); if (memoryEffects) newOp.setMemoryEffectsAttr(memoryEffects); newOp.setNoUnwind(noUnwind); newOp.setWillReturn(willReturn); + return mlir::success(); } @@ -1588,14 +1582,6 @@ mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite( getTypeConverter(), op.getCalleeAttr()); } -mlir::LogicalResult CIRToLLVMTryCallOpLowering::matchAndRewrite( - cir::TryCallOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const { - return rewriteCallOrInvoke(op.getOperation(), adaptor.getOperands(), rewriter, - getTypeConverter(), op.getCalleeAttr(), - op.getCont(), op.getLandingPad()); -} - mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite( cir::ReturnAddrOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { From 92fb0a8ddaa9a2bf3b7a6bd76317988976030bdd Mon Sep 17 00:00:00 2001 From: Amr Hesham Date: Thu, 20 Nov 2025 21:57:46 +0100 Subject: [PATCH 3/5] Address code review comments --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 76 +++++++++----------- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 53 -------------- 2 files changed, 35 insertions(+), 94 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index e2c6d4b4b771f..a4f995b1a463a 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2856,45 +2856,59 @@ def CIR_CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> { } def CIR_TryCallOp : CIR_CallOpBase<"try_call",[ - DeclareOpInterfaceMethods, - Terminator, AttrSizedOperandSegments + Terminator ]> { let summary = "try_call operation"; - let description = [{ - Mostly similar to cir.call but requires two destination - branches, one for handling exceptions in case its thrown and - the other one to follow on regular control-flow. + Mostly similar to `cir.call` but requires two destination + branches, one for follow on regular control-flow, and the other + one for handling exceptions in case it's thrown. + + This operation is used only after the CFG flatterning pass. Example: ```mlir - // Direct call - %result = cir.try_call @division(%a, %b) ^normalDest, ^unwindDest + // Before CFG flattening + cir.try { + %call = cir.call @division(%a, %b) : () -> !s32i + cir.yield + } catch all { + cir.yield + } + + // After CFG flattening + %call = cir.try_call @division(%a, %b) ^normalDest, ^unwindDest : (f32, f32) -> f32 + ^normalDest: + cir.br ^afterTryBlock + ^unwindDest: + %exception_ptr, %type_id = cir.eh.inflight_exception + cir.br ^catchHandlerBlock(%exception_ptr : !cir.ptr) + ^catchHandlerBlock: + ... ``` }]; - let arguments = !con((ins - Variadic:$normalDestOperands, - Variadic:$unwindDestOperands - ), commonArgs); - + let arguments = commonArgs; let results = (outs Optional:$result); - let successors = (successor AnySuccessor:$normalDest, AnySuccessor:$unwindDest); + let successors = (successor + AnySuccessor:$normalDest, + AnySuccessor:$unwindDest + ); let skipDefaultBuilders = 1; let hasLLVMLowering = false; let builders = [ - OpBuilder<(ins "mlir::SymbolRefAttr":$callee, "mlir::Type":$resType, + OpBuilder<(ins "mlir::SymbolRefAttr":$callee, + "mlir::Type":$resType, "mlir::Block *":$normalDest, "mlir::Block *":$unwindDest, - CArg<"mlir::ValueRange", "{}">:$operands, - CArg<"mlir::ValueRange", "{}">:$normalDestOperands, - CArg<"mlir::ValueRange", "{}">:$unwindDestOperands, + CArg<"mlir::ValueRange", "{}">:$callOperands, CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{ - $_state.addOperands(operands); + $_state.addOperands(callOperands); + if (callee) $_state.addAttribute("callee", callee); if (resType && !isa(resType)) @@ -2904,15 +2918,6 @@ def CIR_TryCallOp : CIR_CallOpBase<"try_call",[ SideEffectAttr::get($_builder.getContext(), sideEffect)); // Handle branches - $_state.addOperands(normalDestOperands); - $_state.addOperands(unwindDestOperands); - // The TryCall ODS layout is: cont, landing_pad, operands. - llvm::copy(::llvm::ArrayRef({ - static_cast(normalDestOperands.size()), - static_cast(unwindDestOperands.size()), - static_cast(operands.size()) - }), - odsState.getOrAddProperties().operandSegmentSizes.begin()); $_state.addSuccessors(normalDest); $_state.addSuccessors(unwindDest); }]>, @@ -2920,12 +2925,10 @@ def CIR_TryCallOp : CIR_CallOpBase<"try_call",[ "FuncType":$fn_type, "mlir::Block *":$normalDest, "mlir::Block *":$unwindDest, - CArg<"mlir::ValueRange", "{}">:$operands, - CArg<"mlir::ValueRange", "{}">:$normalDestOperands, - CArg<"mlir::ValueRange", "{}">:$unwindDestOperands, + CArg<"mlir::ValueRange", "{}">:$callOperands, CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{ ::llvm::SmallVector finalCallOperands({ind_target}); - finalCallOperands.append(operands.begin(), operands.end()); + finalCallOperands.append(callOperands.begin(), callOperands.end()); $_state.addOperands(finalCallOperands); if (!fn_type.hasVoidReturn()) @@ -2935,15 +2938,6 @@ def CIR_TryCallOp : CIR_CallOpBase<"try_call",[ SideEffectAttr::get($_builder.getContext(), sideEffect)); // Handle branches - $_state.addOperands(normalDestOperands); - $_state.addOperands(unwindDestOperands); - // The TryCall ODS layout is: cont, landing_pad, operands. - llvm::copy(::llvm::ArrayRef({ - static_cast(normalDestOperands.size()), - static_cast(unwindDestOperands.size()), - static_cast(finalCallOperands.size()) - }), - odsState.getOrAddProperties().operandSegmentSizes.begin()); $_state.addSuccessors(normalDest); $_state.addSuccessors(unwindDest); }]> diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index a8ccd1b559360..50e1eeea2944f 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -748,14 +748,6 @@ static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, mlir::FlatSymbolRefAttr calleeAttr; llvm::ArrayRef allResultTypes; - // TryCall control flow related - llvm::SmallVector continueOperands; - llvm::SMLoc continueOperandsLoc; - llvm::SmallVector continueTypes; - llvm::SmallVector landingPadOperands; - llvm::SMLoc landingPadOperandsLoc; - llvm::SmallVector landingPadTypes; - // If we cannot parse a string callee, it means this is an indirect call. if (!parser .parseOptionalAttribute(calleeAttr, CIRDialect::getCalleeAttrName(), @@ -814,24 +806,6 @@ static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, if (parser.resolveOperands(ops, opsFnTy.getInputs(), opsLoc, result.operands)) return mlir::failure(); - if (hasDestinationBlocks) { - // The TryCall ODS layout is: cont, landing_pad, operands. - llvm::copy(::llvm::ArrayRef( - {static_cast(continueOperands.size()), - static_cast(landingPadOperands.size()), - static_cast(ops.size())}), - result.getOrAddProperties() - .operandSegmentSizes.begin()); - - if (parser.resolveOperands(continueOperands, continueTypes, - continueOperandsLoc, result.operands)) - return ::mlir::failure(); - - if (parser.resolveOperands(landingPadOperands, landingPadTypes, - landingPadOperandsLoc, result.operands)) - return ::mlir::failure(); - } - return mlir::success(); } @@ -863,25 +837,9 @@ static void printCallCommon(mlir::Operation *op, auto tryCall = dyn_cast(op); assert(tryCall && "regular calls do not branch"); printer << ' ' << tryCall.getNormalDest(); - if (!tryCall.getNormalDestOperands().empty()) { - printer << "("; - printer << tryCall.getNormalDestOperands(); - printer << ' ' << ":"; - printer << ' '; - printer << tryCall.getNormalDestOperands().getTypes(); - printer << ")"; - } printer << ","; printer << ' '; printer << tryCall.getUnwindDest(); - if (!tryCall.getUnwindDestOperands().empty()) { - printer << "("; - printer << tryCall.getUnwindDestOperands(); - printer << ' ' << ":"; - printer << ' '; - printer << tryCall.getUnwindDestOperands().getTypes(); - printer << ")"; - } } if (isNothrow) @@ -1032,17 +990,6 @@ void cir::TryCallOp::print(::mlir::OpAsmPrinter &p) { sideEffect, getNormalDest(), getUnwindDest()); } -mlir::SuccessorOperands cir::TryCallOp::getSuccessorOperands(unsigned index) { - assert(index < getNumSuccessors() && "invalid successor index"); - if (index == 0) - return SuccessorOperands(getNormalDestOperandsMutable()); - if (index == 1) - return SuccessorOperands(getUnwindDestOperandsMutable()); - - // index == 2 - return SuccessorOperands(getArgOperandsMutable()); -} - //===----------------------------------------------------------------------===// // ReturnOp //===----------------------------------------------------------------------===// From 664ae531ed10a26e31e9ffe2e912b2929d444d42 Mon Sep 17 00:00:00 2001 From: Amr Hesham Date: Wed, 26 Nov 2025 19:20:32 +0100 Subject: [PATCH 4/5] Address code review comments --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 7 +++--- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 6 ++--- clang/test/CIR/IR/try-call.cir | 24 ++++++++++++-------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index a4f995b1a463a..5f5fab6f12300 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2860,9 +2860,10 @@ def CIR_TryCallOp : CIR_CallOpBase<"try_call",[ ]> { let summary = "try_call operation"; let description = [{ - Mostly similar to `cir.call` but requires two destination - branches, one for follow on regular control-flow, and the other - one for handling exceptions in case it's thrown. + Similar to `cir.call` but requires two destination blocks, + one which is used if the call returns without throwing an + exception (the "normal" destination) and another which is used + if an exception is thrown (the "unwind" destination). This operation is used only after the CFG flatterning pass. diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 50e1eeea2944f..93c6370d3c1f8 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -833,9 +833,8 @@ static void printCallCommon(mlir::Operation *op, printer << "(" << ops << ")"; if (normalDest) { - assert(landingPad && "expected two successors"); - auto tryCall = dyn_cast(op); - assert(tryCall && "regular calls do not branch"); + assert(unwindDest && "expected two successors"); + auto tryCall = cast(op); printer << ' ' << tryCall.getNormalDest(); printer << ","; printer << ' '; @@ -856,7 +855,6 @@ static void printCallCommon(mlir::Operation *op, CIRDialect::getSideEffectAttrName(), CIRDialect::getOperandSegmentSizesAttrName()}; printer.printOptionalAttrDict(op->getAttrs(), elidedAttrs); - printer << " : "; printer.printFunctionalType(op->getOperands().getTypes(), op->getResultTypes()); diff --git a/clang/test/CIR/IR/try-call.cir b/clang/test/CIR/IR/try-call.cir index 6c23d3add15c8..bb3f83071e5f7 100644 --- a/clang/test/CIR/IR/try-call.cir +++ b/clang/test/CIR/IR/try-call.cir @@ -9,22 +9,26 @@ cir.func private @division(%a: !s32i, %b: !s32i) -> !s32i cir.func @flatten_structure_with_try_call_op() { %a = cir.const #cir.int<1> : !s32i %b = cir.const #cir.int<2> : !s32i - %3 = cir.try_call @division(%a, %b) ^continue, ^landing_pad : (!s32i, !s32i) -> !s32i - ^continue: - cir.br ^landing_pad - ^landing_pad: + %3 = cir.try_call @division(%a, %b) ^normal, ^unwind : (!s32i, !s32i) -> !s32i + ^normal: + cir.br ^end + ^unwind: + cir.br ^end + ^end: cir.return } // CHECK: cir.func private @division(!s32i, !s32i) -> !s32i // CHECK: cir.func @flatten_structure_with_try_call_op() { -// CHECK-NEXT: %[[CONST_0:.*]] = cir.const #cir.int<1> : !s32i -// CHECK-NEXT: %[[CONST_1:.*]] = cir.const #cir.int<2> : !s32i -// CHECK-NEXT: %[[CALL:.*]] = cir.try_call @division(%0, %1) ^[[CONTINUE:.*]], ^[[LANDING_PAD:.*]] : (!s32i, !s32i) -> !s32i -// CHECK-NEXT: ^[[CONTINUE]]: -// CHECK-NEXT: cir.br ^[[LANDING_PAD]] -// CHECK-NEXT: ^[[LANDING_PAD]]: +// CHECK-NEXT: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i +// CHECK-NEXT: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i +// CHECK-NEXT: %[[CALL:.*]] = cir.try_call @division(%[[CONST_1]], %[[CONST_2]]) ^[[NORMAL:.*]], ^[[UNWIND:.*]] : (!s32i, !s32i) -> !s32i +// CHECK-NEXT: ^[[normal]]: +// CHECK-NEXT: cir.br ^[[END:.*]] +// CHECK-NEXT: ^[[unwind]]: +// CHECK-NEXT: cir.br ^[[END:.*]] +// CHECK-NEXT: ^[[END]]: // CHECK-NEXT: cir.return // CHECK-NEXT: } From 62b6230f46a7fd3d7e1c7b59f97edeb138ee53a7 Mon Sep 17 00:00:00 2001 From: Amr Hesham Date: Thu, 27 Nov 2025 21:00:08 +0100 Subject: [PATCH 5/5] Address code review comments --- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 2 +- clang/test/CIR/IR/try-call.cir | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 93c6370d3c1f8..d505ca141d383 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -850,7 +850,7 @@ static void printCallCommon(mlir::Operation *op, printer << ")"; } - llvm::SmallVector<::llvm::StringRef, 4> elidedAttrs = { + llvm::SmallVector<::llvm::StringRef> elidedAttrs = { CIRDialect::getCalleeAttrName(), CIRDialect::getNoThrowAttrName(), CIRDialect::getSideEffectAttrName(), CIRDialect::getOperandSegmentSizesAttrName()}; diff --git a/clang/test/CIR/IR/try-call.cir b/clang/test/CIR/IR/try-call.cir index bb3f83071e5f7..39db43aee40c1 100644 --- a/clang/test/CIR/IR/try-call.cir +++ b/clang/test/CIR/IR/try-call.cir @@ -24,9 +24,9 @@ cir.func @flatten_structure_with_try_call_op() { // CHECK-NEXT: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i // CHECK-NEXT: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i // CHECK-NEXT: %[[CALL:.*]] = cir.try_call @division(%[[CONST_1]], %[[CONST_2]]) ^[[NORMAL:.*]], ^[[UNWIND:.*]] : (!s32i, !s32i) -> !s32i -// CHECK-NEXT: ^[[normal]]: +// CHECK-NEXT: ^[[NORMAL]]: // CHECK-NEXT: cir.br ^[[END:.*]] -// CHECK-NEXT: ^[[unwind]]: +// CHECK-NEXT: ^[[UNWIND]]: // CHECK-NEXT: cir.br ^[[END:.*]] // CHECK-NEXT: ^[[END]]: // CHECK-NEXT: cir.return