Author: Sirui Mu Date: 2025-07-03T22:54:15+08:00 New Revision: 23104a74e79f208d467830058111fd883dfcb489
URL: https://github.com/llvm/llvm-project/commit/23104a74e79f208d467830058111fd883dfcb489 DIFF: https://github.com/llvm/llvm-project/commit/23104a74e79f208d467830058111fd883dfcb489.diff LOG: [CIR] Add nothrow attribute to the call operation (#145178) This patch adds extra function attributes to the `cir.call` operation. The extra attributes now may contain a single `cir.nothrow` attribute that indicates whether the callee throws. Added: Modified: clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h clang/include/clang/CIR/Dialect/IR/CIRDialect.td clang/include/clang/CIR/Dialect/IR/CIROps.td clang/include/clang/CIR/Interfaces/CIROpInterfaces.td clang/lib/CIR/CodeGen/CIRGenCall.cpp clang/lib/CIR/CodeGen/CIRGenCall.h clang/lib/CIR/CodeGen/CIRGenModule.h clang/lib/CIR/Dialect/IR/CIRDialect.cpp clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h clang/test/CIR/CodeGen/builtin_call.cpp clang/test/CIR/CodeGen/builtin_printf.cpp clang/test/CIR/CodeGen/call.cpp Removed: ################################################################################ diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 41ac8c1c875df..277c278fd38b7 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -228,25 +228,28 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, - cir::SideEffect sideEffect = cir::SideEffect::All) { - return create<cir::CallOp>(loc, callee, returnType, operands, sideEffect); + llvm::ArrayRef<mlir::NamedAttribute> attrs = {}) { + auto op = create<cir::CallOp>(loc, callee, returnType, operands); + op->setAttrs(attrs); + return op; } cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee, mlir::ValueRange operands, - cir::SideEffect sideEffect = cir::SideEffect::All) { + llvm::ArrayRef<mlir::NamedAttribute> attrs = {}) { return createCallOp(loc, mlir::SymbolRefAttr::get(callee), callee.getFunctionType().getReturnType(), operands, - sideEffect); + attrs); } - cir::CallOp createIndirectCallOp(mlir::Location loc, - mlir::Value indirectTarget, - cir::FuncType funcType, - mlir::ValueRange operands, - cir::SideEffect sideEffect) { - return create<cir::CallOp>(loc, indirectTarget, funcType.getReturnType(), - operands, sideEffect); + cir::CallOp + createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget, + cir::FuncType funcType, mlir::ValueRange operands, + llvm::ArrayRef<mlir::NamedAttribute> attrs = {}) { + llvm::SmallVector<mlir::Value> resOperands{indirectTarget}; + resOperands.append(operands.begin(), operands.end()); + return createCallOp(loc, mlir::SymbolRefAttr(), funcType.getReturnType(), + resOperands, attrs); } //===--------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td index d77ed53aa93a1..fa73e5bf41f23 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td @@ -37,6 +37,9 @@ def CIR_Dialect : Dialect { let extraClassDeclaration = [{ static llvm::StringRef getTripleAttrName() { return "cir.triple"; } static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; } + static llvm::StringRef getCalleeAttrName() { return "callee"; } + static llvm::StringRef getNoThrowAttrName() { return "nothrow"; } + static llvm::StringRef getSideEffectAttrName() { return "side_effect"; } 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 187e04bc25f24..7e0f3dba6fbe0 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1991,6 +1991,7 @@ class CIR_CallOpBase<string mnemonic, list<Trait> extra_traits = []> dag commonArgs = (ins OptionalAttr<FlatSymbolRefAttr>:$callee, Variadic<CIR_AnyType>:$args, + UnitAttr:$nothrow, DefaultValuedAttr<CIR_SideEffect, "SideEffect::All">:$side_effect); } @@ -2020,29 +2021,14 @@ def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> { let arguments = commonArgs; let builders = [ - // Build a call op for a direct call OpBuilder<(ins "mlir::SymbolRefAttr":$callee, "mlir::Type":$resType, - "mlir::ValueRange":$operands, - CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{ - assert(callee && "callee attribute is required for direct call"); + "mlir::ValueRange":$operands), [{ $_state.addOperands(operands); - $_state.addAttribute("callee", callee); - $_state.addAttribute("side_effect", - SideEffectAttr::get($_builder.getContext(), sideEffect)); + if (callee) + $_state.addAttribute("callee", callee); if (resType && !isa<VoidType>(resType)) $_state.addTypes(resType); - }]>, - // Build a call op for an indirect call - OpBuilder<(ins "mlir::Value":$calleePtr, "mlir::Type":$resType, - "mlir::ValueRange":$operands, - CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{ - $_state.addOperands(calleePtr); - $_state.addOperands(operands); - if (resType && !isa<VoidType>(resType)) - $_state.addTypes(resType); - $_state.addAttribute("side_effect", - SideEffectAttr::get($_builder.getContext(), sideEffect)); - }]>, + }]> ]; } diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td index 5817b91b49e31..4702b4ef08acc 100644 --- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td +++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td @@ -34,6 +34,8 @@ let cppNamespace = "::cir" in { "Return the number of operands, accounts for indirect call or " "exception info", "unsigned", "getNumArgOperands", (ins)>, + InterfaceMethod<"Return whether the callee is nothrow", + "bool", "getNothrow", (ins)>, InterfaceMethod<"Return the side effects of the call operation", "cir::SideEffect", "getSideEffect", (ins)>, ]; diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 163d0dbfec3dc..938d1436a76ea 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -77,17 +77,40 @@ void CIRGenFunction::emitAggregateStore(mlir::Value value, Address dest) { builder.createStore(*currSrcLoc, value, dest); } +static void addAttributesFromFunctionProtoType(CIRGenBuilderTy &builder, + mlir::NamedAttrList &attrs, + const FunctionProtoType *fpt) { + if (!fpt) + return; + + if (!isUnresolvedExceptionSpec(fpt->getExceptionSpecType()) && + fpt->isNothrow()) + attrs.set(cir::CIRDialect::getNoThrowAttrName(), + mlir::UnitAttr::get(builder.getContext())); +} + /// Construct the CIR attribute list of a function or call. void CIRGenModule::constructAttributeList(CIRGenCalleeInfo calleeInfo, - cir::SideEffect &sideEffect) { + mlir::NamedAttrList &attrs) { assert(!cir::MissingFeatures::opCallCallConv()); - sideEffect = cir::SideEffect::All; + auto sideEffect = cir::SideEffect::All; - assert(!cir::MissingFeatures::opCallAttrs()); + addAttributesFromFunctionProtoType(getBuilder(), attrs, + calleeInfo.getCalleeFunctionProtoType()); const Decl *targetDecl = calleeInfo.getCalleeDecl().getDecl(); if (targetDecl) { + if (targetDecl->hasAttr<NoThrowAttr>()) + attrs.set(cir::CIRDialect::getNoThrowAttrName(), + mlir::UnitAttr::get(&getMLIRContext())); + + if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) { + addAttributesFromFunctionProtoType( + getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>()); + assert(!cir::MissingFeatures::opCallAttrs()); + } + assert(!cir::MissingFeatures::opCallAttrs()); // 'const', 'pure' and 'noalias' attributed functions are also nounwind. @@ -104,6 +127,9 @@ void CIRGenModule::constructAttributeList(CIRGenCalleeInfo calleeInfo, } assert(!cir::MissingFeatures::opCallAttrs()); + + attrs.set(cir::CIRDialect::getSideEffectAttrName(), + cir::SideEffectAttr::get(&getMLIRContext(), sideEffect)); } /// Returns the canonical formal type of the given C++ method. @@ -416,7 +442,7 @@ emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc, cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal, cir::FuncOp directFuncOp, const SmallVectorImpl<mlir::Value> &cirCallArgs, - cir::SideEffect sideEffect) { + const mlir::NamedAttrList &attrs) { CIRGenBuilderTy &builder = cgf.getBuilder(); assert(!cir::MissingFeatures::opCallSurroundingTry()); @@ -424,14 +450,17 @@ emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc, assert(builder.getInsertionBlock() && "expected valid basic block"); + cir::CallOp op; if (indirectFuncTy) { // TODO(cir): Set calling convention for indirect calls. assert(!cir::MissingFeatures::opCallCallConv()); - return builder.createIndirectCallOp( - callLoc, indirectFuncVal, indirectFuncTy, cirCallArgs, sideEffect); + op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy, + cirCallArgs, attrs); + } else { + op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs); } - return builder.createCallOp(callLoc, directFuncOp, cirCallArgs, sideEffect); + return op; } const CIRGenFunctionInfo & @@ -544,8 +573,7 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo, assert(!cir::MissingFeatures::opCallCallConv()); assert(!cir::MissingFeatures::opCallAttrs()); - cir::SideEffect sideEffect; - cgm.constructAttributeList(callee.getAbstractInfo(), sideEffect); + cgm.constructAttributeList(callee.getAbstractInfo(), attrs); assert(!cir::MissingFeatures::invokeOp()); @@ -566,12 +594,10 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo, indirectFuncVal = calleePtr->getResult(0); } - assert(!cir::MissingFeatures::opCallAttrs()); - mlir::Location callLoc = loc; cir::CIRCallOpInterface theCall = emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp, - cirCallArgs, sideEffect); + cirCallArgs, attrs); if (callOp) *callOp = theCall; diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.h b/clang/lib/CIR/CodeGen/CIRGenCall.h index 56c76c51a46d8..bd113293fdafd 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.h +++ b/clang/lib/CIR/CodeGen/CIRGenCall.h @@ -33,7 +33,8 @@ class CIRGenCalleeInfo { CIRGenCalleeInfo(const clang::FunctionProtoType *calleeProtoTy, clang::GlobalDecl calleeDecl) : calleeProtoTy(calleeProtoTy), calleeDecl(calleeDecl) {} - CIRGenCalleeInfo(clang::GlobalDecl calleeDecl) : calleeDecl(calleeDecl) {} + CIRGenCalleeInfo(clang::GlobalDecl calleeDecl) + : calleeProtoTy(nullptr), calleeDecl(calleeDecl) {} const clang::FunctionProtoType *getCalleeFunctionProtoType() const { return calleeProtoTy; diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index 5a1eb9dea35c6..16922b115027e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -166,7 +166,7 @@ class CIRGenModule : public CIRGenTypeCache { /// constructed for. If valid, the attributes applied to this decl may /// contribute to the function attributes and calling convention. void constructAttributeList(CIRGenCalleeInfo calleeInfo, - cir::SideEffect &sideEffect); + mlir::NamedAttrList &attrs); /// Return a constant array for the given string. mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e); diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 2a54906703011..8512b229c2663 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -597,7 +597,9 @@ static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, llvm::ArrayRef<mlir::Type> allResultTypes; // If we cannot parse a string callee, it means this is an indirect call. - if (!parser.parseOptionalAttribute(calleeAttr, "callee", result.attributes) + if (!parser + .parseOptionalAttribute(calleeAttr, CIRDialect::getCalleeAttrName(), + result.attributes) .has_value()) { OpAsmParser::UnresolvedOperand indirectVal; // Do not resolve right now, since we need to figure out the type @@ -615,6 +617,10 @@ static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, if (parser.parseRParen()) return mlir::failure(); + if (parser.parseOptionalKeyword("nothrow").succeeded()) + result.addAttribute(CIRDialect::getNoThrowAttrName(), + mlir::UnitAttr::get(parser.getContext())); + if (parser.parseOptionalKeyword("side_effect").succeeded()) { if (parser.parseLParen().failed()) return failure(); @@ -624,7 +630,7 @@ static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, if (parser.parseRParen().failed()) return failure(); auto attr = cir::SideEffectAttr::get(parser.getContext(), sideEffect); - result.addAttribute("side_effect", attr); + result.addAttribute(CIRDialect::getSideEffectAttrName(), attr); } if (parser.parseOptionalAttrDict(result.attributes)) @@ -649,7 +655,7 @@ static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, static void printCallCommon(mlir::Operation *op, mlir::FlatSymbolRefAttr calleeSym, mlir::Value indirectCallee, - mlir::OpAsmPrinter &printer, + mlir::OpAsmPrinter &printer, bool isNothrow, cir::SideEffect sideEffect) { printer << ' '; @@ -666,13 +672,19 @@ static void printCallCommon(mlir::Operation *op, } printer << "(" << ops << ")"; + if (isNothrow) + printer << " nothrow"; + if (sideEffect != cir::SideEffect::All) { printer << " side_effect("; printer << stringifySideEffect(sideEffect); printer << ")"; } - printer.printOptionalAttrDict(op->getAttrs(), {"callee", "side_effect"}); + printer.printOptionalAttrDict(op->getAttrs(), + {CIRDialect::getCalleeAttrName(), + CIRDialect::getNoThrowAttrName(), + CIRDialect::getSideEffectAttrName()}); printer << " : "; printer.printFunctionalType(op->getOperands().getTypes(), @@ -687,13 +699,15 @@ mlir::ParseResult cir::CallOp::parse(mlir::OpAsmParser &parser, void cir::CallOp::print(mlir::OpAsmPrinter &p) { mlir::Value indirectCallee = isIndirect() ? getIndirectCall() : nullptr; cir::SideEffect sideEffect = getSideEffect(); - printCallCommon(*this, getCalleeAttr(), indirectCallee, p, sideEffect); + printCallCommon(*this, getCalleeAttr(), indirectCallee, p, getNothrow(), + sideEffect); } static LogicalResult verifyCallCommInSymbolUses(mlir::Operation *op, SymbolTableCollection &symbolTable) { - auto fnAttr = op->getAttrOfType<FlatSymbolRefAttr>("callee"); + auto fnAttr = + op->getAttrOfType<FlatSymbolRefAttr>(CIRDialect::getCalleeAttrName()); if (!fnAttr) { // This is an indirect call, thus we don't have to check the symbol uses. return mlir::success(); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 891017e1d8256..b24e2ee2de86f 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -232,7 +232,7 @@ mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, return value; } -void convertSideEffectForCall(mlir::Operation *callOp, +void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow, cir::SideEffect sideEffect, mlir::LLVM::MemoryEffectsAttr &memoryEffect, bool &noUnwind, bool &willReturn) { @@ -241,7 +241,7 @@ void convertSideEffectForCall(mlir::Operation *callOp, switch (sideEffect) { case cir::SideEffect::All: memoryEffect = {}; - noUnwind = false; + noUnwind = isNothrow; willReturn = false; break; @@ -800,8 +800,8 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands, mlir::LLVM::MemoryEffectsAttr memoryEffects; bool noUnwind = false; bool willReturn = false; - convertSideEffectForCall(op, call.getSideEffect(), memoryEffects, noUnwind, - willReturn); + convertSideEffectForCall(op, call.getNothrow(), call.getSideEffect(), + memoryEffects, noUnwind, willReturn); mlir::LLVM::LLVMFunctionType llvmFnTy; if (calleeAttr) { // direct call diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index 1c3622172f836..de4600f376e55 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -29,7 +29,7 @@ mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, mlir::Attribute attr, mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage); -void convertSideEffectForCall(mlir::Operation *callOp, +void convertSideEffectForCall(mlir::Operation *callOp, bool isNothrow, cir::SideEffect sideEffect, mlir::LLVM::MemoryEffectsAttr &memoryEffect, bool &noUnwind, bool &willReturn); diff --git a/clang/test/CIR/CodeGen/builtin_call.cpp b/clang/test/CIR/CodeGen/builtin_call.cpp index b956f2580593e..ad0e478040836 100644 --- a/clang/test/CIR/CodeGen/builtin_call.cpp +++ b/clang/test/CIR/CodeGen/builtin_call.cpp @@ -84,8 +84,8 @@ void library_builtins() { // CIR: cir.func{{.*}} @_Z16library_builtinsv() { // CIR: %[[NULL:.+]] = cir.const #cir.ptr<null> : !cir.ptr<!s8i> -// CIR: cir.call @printf(%[[NULL]]) : (!cir.ptr<!s8i>) -> !s32i -// CIR: cir.call @abort() : () -> () +// CIR: cir.call @printf(%[[NULL]]) nothrow : (!cir.ptr<!s8i>) -> !s32i +// CIR: cir.call @abort() nothrow : () -> () // LLVM: define{{.*}} void @_Z16library_builtinsv() // LLVM: call i32 (ptr, ...) @printf(ptr null) diff --git a/clang/test/CIR/CodeGen/builtin_printf.cpp b/clang/test/CIR/CodeGen/builtin_printf.cpp index d12f822d43ebf..43128e44b19e4 100644 --- a/clang/test/CIR/CodeGen/builtin_printf.cpp +++ b/clang/test/CIR/CodeGen/builtin_printf.cpp @@ -26,16 +26,16 @@ void func(char const * const str, int i) { // CIR: cir.store %[[arg0]], %[[str_ptr]] : !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>> // CIR: cir.store %[[arg1]], %[[i_ptr]] : !s32i, !cir.ptr<!s32i> // CIR: %[[null_ptr:.+]] = cir.const #cir.ptr<null> : !cir.ptr<!s8i> -// CIR: %[[printf_result1:.+]] = cir.call @printf(%[[null_ptr]]) : (!cir.ptr<!s8i>) -> !s32i +// CIR: %[[printf_result1:.+]] = cir.call @printf(%[[null_ptr]]) nothrow : (!cir.ptr<!s8i>) -> !s32i // CIR: %[[str_fmt_global:.+]] = cir.get_global @".str" : !cir.ptr<!cir.array<!s8i x 3>> // CIR: %[[str_fmt_ptr:.+]] = cir.cast(array_to_ptrdecay, %[[str_fmt_global]] : !cir.ptr<!cir.array<!s8i x 3>>), !cir.ptr<!s8i> // CIR: %[[str_val:.+]] = cir.load{{.*}} %[[str_ptr]] : !cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!s8i> -// CIR: %[[printf_result2:.+]] = cir.call @printf(%[[str_fmt_ptr]], %[[str_val]]) : (!cir.ptr<!s8i>, !cir.ptr<!s8i>) -> !s32i +// CIR: %[[printf_result2:.+]] = cir.call @printf(%[[str_fmt_ptr]], %[[str_val]]) nothrow : (!cir.ptr<!s8i>, !cir.ptr<!s8i>) -> !s32i // CIR: %[[full_fmt_global:.+]] = cir.get_global @".str.1" : !cir.ptr<!cir.array<!s8i x 7>> // CIR: %[[full_fmt_ptr:.+]] = cir.cast(array_to_ptrdecay, %[[full_fmt_global]] : !cir.ptr<!cir.array<!s8i x 7>>), !cir.ptr<!s8i> // CIR: %[[str_val2:.+]] = cir.load{{.*}} %[[str_ptr]] : !cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!s8i> // CIR: %[[i_val:.+]] = cir.load{{.*}} %[[i_ptr]] : !cir.ptr<!s32i>, !s32i -// CIR: %[[printf_result3:.+]] = cir.call @printf(%[[full_fmt_ptr]], %[[str_val2]], %[[i_val]]) : (!cir.ptr<!s8i>, !cir.ptr<!s8i>, !s32i) -> !s32i +// CIR: %[[printf_result3:.+]] = cir.call @printf(%[[full_fmt_ptr]], %[[str_val2]], %[[i_val]]) nothrow : (!cir.ptr<!s8i>, !cir.ptr<!s8i>, !s32i) -> !s32i // CIR: cir.return // LLVM: define{{.*}} void @_Z4funcPKci(ptr %[[arg0:.+]], i32 %[[arg1:.+]]) diff --git a/clang/test/CIR/CodeGen/call.cpp b/clang/test/CIR/CodeGen/call.cpp index f7653ed7a572b..43e5d150a949f 100644 --- a/clang/test/CIR/CodeGen/call.cpp +++ b/clang/test/CIR/CodeGen/call.cpp @@ -102,3 +102,18 @@ void f12() { // LLVM: %[[#slot:]] = alloca %struct.S, i64 1, align 4 // LLVM-NEXT: %[[#ret:]] = call %struct.S @_Z3f10v() // LLVM-NEXT: store %struct.S %[[#ret]], ptr %[[#slot]], align 4 + +void f13() noexcept; +void f14() { + f13(); +} + +// CIR-LABEL: cir.func{{.+}} @_Z3f14v() +// CIR: cir.call @_Z3f13v() nothrow : () -> () +// CIR: } + +// LLVM-LABEL: define{{.+}} void @_Z3f14v() +// LLVM: call void @_Z3f13v() #[[LLVM_ATTR_0:.+]] +// LLVM: } + +// LLLVM: attributes #[[LLVM_ATTR_0]] = { nounwind } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits