Author: Erich Keane
Date: 2026-01-28T06:06:56-08:00
New Revision: 6682681fd2d79a2b1fc76a07605e580e0146daba

URL: 
https://github.com/llvm/llvm-project/commit/6682681fd2d79a2b1fc76a07605e580e0146daba
DIFF: 
https://github.com/llvm/llvm-project/commit/6682681fd2d79a2b1fc76a07605e580e0146daba.diff

LOG: [CIR] Implement returns_twice, cold, hot, noduplicate, convergent func 
attrs (#178289)

Continuing my quest to get most of the attributes completed, this patch
implements 5 attributes for CIR/Clang CIR codegen.

4 of the 5 are also implemented in LLVM-MLIR, since 'convergent' was
already there.

As a part of this, we also had to make sure that attributes were handled
properly for Call operation lowering, like we do for function
attributes.

Added: 
    clang/test/CIR/CodeGen/misc-attrs.cpp

Modified: 
    clang/include/clang/CIR/Dialect/IR/CIRDialect.td
    clang/lib/CIR/CodeGen/CIRGenCall.cpp
    clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
    mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
    mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
    mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
    mlir/lib/Target/LLVMIR/ModuleImport.cpp
    mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
    mlir/test/Dialect/LLVMIR/func.mlir
    mlir/test/Dialect/LLVMIR/roundtrip.mlir
    mlir/test/Target/LLVMIR/Import/function-attributes.ll
    mlir/test/Target/LLVMIR/Import/instructions.ll
    mlir/test/Target/LLVMIR/llvmir.mlir

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index 47ca625c34816..31cebdde1aa64 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -41,6 +41,12 @@ def CIR_Dialect : Dialect {
     static llvm::StringRef getNoThrowAttrName() { return "nothrow"; }
     static llvm::StringRef getNoReturnAttrName() { return "noreturn"; }
     static llvm::StringRef getSideEffectAttrName() { return "side_effect"; }
+    static llvm::StringRef getReturnsTwiceAttrName() { return "returns_twice"; 
}
+    static llvm::StringRef getColdAttrName() { return "cold"; }
+    static llvm::StringRef getHotAttrName() { return "hot"; }
+    static llvm::StringRef getNoDuplicatesAttrName() { return "noduplicate"; }
+    static llvm::StringRef getConvergentAttrName() { return "convergent"; }
+    static llvm::StringRef getNoUnwindAttrName() { return "nounwind"; }
     static llvm::StringRef getModuleLevelAsmAttrName() { return 
"cir.module_asm"; }
     static llvm::StringRef getGlobalCtorsAttrName() { return 
"cir.global_ctors"; }
     static llvm::StringRef getGlobalDtorsAttrName() { return 
"cir.global_dtors"; }

diff  --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index a7680d3b9e823..83b1c4e78c4d6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -122,9 +122,13 @@ void CIRGenModule::constructAttributeList(llvm::StringRef 
name,
   assert(!cir::MissingFeatures::opCallCallConv());
   sideEffect = cir::SideEffect::All;
 
+  auto addUnitAttr = [&](llvm::StringRef name) {
+    attrs.set(name, mlir::UnitAttr::get(&getMLIRContext()));
+  };
+
   if (info.isNoReturn())
-    attrs.set(cir::CIRDialect::getNoReturnAttrName(),
-              mlir::UnitAttr::get(&getMLIRContext()));
+    addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
+
   // TODO(cir): Check/add cmse_nonsecure_call attribute here.
 
   addAttributesFromFunctionProtoType(getBuilder(), attrs,
@@ -134,15 +138,23 @@ void CIRGenModule::constructAttributeList(llvm::StringRef 
name,
 
   if (targetDecl) {
     if (targetDecl->hasAttr<NoThrowAttr>())
-      attrs.set(cir::CIRDialect::getNoThrowAttrName(),
-                mlir::UnitAttr::get(&getMLIRContext()));
+      addUnitAttr(cir::CIRDialect::getNoThrowAttrName());
     // TODO(cir): This is actually only possible if targetDecl isn't a
     // declarator, which ObjCMethodDecl seems to be the only way to get this to
     // happen.  We're including it here for completeness, but we should add a
     // test for this when we start generating ObjectiveC.
     if (targetDecl->hasAttr<NoReturnAttr>())
-      attrs.set(cir::CIRDialect::getNoReturnAttrName(),
-                mlir::UnitAttr::get(&getMLIRContext()));
+      addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
+    if (targetDecl->hasAttr<ReturnsTwiceAttr>())
+      addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
+    if (targetDecl->hasAttr<ColdAttr>())
+      addUnitAttr(cir::CIRDialect::getColdAttrName());
+    if (targetDecl->hasAttr<HotAttr>())
+      addUnitAttr(cir::CIRDialect::getHotAttrName());
+    if (targetDecl->hasAttr<NoDuplicateAttr>())
+      addUnitAttr(cir::CIRDialect::getNoDuplicatesAttrName());
+    if (targetDecl->hasAttr<ConvergentAttr>())
+      addUnitAttr(cir::CIRDialect::getConvergentAttrName());
 
     if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
       addAttributesFromFunctionProtoType(

diff  --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 1894e92a485cd..091489c404642 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1606,6 +1606,22 @@ mlir::LogicalResult 
CIRToLLVMRotateOpLowering::matchAndRewrite(
   return mlir::LogicalResult::success();
 }
 
+static void lowerCallAttributes(cir::CIRCallOpInterface op,
+                                SmallVectorImpl<mlir::NamedAttribute> &result) 
{
+  for (mlir::NamedAttribute attr : op->getAttrs()) {
+    assert(!cir::MissingFeatures::opFuncCallingConv());
+    if (attr.getName() == CIRDialect::getCalleeAttrName() ||
+        attr.getName() == CIRDialect::getSideEffectAttrName() ||
+        attr.getName() == CIRDialect::getNoThrowAttrName() ||
+        attr.getName() == CIRDialect::getNoUnwindAttrName() ||
+        attr.getName() == CIRDialect::getNoReturnAttrName())
+      continue;
+
+    assert(!cir::MissingFeatures::opFuncExtraAttrs());
+    result.push_back(attr);
+  }
+}
+
 static mlir::LogicalResult
 rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange callOperands,
                     mlir::ConversionPatternRewriter &rewriter,
@@ -1627,6 +1643,9 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange 
callOperands,
   convertSideEffectForCall(op, call.getNothrow(), call.getSideEffect(),
                            memoryEffects, noUnwind, willReturn, noReturn);
 
+  SmallVector<mlir::NamedAttribute, 4> attributes;
+  lowerCallAttributes(call, attributes);
+
   mlir::LLVM::LLVMFunctionType llvmFnTy;
 
   // Temporary to handle the case where we need to prepend an operand if the
@@ -1684,6 +1703,7 @@ rewriteCallOrInvoke(mlir::Operation *op, mlir::ValueRange 
callOperands,
 
   auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
       op, llvmFnTy, calleeAttr, callOperands);
+  newOp->setAttrs(attributes);
   if (memoryEffects)
     newOp.setMemoryEffectsAttr(memoryEffects);
   newOp.setNoUnwind(noUnwind);

diff  --git a/clang/test/CIR/CodeGen/misc-attrs.cpp 
b/clang/test/CIR/CodeGen/misc-attrs.cpp
new file mode 100644
index 0000000000000..837f99275c70d
--- /dev/null
+++ b/clang/test/CIR/CodeGen/misc-attrs.cpp
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -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 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+
+extern "C" {
+  // CIR: cir.func{{.*}}@returns_twice() attributes {returns_twice} {
+  // LLVM: Function Attrs:{{.*}}returns_twice
+  // LLVM-NEXT: define{{.*}}@returns_twice() #[[RT_ATTR:.*]] {
+  __attribute__((returns_twice))
+  void returns_twice() {}
+  // CIR: cir.func{{.*}}@cold() attributes {cold} {
+  // LLVM: Function Attrs:{{.*}}cold
+  // LLVM-NEXT: define{{.*}}@cold() #[[COLD_ATTR:.*]] {
+  __attribute__((cold))
+  void cold() {}
+  // CIR: cir.func{{.*}}@hot() attributes {hot} {
+  // LLVM: Function Attrs:{{.*}}hot
+  // LLVM-NEXT: define{{.*}}@hot() #[[HOT_ATTR:.*]] {
+  __attribute__((hot))
+  void hot() {}
+  // CIR: cir.func{{.*}}@nodupes() attributes {noduplicate} {
+  // LLVM: Function Attrs:{{.*}}noduplicate
+  // LLVM-NEXT: define{{.*}}@nodupes() #[[ND_ATTR:.*]] {
+  __attribute__((noduplicate))
+  void nodupes() {}
+  // CIR: cir.func{{.*}}@convergent() attributes {convergent} {
+  // LLVM: Function Attrs:{{.*}}convergent
+  // LLVM-NEXT: define{{.*}}@convergent() #[[CONV_ATTR:.*]] {
+  __attribute__((convergent))
+  void convergent() {}
+
+  void caller() {
+  // CIR: cir.call @returns_twice() {returns_twice} : () -> ()
+  // LLVM: call void @returns_twice() #[[RT_CALL_ATTR:.*]]
+    returns_twice();
+  // CIR: cir.call @cold() {cold} : () -> ()
+  // LLVM: call void @cold() #[[COLD_CALL_ATTR:.*]]
+    cold();
+  // CIR: cir.call @hot() {hot} : () -> ()
+  // LLVM: call void @hot() #[[HOT_CALL_ATTR:.*]]
+    hot();
+  // CIR: cir.call @nodupes() {noduplicate} : () -> ()
+  // LLVM: call void @nodupes() #[[ND_CALL_ATTR:.*]]
+    nodupes();
+  // CIR: cir.call @convergent() {convergent} : () -> ()
+  // LLVM: call void @convergent() #[[CONV_CALL_ATTR:.*]]
+    convergent();
+  }
+}
+
+// LLVM: attributes #[[RT_ATTR]] = {{.*}}returns_twice
+// LLVM: attributes #[[COLD_ATTR]] = {{.*}}cold
+// LLVM: attributes #[[HOT_ATTR]] = {{.*}}hot
+// LLVM: attributes #[[ND_ATTR]] = {{.*}}noduplicate
+// LLVM: attributes #[[CONV_ATTR]] = {{.*}}convergent
+// LLVM: attributes #[[RT_CALL_ATTR]] = {{.*}}returns_twice
+// LLVM: attributes #[[COLD_CALL_ATTR]] = {{.*}}cold
+// LLVM: attributes #[[HOT_CALL_ATTR]] = {{.*}}hot
+// LLVM: attributes #[[ND_CALL_ATTR]] = {{.*}}noduplicate
+// LLVM: attributes #[[CONV_CALL_ATTR]] = {{.*}}convergent

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td 
b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 390d5a1ea7dfe..f6f1c90b481c5 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -795,7 +795,8 @@ def LLVM_CallOp
       DefaultValuedAttr<TailCallKind, "TailCallKind::None">:$TailCallKind,
       OptionalAttr<LLVM_MemoryEffectsAttr>:$memory_effects,
       UnitAttr:$convergent, UnitAttr:$no_unwind, UnitAttr:$will_return,
-      UnitAttr:$noreturn,
+      UnitAttr:$noreturn, UnitAttr:$returns_twice, UnitAttr:$hot,
+      UnitAttr:$cold, UnitAttr:$noduplicate,
       VariadicOfVariadic<LLVM_Type, "op_bundle_sizes">:$op_bundle_operands,
       DenseI32ArrayAttr:$op_bundle_sizes,
       OptionalAttr<ArrayAttr>:$op_bundle_tags,
@@ -1995,6 +1996,10 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
     OptionalAttr<UnitAttr>:$will_return,
     OptionalAttr<UnitAttr>:$noreturn,
     OptionalAttr<UnitAttr>:$optimize_none,
+    OptionalAttr<UnitAttr>:$returns_twice,
+    OptionalAttr<UnitAttr>:$hot,
+    OptionalAttr<UnitAttr>:$cold,
+    OptionalAttr<UnitAttr>:$noduplicate,
     OptionalAttr<LLVM_VecTypeHintAttr>:$vec_type_hint,
     OptionalAttr<DenseI32ArrayAttr>:$work_group_size_hint,
     OptionalAttr<DenseI32ArrayAttr>:$reqd_work_group_size,

diff  --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp 
b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index d1c45bcb1656b..27d6355c9e221 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -995,7 +995,8 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state, TypeRange results,
         /*CConv=*/nullptr, /*TailCallKind=*/nullptr,
         /*memory_effects=*/nullptr,
         /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
-        /*noreturn=*/nullptr,
+        /*noreturn=*/nullptr, /*returns_twice=*/nullptr, /*hot=*/nullptr,
+        /*cold=*/nullptr, /*noduplicate=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
         /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
@@ -1027,6 +1028,8 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state,
         /*convergent=*/nullptr,
         /*no_unwind=*/nullptr, /*will_return=*/nullptr,
         /*noreturn=*/nullptr,
+        /*returns_twice=*/nullptr, /*hot=*/nullptr,
+        /*cold=*/nullptr, /*noduplicate=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
         /*access_groups=*/nullptr,
@@ -1044,6 +1047,8 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state,
         /*CConv=*/nullptr, /*TailCallKind=*/nullptr, 
/*memory_effects=*/nullptr,
         /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
         /*noreturn=*/nullptr,
+        /*returns_twice=*/nullptr, /*hot=*/nullptr,
+        /*cold=*/nullptr, /*noduplicate=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,
         /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
@@ -1061,6 +1066,8 @@ void CallOp::build(OpBuilder &builder, OperationState 
&state, LLVMFuncOp func,
         /*CConv=*/nullptr, /*TailCallKind=*/nullptr, 
/*memory_effects=*/nullptr,
         /*convergent=*/nullptr, /*no_unwind=*/nullptr, /*will_return=*/nullptr,
         /*noreturn=*/nullptr,
+        /*returns_twice=*/nullptr, /*hot=*/nullptr,
+        /*cold=*/nullptr, /*noduplicate=*/nullptr,
         /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{},
         /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
         /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr,

diff  --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp 
b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index b1d7f3ab7b777..31636abfff27f 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -423,6 +423,14 @@ convertOperationImpl(Operation &opInst, 
llvm::IRBuilderBase &builder,
       call->addFnAttr(llvm::Attribute::WillReturn);
     if (callOp.getNoreturnAttr())
       call->addFnAttr(llvm::Attribute::NoReturn);
+    if (callOp.getReturnsTwiceAttr())
+      call->addFnAttr(llvm::Attribute::ReturnsTwice);
+    if (callOp.getColdAttr())
+      call->addFnAttr(llvm::Attribute::Cold);
+    if (callOp.getHotAttr())
+      call->addFnAttr(llvm::Attribute::Hot);
+    if (callOp.getNoduplicateAttr())
+      call->addFnAttr(llvm::Attribute::NoDuplicate);
     if (callOp.getNoInlineAttr())
       call->addFnAttr(llvm::Attribute::NoInline);
     if (callOp.getAlwaysInlineAttr())

diff  --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp 
b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 555e72bd77358..928e7a57ae24f 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -2653,11 +2653,13 @@ static constexpr std::array 
kExplicitLLVMFuncOpAttributes{
     StringLiteral("aarch64_pstate_sm_compatible"),
     StringLiteral("aarch64_pstate_sm_enabled"),
     StringLiteral("alwaysinline"),
+    StringLiteral("cold"),
     StringLiteral("convergent"),
     StringLiteral("denormal-fp-math"),
     StringLiteral("denormal-fp-math-f32"),
     StringLiteral("fp-contract"),
     StringLiteral("frame-pointer"),
+    StringLiteral("hot"),
     StringLiteral("inlinehint"),
     StringLiteral("instrument-function-entry"),
     StringLiteral("instrument-function-exit"),
@@ -2665,10 +2667,12 @@ static constexpr std::array 
kExplicitLLVMFuncOpAttributes{
     StringLiteral("no-infs-fp-math"),
     StringLiteral("no-nans-fp-math"),
     StringLiteral("no-signed-zeros-fp-math"),
+    StringLiteral("noduplicate"),
     StringLiteral("noinline"),
     StringLiteral("noreturn"),
     StringLiteral("nounwind"),
     StringLiteral("optnone"),
+    StringLiteral("returns_twice"),
     StringLiteral("target-features"),
     StringLiteral("tune-cpu"),
     StringLiteral("uwtable"),
@@ -2710,6 +2714,14 @@ void 
ModuleImport::processFunctionAttributes(llvm::Function *func,
     funcOp.setWillReturn(true);
   if (func->hasFnAttribute(llvm::Attribute::NoReturn))
     funcOp.setNoreturn(true);
+  if (func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
+    funcOp.setReturnsTwice(true);
+  if (func->hasFnAttribute(llvm::Attribute::Cold))
+    funcOp.setCold(true);
+  if (func->hasFnAttribute(llvm::Attribute::Hot))
+    funcOp.setHot(true);
+  if (func->hasFnAttribute(llvm::Attribute::NoDuplicate))
+    funcOp.setNoduplicate(true);
 
   if (func->hasFnAttribute("aarch64_pstate_sm_enabled"))
     funcOp.setArmStreaming(true);
@@ -2931,6 +2943,12 @@ LogicalResult 
ModuleImport::convertCallAttributes(llvm::CallInst *inst,
   op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
   op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
   op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
+  op.setReturnsTwice(
+      callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
+  op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
+  op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
+  op.setNoduplicate(
+      callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
   op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
   op.setAlwaysInline(
       callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());

diff  --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp 
b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 46a0b97f1edbd..79d65ffe4e551 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1670,6 +1670,14 @@ static void convertFunctionAttributes(LLVMFuncOp func,
     llvmFunc->addFnAttr(llvm::Attribute::InlineHint);
   if (func.getOptimizeNoneAttr())
     llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
+  if (func.getReturnsTwiceAttr())
+    llvmFunc->addFnAttr(llvm::Attribute::ReturnsTwice);
+  if (func.getColdAttr())
+    llvmFunc->addFnAttr(llvm::Attribute::Cold);
+  if (func.getHotAttr())
+    llvmFunc->addFnAttr(llvm::Attribute::Hot);
+  if (func.getNoduplicateAttr())
+    llvmFunc->addFnAttr(llvm::Attribute::NoDuplicate);
   if (func.getConvergentAttr())
     llvmFunc->addFnAttr(llvm::Attribute::Convergent);
   if (func.getNoUnwindAttr())

diff  --git a/mlir/test/Dialect/LLVMIR/func.mlir 
b/mlir/test/Dialect/LLVMIR/func.mlir
index 936260f862a98..a66087e431eee 100644
--- a/mlir/test/Dialect/LLVMIR/func.mlir
+++ b/mlir/test/Dialect/LLVMIR/func.mlir
@@ -330,6 +330,30 @@ module {
     llvm.return
   }
 
+  llvm.func @returnstwice_function() attributes {returnstwice} {
+    // CHECK: @returnstwice_function
+    // CHECK-SAME: attributes {returnstwice}
+    llvm.return
+  }
+
+  llvm.func @hot_function() attributes {hot} {
+    // CHECK: @hot_function
+    // CHECK-SAME: attributes {hot}
+    llvm.return
+  }
+
+  llvm.func @cold_function() attributes {cold} {
+    // CHECK: @cold_function
+    // CHECK-SAME: attributes {cold}
+    llvm.return
+  }
+
+  llvm.func @noduplicate_function() attributes {noduplicate} {
+    // CHECK: @noduplicate_function
+    // CHECK-SAME: attributes {noduplicate}
+    llvm.return
+  }
+
 }
 
 // -----

diff  --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir 
b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index fc2456b350a56..9ce45afd96c25 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -125,6 +125,18 @@ func.func @ops(%arg0: i32, %arg1: f32,
 // CHECK: llvm.call @baz() {noreturn} : () -> ()
   llvm.call @baz() {noreturn} : () -> ()
 
+// CHECK: llvm.call @baz() {returns_twice} : () -> ()
+  llvm.call @baz() {returns_twice} : () -> ()
+
+// CHECK: llvm.call @baz() {hot} : () -> ()
+  llvm.call @baz() {hot} : () -> ()
+
+// CHECK: llvm.call @baz() {cold} : () -> ()
+  llvm.call @baz() {cold} : () -> ()
+
+// CHECK: llvm.call @baz() {noduplicate} : () -> ()
+  llvm.call @baz() {noduplicate} : () -> ()
+
 // CHECK: llvm.call @baz() {memory = #llvm.memory_effects<other = none, argMem 
= read, inaccessibleMem = write, errnoMem = none, targetMem0 = none, targetMem1 
= none>} : () -> ()
   llvm.call @baz() {memory = #llvm.memory_effects<other = none, argMem = read, 
inaccessibleMem = write, errnoMem = none, targetMem0 = none, targetMem1 = 
none>} : () -> ()
 

diff  --git a/mlir/test/Target/LLVMIR/Import/function-attributes.ll 
b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
index 69e18e1c5bbff..1002ad03c227c 100644
--- a/mlir/test/Target/LLVMIR/Import/function-attributes.ll
+++ b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
@@ -417,5 +417,29 @@ declare void @noreturn_attribute() noreturn
 
 // -----
 
+; CHECK-LABEL: @returnstwice_attribute
+; CHECK-SAME: attributes {returns_twice}
+declare void @returnstwice_attribute() returns_twice
+
+// -----
+
+; CHECK-LABEL: @hot_attribute
+; CHECK-SAME: attributes {hot}
+declare void @hot_attribute() hot
+
+// -----
+
+; CHECK-LABEL: @cold_attribute
+; CHECK-SAME: attributes {cold}
+declare void @cold_attribute() cold
+
+// -----
+
+; CHECK-LABEL: @noduplicate_attribute
+; CHECK-SAME: attributes {noduplicate}
+declare void @noduplicate_attribute() noduplicate
+
+// -----
+
 ; expected-warning @unknown {{'preallocated' attribute is invalid on current 
operation, skipping it}}
 declare void @test() preallocated(i32)

diff  --git a/mlir/test/Target/LLVMIR/Import/instructions.ll 
b/mlir/test/Target/LLVMIR/Import/instructions.ll
index 766f19ce386f8..11ebd70def8ce 100644
--- a/mlir/test/Target/LLVMIR/Import/instructions.ll
+++ b/mlir/test/Target/LLVMIR/Import/instructions.ll
@@ -713,6 +713,54 @@ define void @call_noreturn() {
 ; CHECK: llvm.func @f()
 declare void @f()
 
+; CHECK-LABEL: @call_returnstwice
+define void @call_returnstwice() {
+; CHECK: llvm.call @f() {returns_twice}
+  call void @f() returns_twice
+  ret void
+}
+
+; // -----
+
+; CHECK: llvm.func @f()
+declare void @f()
+
+; CHECK-LABEL: @call_hot
+define void @call_hot() {
+; CHECK: llvm.call @f() {hot}
+  call void @f() hot
+  ret void
+}
+
+; // -----
+
+; CHECK: llvm.func @f()
+declare void @f()
+
+; CHECK-LABEL: @call_cold
+define void @call_cold() {
+; CHECK: llvm.call @f() {cold}
+  call void @f() cold
+  ret void
+}
+
+; // -----
+
+; CHECK: llvm.func @f()
+declare void @f()
+
+; CHECK-LABEL: @call_noduplicate
+define void @call_noduplicate() {
+; CHECK: llvm.call @f() {noduplicate}
+  call void @f() noduplicate
+  ret void
+}
+
+; // -----
+
+; CHECK: llvm.func @f()
+declare void @f()
+
 ; CHECK-LABEL: @call_memory_effects
 define void @call_memory_effects() {
 ; CHECK: llvm.call @f() {memory_effects = #llvm.memory_effects<other = none, 
argMem = none, inaccessibleMem = none, errnoMem = none, targetMem0 = none, 
targetMem1 = none>}

diff  --git a/mlir/test/Target/LLVMIR/llvmir.mlir 
b/mlir/test/Target/LLVMIR/llvmir.mlir
index 12d73b429b3ce..8adf305805b0e 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2642,6 +2642,50 @@ llvm.func @noreturn() attributes { noreturn } {
 
 // -----
 
+// CHECK-LABEL: @returnstwice
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @returnstwice() attributes { returns_twice } {
+  llvm.return
+}
+
+// CHECK: #[[ATTRS]]
+// CHECK-SAME: returns_twice
+
+// -----
+
+// CHECK-LABEL: @hot
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @hot() attributes { hot } {
+  llvm.return
+}
+
+// CHECK: #[[ATTRS]]
+// CHECK-SAME: hot
+
+// -----
+
+// CHECK-LABEL: @cold
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @cold() attributes { cold } {
+  llvm.return
+}
+
+// CHECK: #[[ATTRS]]
+// CHECK-SAME:cold
+
+// -----
+
+// CHECK-LABEL: @noduplicate
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @noduplicate() attributes { noduplicate } {
+  llvm.return
+}
+
+// CHECK: #[[ATTRS]]
+// CHECK-SAME: noduplicate
+
+// -----
+
 llvm.func @f()
 
 // CHECK-LABEL: @convergent_call


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to