From ba5dcb9fe99b08b741438dc754d5692b81ab2828 Mon Sep 17 00:00:00 2001 From: Rory Shu Date: Tue, 21 May 2024 01:56:51 -0700 Subject: [PATCH 1/2] [CIR] Add ExtraFuncAttr to CallOp and TryCalOp --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 0a2dca2a27b3..4c5046e8f6e7 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2785,6 +2785,7 @@ class CIR_CallOp extra_traits = []> : dag commonArgs = (ins OptionalAttr:$callee, Variadic:$arg_ops, + ExtraFuncAttr:$extra_attrs, OptionalAttr:$ast ); } From 26991eacebda5cc01d3e3ece7d0d4f4915f449b6 Mon Sep 17 00:00:00 2001 From: Rory Shu Date: Wed, 29 May 2024 01:41:25 -0700 Subject: [PATCH 2/2] [CIR] Pass in ExtraFuncAttrs to CallOp and TryCallOp --- .../CIR/Dialect/Builder/CIRBaseBuilder.h | 51 +++++++++++++++++++ clang/include/clang/CIR/Dialect/IR/CIROps.td | 24 +++------ clang/lib/CIR/CodeGen/CIRGenCall.cpp | 32 +++++++----- clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp | 13 +++-- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 4 +- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 39 ++++++++++++-- .../Dialect/Transforms/LoweringPrepare.cpp | 25 +++++---- .../TargetLowering/LowerFunction.cpp | 5 +- .../Targets/LoweringPrepareItaniumCXXABI.cpp | 6 +-- clang/test/CIR/CodeGen/call-extra-attrs.cpp | 34 +++++++++++++ 10 files changed, 173 insertions(+), 60 deletions(-) create mode 100644 clang/test/CIR/CodeGen/call-extra-attrs.cpp diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 9420b24e42e0..cb7bb85617f5 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -415,6 +415,57 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { mlir::ValueRange value = {}) { return create(loc, value); } + + mlir::cir::CallOp + createCallOp(mlir::Location loc, + mlir::SymbolRefAttr callee = mlir::SymbolRefAttr(), + mlir::Type returnType = mlir::cir::VoidType(), + mlir::ValueRange operands = mlir::ValueRange(), + mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) { + + mlir::cir::CallOp callOp = + create(loc, callee, returnType, operands); + + if (extraFnAttr) { + callOp->setAttr("extra_attrs", extraFnAttr); + } else { + mlir::NamedAttrList empty; + callOp->setAttr("extra_attrs", + mlir::cir::ExtraFuncAttributesAttr::get( + getContext(), empty.getDictionary(getContext()))); + } + return callOp; + } + + mlir::cir::CallOp + createCallOp(mlir::Location loc, mlir::cir::FuncOp callee, + mlir::ValueRange operands = mlir::ValueRange(), + mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) { + return createCallOp(loc, mlir::SymbolRefAttr::get(callee), + callee.getFunctionType().getReturnType(), operands, + extraFnAttr); + } + + mlir::cir::CallOp + createIndirectCallOp(mlir::Location loc, mlir::Value ind_target, + mlir::cir::FuncType fn_type, + mlir::ValueRange operands = mlir::ValueRange(), + mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) { + + llvm::SmallVector resOperands({ind_target}); + resOperands.append(operands.begin(), operands.end()); + + return createCallOp(loc, mlir::SymbolRefAttr(), fn_type.getReturnType(), + resOperands, extraFnAttr); + } + + mlir::cir::CallOp + createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, + mlir::ValueRange operands = mlir::ValueRange(), + mlir::cir::ExtraFuncAttributesAttr extraFnAttr = {}) { + return createCallOp(loc, callee, mlir::cir::VoidType(), operands, + extraFnAttr); + } }; } // namespace cir diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 4c5046e8f6e7..a287464b8eb0 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2821,12 +2821,16 @@ def CallOp : CIR_CallOp<"call"> { let arguments = commonArgs; let results = (outs Optional:$result); + let skipDefaultBuilders = 1; + let builders = [ - OpBuilder<(ins "FuncOp":$callee, CArg<"ValueRange", "{}">:$operands), [{ + OpBuilder<(ins "SymbolRefAttr":$callee, "mlir::Type":$resType, + CArg<"ValueRange", "{}">:$operands), [{ $_state.addOperands(operands); - $_state.addAttribute("callee", SymbolRefAttr::get(callee)); - if (!callee.getFunctionType().isVoid()) - $_state.addTypes(callee.getFunctionType().getReturnType()); + if (callee) + $_state.addAttribute("callee", callee); + if (resType && !resType.isa()) + $_state.addTypes(resType); }]>, OpBuilder<(ins "Value":$ind_target, "FuncType":$fn_type, @@ -2835,18 +2839,6 @@ def CallOp : CIR_CallOp<"call"> { $_state.addOperands(operands); if (!fn_type.isVoid()) $_state.addTypes(fn_type.getReturnType()); - }]>, - OpBuilder<(ins "SymbolRefAttr":$callee, "mlir::Type":$resType, - CArg<"ValueRange", "{}">:$operands), [{ - $_state.addOperands(operands); - $_state.addAttribute("callee", callee); - if (resType && !resType.isa()) - $_state.addTypes(resType); - }]>, - OpBuilder<(ins "SymbolRefAttr":$callee, - CArg<"ValueRange", "{}">:$operands), [{ - $_state.addOperands(operands); - $_state.addAttribute("callee", callee); }]> ]; } diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 60268b72d9dd..bf44ddb263b7 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -447,22 +447,29 @@ static mlir::cir::CIRCallOpInterface buildCallLikeOp(CIRGenFunction &CGF, mlir::Location callLoc, mlir::cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal, mlir::cir::FuncOp directFuncOp, - SmallVectorImpl &CIRCallArgs, bool InvokeDest) { + SmallVectorImpl &CIRCallArgs, bool InvokeDest, + mlir::cir::ExtraFuncAttributesAttr extraFnAttrs) { auto &builder = CGF.getBuilder(); if (InvokeDest) { auto addr = CGF.currLexScope->getExceptionInfo().addr; - if (indirectFuncTy) - return builder.create( + + mlir::cir::TryCallOp tryCallOp; + if (indirectFuncTy) { + tryCallOp = builder.create( callLoc, addr, indirectFuncVal, indirectFuncTy, CIRCallArgs); - return builder.create(callLoc, directFuncOp, addr, - CIRCallArgs); + } else { + tryCallOp = builder.create(callLoc, directFuncOp, + addr, CIRCallArgs); + } + tryCallOp->setAttr("extra_attrs", extraFnAttrs); + return tryCallOp; } if (indirectFuncTy) - return builder.create(callLoc, indirectFuncVal, - indirectFuncTy, CIRCallArgs); - return builder.create(callLoc, directFuncOp, CIRCallArgs); + return builder.createIndirectCallOp( + callLoc, indirectFuncVal, indirectFuncTy, CIRCallArgs, extraFnAttrs); + return builder.createCallOp(callLoc, directFuncOp, CIRCallArgs, extraFnAttrs); } RValue CIRGenFunction::buildCall(const CIRGenFunctionInfo &CallInfo, @@ -735,9 +742,10 @@ RValue CIRGenFunction::buildCall(const CIRGenFunctionInfo &CallInfo, indirectFuncVal = CalleePtr->getResult(0); } - mlir::cir::CIRCallOpInterface callLikeOp = - buildCallLikeOp(*this, callLoc, indirectFuncTy, indirectFuncVal, - directFuncOp, CIRCallArgs, InvokeDest); + mlir::cir::CIRCallOpInterface callLikeOp = buildCallLikeOp( + *this, callLoc, indirectFuncTy, indirectFuncVal, directFuncOp, + CIRCallArgs, InvokeDest, + mlir::cir::ExtraFuncAttributesAttr::get(builder.getContext(), Attrs)); if (E) callLikeOp->setAttr( @@ -844,7 +852,7 @@ mlir::Value CIRGenFunction::buildRuntimeCall(mlir::Location loc, // TODO(cir): set the calling convention to this runtime call. assert(!MissingFeatures::setCallingConv()); - auto call = builder.create(loc, callee, args); + auto call = builder.createCallOp(loc, callee, args); assert(call->getNumResults() <= 1 && "runtime functions have at most 1 result"); diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp index 560335765ef6..362f1ee5fcb3 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp @@ -179,10 +179,9 @@ mlir::cir::CallOp CIRGenFunction::buildCoroIDBuiltinCall(mlir::Location loc, } else fnOp = cast(builtin); - return builder.create( - loc, fnOp, - mlir::ValueRange{builder.getUInt32(NewAlign, loc), nullPtr, nullPtr, - nullPtr}); + return builder.createCallOp(loc, fnOp, + mlir::ValueRange{builder.getUInt32(NewAlign, loc), + nullPtr, nullPtr, nullPtr}); } mlir::cir::CallOp @@ -202,7 +201,7 @@ CIRGenFunction::buildCoroAllocBuiltinCall(mlir::Location loc) { } else fnOp = cast(builtin); - return builder.create( + return builder.createCallOp( loc, fnOp, mlir::ValueRange{CurCoro.Data->CoroId.getResult()}); } @@ -223,7 +222,7 @@ CIRGenFunction::buildCoroBeginBuiltinCall(mlir::Location loc, } else fnOp = cast(builtin); - return builder.create( + return builder.createCallOp( loc, fnOp, mlir::ValueRange{CurCoro.Data->CoroId.getResult(), coroframeAddr}); } @@ -244,7 +243,7 @@ mlir::cir::CallOp CIRGenFunction::buildCoroEndBuiltinCall(mlir::Location loc, } else fnOp = cast(builtin); - return builder.create( + return builder.createCallOp( loc, fnOp, mlir::ValueRange{nullPtr, builder.getBool(false, loc)}); } diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index f570b04b0644..df46db693c04 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -1717,8 +1717,8 @@ void CIRGenModule::ReplaceUsesOfNonProtoTypeWithRealFunction( builder.setInsertionPoint(noProtoCallOp); // Patch call type with the real function type. - auto realCallOp = builder.create( - noProtoCallOp.getLoc(), NewFn, noProtoCallOp.getOperands()); + auto realCallOp = builder.createCallOp(noProtoCallOp.getLoc(), NewFn, + noProtoCallOp.getOperands()); // Replace old no proto call with fixed call. noProtoCallOp.replaceAllUsesWith(realCallOp); diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 9847bafe8b84..6ca73ef64dc6 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2310,6 +2310,7 @@ verifyCallCommInSymbolUses(Operation *op, SymbolTableCollection &symbolTable) { static ::mlir::ParseResult parseCallCommon( ::mlir::OpAsmParser &parser, ::mlir::OperationState &result, + llvm::StringRef extraAttrsAttrName, llvm::function_ref<::mlir::ParseResult(::mlir::OpAsmParser &, ::mlir::OperationState &)> customOpHandler = @@ -2344,6 +2345,23 @@ static ::mlir::ParseResult parseCallCommon( return ::mlir::failure(); if (parser.parseRParen()) return ::mlir::failure(); + + auto &builder = parser.getBuilder(); + Attribute extraAttrs; + if (::mlir::succeeded(parser.parseOptionalKeyword("extra"))) { + if (parser.parseLParen().failed()) + return failure(); + if (parser.parseAttribute(extraAttrs).failed()) + return failure(); + if (parser.parseRParen().failed()) + return failure(); + } else { + NamedAttrList empty; + extraAttrs = mlir::cir::ExtraFuncAttributesAttr::get( + builder.getContext(), empty.getDictionary(builder.getContext())); + } + result.addAttribute(extraAttrsAttrName, extraAttrs); + if (parser.parseOptionalAttrDict(result.attributes)) return ::mlir::failure(); if (parser.parseColon()) @@ -2364,6 +2382,7 @@ static ::mlir::ParseResult parseCallCommon( void printCallCommon( Operation *op, mlir::Value indirectCallee, mlir::FlatSymbolRefAttr flatSym, ::mlir::OpAsmPrinter &state, + ::mlir::cir::ExtraFuncAttributesAttr extraAttrs, llvm::function_ref customOpHandler = []() {}) { state << ' '; @@ -2379,13 +2398,20 @@ void printCallCommon( state << "("; state << ops; state << ")"; - llvm::SmallVector<::llvm::StringRef, 2> elidedAttrs; + + llvm::SmallVector<::llvm::StringRef, 4> elidedAttrs; elidedAttrs.push_back("callee"); elidedAttrs.push_back("ast"); + elidedAttrs.push_back("extra_attrs"); state.printOptionalAttrDict(op->getAttrs(), elidedAttrs); state << ' ' << ":"; state << ' '; state.printFunctionalType(op->getOperands().getTypes(), op->getResultTypes()); + if (!extraAttrs.getElements().empty()) { + state << " extra("; + state.printAttributeWithoutType(extraAttrs); + state << ")"; + } } LogicalResult @@ -2395,12 +2421,14 @@ cir::CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) { ::mlir::ParseResult CallOp::parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result) { - return parseCallCommon(parser, result); + + return parseCallCommon(parser, result, getExtraAttrsAttrName(result.name)); } void CallOp::print(::mlir::OpAsmPrinter &state) { mlir::Value indirectCallee = isIndirect() ? getIndirectCall() : nullptr; - printCallCommon(*this, indirectCallee, getCalleeAttr(), state); + printCallCommon(*this, indirectCallee, getCalleeAttr(), state, + getExtraAttrs()); } //===----------------------------------------------------------------------===// @@ -2457,7 +2485,7 @@ LogicalResult cir::TryCallOp::verify() { return mlir::success(); } ::mlir::ParseResult TryCallOp::parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result) { return parseCallCommon( - parser, result, + parser, result, getExtraAttrsAttrName(result.name), [](::mlir::OpAsmParser &parser, ::mlir::OperationState &result) -> ::mlir::ParseResult { ::mlir::OpAsmParser::UnresolvedOperand exceptionRawOperands[1]; @@ -2499,7 +2527,8 @@ void TryCallOp::print(::mlir::OpAsmPrinter &state) { state << getExceptionInfo(); state << ")"; mlir::Value indirectCallee = isIndirect() ? getIndirectCall() : nullptr; - printCallCommon(*this, indirectCallee, getCalleeAttr(), state); + printCallCommon(*this, indirectCallee, getCalleeAttr(), state, + getExtraAttrs()); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 02b54c5a9962..f7643c9b8016 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -195,7 +195,7 @@ FuncOp LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(GlobalOp op) { } // Create a variable initialization function. - mlir::OpBuilder builder(&getContext()); + CIRBaseBuilderTy builder(getContext()); builder.setInsertionPointAfter(op); auto voidTy = ::mlir::cir::VoidType::get(builder.getContext()); auto fnType = mlir::cir::FuncType::get({}, voidTy); @@ -264,7 +264,7 @@ FuncOp LoweringPreparePass::buildCXXGlobalVarDeclInitFunc(GlobalOp op) { dtorCall.getArgOperand(0)); args[2] = builder.create( Handle.getLoc(), HandlePtrTy, Handle.getSymName()); - builder.create(dtorCall.getLoc(), fnAtExit, args); + builder.createCallOp(dtorCall.getLoc(), fnAtExit, args); dtorCall->erase(); entryBB->getOperations().splice(entryBB->end(), dtorBlock.getOperations(), dtorBlock.begin(), @@ -481,7 +481,7 @@ void LoweringPreparePass::buildCXXGlobalInitFunc() { fnName += getTransformedFileName(theModule); } - mlir::OpBuilder builder(&getContext()); + CIRBaseBuilderTy builder(getContext()); builder.setInsertionPointToEnd(&theModule.getBodyRegion().back()); auto fnType = mlir::cir::FuncType::get( {}, mlir::cir::VoidType::get(builder.getContext())); @@ -490,7 +490,7 @@ void LoweringPreparePass::buildCXXGlobalInitFunc() { mlir::cir::GlobalLinkageKind::ExternalLinkage); builder.setInsertionPointToStart(f.addEntryBlock()); for (auto &f : dynamicInitializers) { - builder.create(f.getLoc(), f); + builder.createCallOp(f.getLoc(), f); } builder.create(f.getLoc()); @@ -597,7 +597,7 @@ void LoweringPreparePass::lowerArrayCtor(ArrayCtor op) { void LoweringPreparePass::lowerStdFindOp(StdFindOp op) { CIRBaseBuilderTy builder(getContext()); builder.setInsertionPointAfter(op.getOperation()); - auto call = builder.create( + auto call = builder.createCallOp( op.getLoc(), op.getOriginalFnAttr(), op.getResult().getType(), mlir::ValueRange{op.getOperand(0), op.getOperand(1), op.getOperand(2)}); @@ -608,9 +608,9 @@ void LoweringPreparePass::lowerStdFindOp(StdFindOp op) { void LoweringPreparePass::lowerIterBeginOp(IterBeginOp op) { CIRBaseBuilderTy builder(getContext()); builder.setInsertionPointAfter(op.getOperation()); - auto call = builder.create( - op.getLoc(), op.getOriginalFnAttr(), op.getResult().getType(), - mlir::ValueRange{op.getOperand()}); + auto call = builder.createCallOp(op.getLoc(), op.getOriginalFnAttr(), + op.getResult().getType(), + mlir::ValueRange{op.getOperand()}); op.replaceAllUsesWith(call); op.erase(); @@ -619,9 +619,9 @@ void LoweringPreparePass::lowerIterBeginOp(IterBeginOp op) { void LoweringPreparePass::lowerIterEndOp(IterEndOp op) { CIRBaseBuilderTy builder(getContext()); builder.setInsertionPointAfter(op.getOperation()); - auto call = builder.create( - op.getLoc(), op.getOriginalFnAttr(), op.getResult().getType(), - mlir::ValueRange{op.getOperand()}); + auto call = builder.createCallOp(op.getLoc(), op.getOriginalFnAttr(), + op.getResult().getType(), + mlir::ValueRange{op.getOperand()}); op.replaceAllUsesWith(call); op.erase(); @@ -712,8 +712,7 @@ void LoweringPreparePass::runOnMathOp(Operation *op) { buildRuntimeFunction(builder, rtFuncName, op->getLoc(), rtFuncTy); builder.setInsertionPointAfter(op); - auto call = builder.create(op->getLoc(), rtFunc, - op->getOperands()); + auto call = builder.createCallOp(op->getLoc(), rtFunc, op->getOperands()); op->replaceAllUsesWith(call); op->erase(); diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp index edf4dfc7d4b3..4d4e2d4f3ba6 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp @@ -317,8 +317,9 @@ Value LowerFunction::rewriteCallOp(const LowerFunctionInfo &CallInfo, // NOTE(cir): We don't know if the callee was already lowered, so we only // fetch the name from the callee, while the return type is fetch from the // lowering types manager. - CallOp _ = rewriter.create(loc, Caller.getCalleeAttr(), - IRFuncTy.getReturnType(), IRCallArgs); + CallOp callOp = rewriter.create(loc, Caller.getCalleeAttr(), + IRFuncTy.getReturnType(), IRCallArgs); + callOp.setExtraAttrsAttr(Caller.getExtraAttrs()); assert(!::cir::MissingFeatures::vectorType()); diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/LoweringPrepareItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/LoweringPrepareItaniumCXXABI.cpp index 83235f50ffee..ebbcfab0f573 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/LoweringPrepareItaniumCXXABI.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/LoweringPrepareItaniumCXXABI.cpp @@ -36,7 +36,7 @@ static void buildBadCastCall(CIRBaseBuilderTy &builder, mlir::Location loc, // TODO(cir): set the calling convention to __cxa_bad_cast. assert(!MissingFeatures::setCallingConv()); - builder.create(loc, badCastFuncRef, mlir::ValueRange{}); + builder.createCallOp(loc, badCastFuncRef, mlir::ValueRange{}); builder.create(loc); builder.clearInsertionPoint(); } @@ -62,8 +62,8 @@ static mlir::Value buildDynamicCastAfterNullCheck(CIRBaseBuilderTy &builder, assert(!MissingFeatures::setCallingConv()); mlir::Value castedPtr = builder - .create(loc, dynCastFuncRef, - builder.getVoidPtrTy(), dynCastFuncArgs) + .createCallOp(loc, dynCastFuncRef, builder.getVoidPtrTy(), + dynCastFuncArgs) .getResult(); assert(castedPtr.getType().isa() && diff --git a/clang/test/CIR/CodeGen/call-extra-attrs.cpp b/clang/test/CIR/CodeGen/call-extra-attrs.cpp new file mode 100644 index 000000000000..a17246ddb1b5 --- /dev/null +++ b/clang/test/CIR/CodeGen/call-extra-attrs.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -std=c++20 -triple aarch64-none-linux-android21 -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s + +__attribute__((nothrow)) +int s0(int a, int b) { + int x = a + b; + return x; +} + +__attribute__((noinline)) +int s1(int a, int b) { + return s0(a,b); +} + +int s2(int a, int b) { + return s1(a, b); +} + +// CIR: #fn_attr = #cir, nothrow = #cir.nothrow, optnone = #cir.optnone})> +// CIR: #fn_attr1 = #cir + +// CIR: cir.func @_Z2s0ii(%{{.*}}, %{{.*}}) -> {{.*}} extra(#fn_attr) +// CIR: cir.func @_Z2s1ii(%{{.*}}, %{{.*}}) -> {{.*}} extra(#fn_attr) +// CIR: cir.call @_Z2s0ii(%{{.*}}, %{{.*}}) : ({{.*}}, {{.*}}) -> {{.*}} extra(#fn_attr1) +// CIR: cir.func @_Z2s2ii(%{{.*}}, %{{.*}}) -> {{.*}} extra(#fn_attr) +// CHECK-NOT: cir.call @_Z2s1ii(%{{.*}}, %{{.*}}) : ({{.*}}, {{.*}}) -> {{.*}} extra(#fn_attr{{.*}}) + +// LLVM: define i32 @_Z2s0ii(i32 %0, i32 %1) #[[#ATTR1:]] +// LLVM: define i32 @_Z2s1ii(i32 %0, i32 %1) #[[#ATTR1:]] +// LLVM: define i32 @_Z2s2ii(i32 %0, i32 %1) #[[#ATTR1:]] + +// LLVM: attributes #[[#ATTR1]] = {{.*}} noinline nounwind optnone