[clang] [CIR] Correctly pass func self-comdat & alignment (PR #223773)

via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 15 11:02:17 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clangir

Author: Erich Keane (erichkeane)

<details>
<summary>Changes</summary>

Classic codegen does these, and it is important for when these end up being stored as function pointers, as we discovered on a benchmark.

This patch does 2 things:

1- Properly passes the 'self' 'comdat' feature (that is, when the symbol
    reference is 'self', not when it is a different name, which isn't
    implemented anywhere).  This mirrors what was done for GlobalOp.

2- Properly calculate and pass the 'alignment'/'preferred alignment' for a function. Only the 'alignment' is passed to LLVM-IR, as the dialect doesn't support preferred alignment, so a 'missing feature' is left in place. That functionality isn't important to this patch, but was 'next to' the alignment work in CodeGenModule.cpp, so it seemed like something we should handle if at all possible.

---

Patch is 38.33 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/223773.diff


22 Files Affected:

- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+6) 
- (modified) clang/include/clang/CIR/MissingFeatures.h (+1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+23) 
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+17) 
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+37-14) 
- (modified) clang/test/CIR/CodeGen/array-init-loop-exprs.cpp (+1-1) 
- (modified) clang/test/CIR/CodeGen/cxx-conversion-operators.cpp (+1-1) 
- (added) clang/test/CIR/CodeGen/func-member-attrs.cpp (+43) 
- (modified) clang/test/CIR/CodeGen/global-tls-dyn-init.cpp (+4-4) 
- (modified) clang/test/CIR/CodeGen/global-tls-simple-init.cpp (+7-7) 
- (modified) clang/test/CIR/CodeGen/global-tls-templates.cpp (+2-2) 
- (modified) clang/test/CIR/CodeGen/inherited-ctors.cpp (+3-3) 
- (modified) clang/test/CIR/CodeGen/lambda-generic-in-cxx11abi-lambda.cpp (+2-2) 
- (modified) clang/test/CIR/CodeGen/lambda-static-invoker-agg-return.cpp (+1-1) 
- (modified) clang/test/CIR/CodeGen/lambda-static-invoker.cpp (+6-6) 
- (modified) clang/test/CIR/CodeGen/lambda.cpp (+5-5) 
- (modified) clang/test/CIR/CodeGen/static-local.cpp (+3-3) 
- (modified) clang/test/CIR/CodeGen/vtable-emission.cpp (+1-1) 
- (modified) clang/test/CIR/CodeGen/vtable-thunk-undefined-callee.cpp (+1-1) 
- (modified) clang/test/CIR/IR/func.cir (+14) 
- (modified) clang/test/CIR/IR/invalid-func.cir (+27) 
- (modified) clang/test/CIR/func-linkage.cpp (+2-8) 


``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index c5a836a0c2f03b..7e9dcfc2ecbdd7 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4293,6 +4293,8 @@ def CIR_FuncOp : CIR_Op<"func", [
     >:$calling_conv,
     OptionalAttr<StrAttr>:$sym_visibility,
     UnitAttr:$comdat,
+    OptionalAttr<I64Attr>:$alignment,
+    OptionalAttr<I64Attr>:$preferred_alignment,
     OptionalAttr<DictArrayAttr>:$arg_attrs,
     OptionalAttr<DictArrayAttr>:$res_attrs,
     OptionalAttr<FlatSymbolRefAttr>:$aliasee,
@@ -4385,6 +4387,10 @@ def CIR_FuncOp : CIR_Op<"func", [
     matchAndRewriteAlias(cir::FuncOp op, llvm::StringRef aliasee, mlir::Type ty,
                          OpAdaptor adaptor,
                          mlir::ConversionPatternRewriter &rewriter) const;
+
+    mutable mlir::LLVM::ComdatOp comdatOp = nullptr;
+    mlir::SymbolRefAttr getComdatAttr(cir::FuncOp &op,
+                                      mlir::OpBuilder &builder) const;
   }];
 }
 
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 16d97871ec7b67..a82d0e0a4729d1 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -82,6 +82,7 @@ struct MissingFeatures {
   static bool opFuncReadOnly() { return false; }
   static bool opFuncUnwindTablesAttr() { return false; }
   static bool opFuncWillReturn() { return false; }
+  static bool opFuncPreferredAlignment() { return false; }
   static bool setLLVMFunctionFEnvAttributes() { return false; }
 
   // CallOp handling
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index bdc2707723283d..e8780fc0ba84ec 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -3379,6 +3379,29 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(
   }
 
   assert(!cir::MissingFeatures::opFuncColdHotAttr());
+
+  std::optional<uint64_t> explicitAlignment;
+  if (unsigned alignment =
+          decl->getMaxAlignment() / getASTContext().getCharWidth())
+    explicitAlignment = alignment;
+  else if (langOpts.FunctionAlignment)
+    explicitAlignment = 1ull << langOpts.FunctionAlignment;
+
+  if (explicitAlignment) {
+    f.setAlignment(*explicitAlignment);
+    f.setPreferredAlignment(*explicitAlignment);
+  } else if (langOpts.PreferredFunctionAlignment) {
+    f.setPreferredAlignment(langOpts.PreferredFunctionAlignment);
+  }
+
+  // Some C++ ABIs require 2-byte alignment for member functions, in order to
+  // reserve a bit for differentiating between virtual and non-virtual member
+  // functions. If the current target's C++ ABI requires this and this is a
+  // member function, set its alignment accordingly.
+  if (getTarget().getCXXABI().areMemberFunctionsAligned()) {
+    if (isa<CXXMethodDecl>(decl) && f.getAlignment().value_or(1) < 2)
+      f.setAlignment(std::max(2ul, f.getAlignment().value_or(1)));
+  }
 }
 
 // Maps an AST address space to the OpenCL logical address space kind recorded
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 4782de43bec5f0..ed99bae5e3c789 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2597,6 +2597,7 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
   mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
   mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
   mlir::StringAttr comdatNameAttr = getComdatAttrName(state.name);
+  mlir::StringAttr alignmentNameAttr = getAlignmentAttrName(state.name);
   mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
   mlir::StringAttr dsoLocalNameAttr = getDsoLocalAttrName(state.name);
   mlir::StringAttr funcInfoNameAttr = getFuncInfoAttrName(state.name);
@@ -2622,6 +2623,19 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
   if (parser.parseOptionalKeyword(comdatNameAttr).succeeded())
     state.addAttribute(comdatNameAttr, parser.getBuilder().getUnitAttr());
 
+  if (parser.parseOptionalKeyword(alignmentNameAttr).succeeded()) {
+    int64_t value;
+    if (parser.parseLParen().failed() || parser.parseInteger(value).failed() ||
+        parser.parseRParen().failed())
+      return failure();
+
+    if (value <= 0)
+      return parser.emitError(loc,
+                              "function alignment must be a positive integer");
+
+    state.addAttribute(alignmentNameAttr, builder.getI64IntegerAttr(value));
+  }
+
   // Default to external linkage if no keyword is provided.
   state.addAttribute(getLinkageAttrNameString(),
                      GlobalLinkageKindAttr::get(
@@ -2933,6 +2947,9 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
   if (getComdat())
     p << " comdat";
 
+  if (getAlignment())
+    p << " alignment(" << *getAlignment() << ')';
+
   if (getLinkage() != GlobalLinkageKind::ExternalLinkage)
     p << ' ' << stringifyGlobalLinkageKind(getLinkage());
 
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 24ee700e87ecee..13dab4c9e26d33 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2694,7 +2694,9 @@ static bool shouldDropFuncAttribute(cir::FuncOp func, mlir::NamedAttribute attr,
          attr.getName() == func.getSideEffectAttrName() ||
          attr.getName() == CIRDialect::getNoReturnAttrName() ||
          attr.getName() == CIRDialect::getStrictFPAttrName() ||
-         attr.getName() == func.getAnnotationsAttrName();
+         attr.getName() == func.getAnnotationsAttrName() ||
+         attr.getName() == func.getComdatAttrName() ||
+         attr.getName() == func.getAlignmentAttrName();
 }
 
 /// Lower `cir.func` attributes for an `LLVMFuncOp` or `LLVM::AliasOp`.
@@ -2804,9 +2806,11 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
                                        attributes)))
     return mlir::failure();
 
+  mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
+
   mlir::LLVM::LLVMFuncOp fn = mlir::LLVM::LLVMFuncOp::create(
       rewriter, loc, op.getName(), llvmFnTy, linkage, isDsoLocal, cconv,
-      mlir::SymbolRefAttr(), attributes);
+      comdatAttr, attributes);
 
   assert(!cir::MissingFeatures::opFuncMultipleReturnVals());
 
@@ -2864,6 +2868,9 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
   fn.setVisibility_(
       lowerCIRVisibilityToLLVMVisibility(op.getGlobalVisibility()));
 
+  fn.setAlignment(op.getAlignment());
+  assert(!MissingFeatures::opFuncPreferredAlignment());
+
   rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
   if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
                                          &signatureConversion)))
@@ -3142,23 +3149,20 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
-mlir::SymbolRefAttr
-CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
-                                         mlir::OpBuilder &builder) const {
-  if (!op.getComdat())
-    return mlir::SymbolRefAttr{};
-
-  mlir::ModuleOp modOp = op->getParentOfType<mlir::ModuleOp>();
+static mlir::SymbolRefAttr getComdatAttrHelper(mlir::ModuleOp modOp,
+                                               mlir::OpBuilder &builder,
+                                               StringRef symName,
+                                               mlir::LLVM::ComdatOp &comdatOp,
+                                               StringRef comdatName) {
   mlir::OpBuilder::InsertionGuard guard(builder);
-  StringRef comdatName("__llvm_comdat_globals");
   if (!comdatOp) {
     builder.setInsertionPointToStart(modOp.getBody());
     comdatOp =
         mlir::LLVM::ComdatOp::create(builder, modOp.getLoc(), comdatName);
   }
 
-  if (auto comdatSelector = comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(
-          op.getSymName())) {
+  if (auto comdatSelector =
+          comdatOp.lookupSymbol<mlir::LLVM::ComdatSelectorOp>(symName)) {
     return mlir::SymbolRefAttr::get(
         builder.getContext(), comdatName,
         mlir::FlatSymbolRefAttr::get(comdatSelector.getSymNameAttr()));
@@ -3166,13 +3170,32 @@ CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
 
   builder.setInsertionPointToStart(&comdatOp.getBody().back());
   auto selectorOp = mlir::LLVM::ComdatSelectorOp::create(
-      builder, comdatOp.getLoc(), op.getSymName(),
-      mlir::LLVM::comdat::Comdat::Any, /*sym_visibility=*/nullptr);
+      builder, comdatOp.getLoc(), symName, mlir::LLVM::comdat::Comdat::Any,
+      /*sym_visibility=*/nullptr);
   return mlir::SymbolRefAttr::get(
       builder.getContext(), comdatName,
       mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));
 }
 
+mlir::SymbolRefAttr
+CIRToLLVMGlobalOpLowering::getComdatAttr(cir::GlobalOp &op,
+                                         mlir::OpBuilder &builder) const {
+  if (!op.getComdat())
+    return mlir::SymbolRefAttr{};
+  return getComdatAttrHelper(op->getParentOfType<mlir::ModuleOp>(), builder,
+                             op.getSymName(), comdatOp,
+                             "__llvm_comdat_globals");
+}
+
+mlir::SymbolRefAttr
+CIRToLLVMFuncOpLowering::getComdatAttr(cir::FuncOp &op,
+                                       mlir::OpBuilder &builder) const {
+  if (!op.getComdat())
+    return mlir::SymbolRefAttr{};
+  return getComdatAttrHelper(op->getParentOfType<mlir::ModuleOp>(), builder,
+                             op.getSymName(), comdatOp, "__llvm_comdat_funcs");
+}
+
 mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
     cir::SwitchFlatOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/test/CIR/CodeGen/array-init-loop-exprs.cpp b/clang/test/CIR/CodeGen/array-init-loop-exprs.cpp
index 172a3d34573e15..f5907892fe53e3 100644
--- a/clang/test/CIR/CodeGen/array-init-loop-exprs.cpp
+++ b/clang/test/CIR/CodeGen/array-init-loop-exprs.cpp
@@ -49,7 +49,7 @@ struct HasMultiDimArray {
 // CIR-LABEL: cir.func {{.*}}@_ZN16HasMultiDimArrayC1ERKS_(
 // CIR:    cir.call @_ZN16HasMultiDimArrayC2ERKS_(
 
-// CIR-LABEL: cir.func no_inline comdat linkonce_odr @_ZN18HasNonTrivialArrayC2ERKS_({{.*}}) func_info<#cir.cxx_ctor<!rec_HasNonTrivialArray, copy>> 
+// CIR-LABEL: cir.func no_inline comdat alignment(2) linkonce_odr @_ZN18HasNonTrivialArrayC2ERKS_({{.*}}) func_info<#cir.cxx_ctor<!rec_HasNonTrivialArray, copy>> 
 // CIR: %[[THIS_ALLOCA:.*]] = cir.alloca "this" {{.*}} init : !cir.ptr<!cir.ptr<!rec_HasNonTrivialArray>>
 // CIR: %[[RHS_ALLOCA:.*]] = cir.alloca "" {{.*}} init const : !cir.ptr<!cir.ptr<!rec_HasNonTrivialArray>>
 // CIR: %[[ITR_ALLOCA:.*]] = cir.alloca "arrayinit.temp" {{.*}} : !cir.ptr<!cir.ptr<!rec_NonTrivial>>
diff --git a/clang/test/CIR/CodeGen/cxx-conversion-operators.cpp b/clang/test/CIR/CodeGen/cxx-conversion-operators.cpp
index 989145c9f8e96f..21dfbf23346458 100644
--- a/clang/test/CIR/CodeGen/cxx-conversion-operators.cpp
+++ b/clang/test/CIR/CodeGen/cxx-conversion-operators.cpp
@@ -51,7 +51,7 @@ void test() {
 // CIR:   cir.return
 // CIR: }
 
-// CIR: cir.func no_inline comdat linkonce_odr @_ZNK15inline_operatorcviEv(%[[INLINE_THIS_ARG:.+]]: !cir.ptr<!rec_inline_operator>{{.*}}) -> (!s32i{{.*}})
+// CIR: cir.func no_inline comdat alignment(2) linkonce_odr @_ZNK15inline_operatorcviEv(%[[INLINE_THIS_ARG:.+]]: !cir.ptr<!rec_inline_operator>{{.*}}) -> (!s32i{{.*}})
 // CIR:   %[[INLINE_THIS_ALLOCA:.+]] = cir.alloca "this" {{.*}} init : !cir.ptr<!cir.ptr<!rec_inline_operator>>
 // CIR:   %[[INLINE_RETVAL:.+]] = cir.alloca "__retval" {{.*}} : !cir.ptr<!s32i>
 // CIR:   cir.store %[[INLINE_THIS_ARG]], %[[INLINE_THIS_ALLOCA]] : !cir.ptr<!rec_inline_operator>, !cir.ptr<!cir.ptr<!rec_inline_operator>>
diff --git a/clang/test/CIR/CodeGen/func-member-attrs.cpp b/clang/test/CIR/CodeGen/func-member-attrs.cpp
new file mode 100644
index 00000000000000..b62c46d7591a13
--- /dev/null
+++ b/clang/test/CIR/CodeGen/func-member-attrs.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck %s -check-prefix=CIR --input-file %t.cir
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck %s -check-prefix=LLVM --input-file %t-cir.ll
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck %s -check-prefix=LLVM --input-file %t.ll
+
+struct S {
+  void regular_method();
+
+  void inline_method() {}
+
+  void __attribute__((aligned(8))) aligned_method() {}
+
+  static void static_method() {}
+};
+
+void S::regular_method() {}
+
+inline void free_inline() {}
+
+void use(S &s) {
+  s.regular_method();
+  s.inline_method();
+  s.aligned_method();
+  S::static_method();
+  free_inline();
+}
+
+// CIR: cir.func no_inline alignment(2) dso_local @_ZN1S14regular_methodEv(
+// LLVM: define dso_local void @_ZN1S14regular_methodEv({{.*}}) #{{[0-9]+}} align 2
+
+// CIR: cir.func no_inline comdat alignment(2) linkonce_odr @_ZN1S13inline_methodEv(
+// LLVM: define linkonce_odr void @_ZN1S13inline_methodEv({{.*}}) #{{[0-9]+}} comdat align 2
+
+// CIR: cir.func no_inline comdat alignment(8) linkonce_odr @_ZN1S14aligned_methodEv(
+// LLVM: define linkonce_odr void @_ZN1S14aligned_methodEv({{.*}}) #{{[0-9]+}} comdat align 8
+
+// CIR: cir.func no_inline comdat alignment(2) linkonce_odr @_ZN1S13static_methodEv(
+// LLVM: define linkonce_odr void @_ZN1S13static_methodEv() #{{[0-9]+}} comdat align 2
+
+// CIR: cir.func no_inline comdat linkonce_odr @_Z11free_inlinev()
+// LLVM: define linkonce_odr void @_Z11free_inlinev() #{{[0-9]+}} comdat {
diff --git a/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp b/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp
index 9b4422374fadb7..fe6288f3312277 100644
--- a/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp
+++ b/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp
@@ -63,25 +63,25 @@ struct CtorDtor {
 // CIR:  }
 // CIR:  cir.return
 
-// LLVM: define weak_odr hidden ptr @_ZTW19tls_cd_dyn_not_used() {
+// LLVM: define weak_odr hidden ptr @_ZTW19tls_cd_dyn_not_used() comdat {
 // LLVM:   call void @_ZTH19tls_cd_dyn_not_used()
 // LLVM:   %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd_dyn_not_used)
 // LLVM:   ret ptr %[[GET_GLOB]]
 // LLVM: }
 //
-// LLVM: define weak_odr hidden ptr @_ZTW10tls_cd_ref() {
+// LLVM: define weak_odr hidden ptr @_ZTW10tls_cd_ref() comdat {
 // LLVM:   call void @_ZTH10tls_cd_ref()
 // LLVM:   %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd_ref)
 // LLVM:   ret ptr %[[GET_GLOB]]
 // LLVM: }
 //
-// LLVM: define weak_odr hidden ptr @_ZTW10tls_cd_dyn() {
+// LLVM: define weak_odr hidden ptr @_ZTW10tls_cd_dyn() comdat {
 // LLVM:   call void @_ZTH10tls_cd_dyn()
 // LLVM:   %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd_dyn)
 // LLVM:   ret ptr %[[GET_GLOB]]
 // LLVM: }
 //
-// LLVM: define weak_odr hidden ptr @_ZTW6tls_cd() {
+// LLVM: define weak_odr hidden ptr @_ZTW6tls_cd() comdat {
 // LLVM:   call void @_ZTH6tls_cd()
 // LLVM:   %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd)
 // LLVM:   ret ptr %[[GET_GLOB]]
diff --git a/clang/test/CIR/CodeGen/global-tls-simple-init.cpp b/clang/test/CIR/CodeGen/global-tls-simple-init.cpp
index a324cd63bf7c24..049e8fd9f16d72 100644
--- a/clang/test/CIR/CodeGen/global-tls-simple-init.cpp
+++ b/clang/test/CIR/CodeGen/global-tls-simple-init.cpp
@@ -87,34 +87,34 @@ struct CtorDtor {
 // LLVM-BOTH-DAG: @_ZTH11tls_int_dyn = alias void (), ptr @__tls_init
 
 // Wrappers: 
-// LLVM: define linkonce_odr hidden ptr @_ZTW12maybe_inited() {
+// LLVM: define linkonce_odr hidden ptr @_ZTW12maybe_inited() comdat {
 // LLVM:   %[[HAS_INIT_FUNC:.*]] = icmp ne ptr @_ZTH12maybe_inited, null
 // LLVM:   br i1 %[[HAS_INIT_FUNC]]
 // LLVM:   call void @_ZTH12maybe_inited()
 // LLVM:   %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @maybe_inited)
 // LLVM:   ret ptr %[[GET_GLOB]]
 //
-// LLVM: define weak_odr hidden ptr @_ZTW21definitely_inited_dyn() {
+// LLVM: define weak_odr hidden ptr @_ZTW21definitely_inited_dyn() comdat {
 // LLVM:   call void @_ZTH21definitely_inited_dyn()
 // LLVM:   %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @definitely_inited_dyn)
 // LLVM:   ret ptr %[[GET_GLOB]]
 //
-// LLVM: define weak_odr hidden ptr @_ZTW17definitely_inited() {
+// LLVM: define weak_odr hidden ptr @_ZTW17definitely_inited() comdat {
 // LLVM:   %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @definitely_inited)
 // LLVM:   ret ptr %[[GET_GLOB]]
 // LLVM: }
 //
-// LLVM: define weak_odr hidden ptr @_ZTW17tls_int_self_init() {
+// LLVM: define weak_odr hidden ptr @_ZTW17tls_int_self_init() comdat {
 // LLVM:   call void @_ZTH17tls_int_self_init()
 // LLVM:   %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_int_self_init)
 // LLVM:   ret ptr %[[GET_GLOB]]
 //
-// LLVM: define weak_odr hidden ptr @_ZTW11tls_int_ref() {
+// LLVM: define weak_odr hidden ptr @_ZTW11tls_int_ref() comdat {
 // LLVM:   call void @_ZTH11tls_int_ref()
 // LLVM:   %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_int_ref)
 // LLVM:   ret ptr %[[GET_GLOB]]
 //
-// LLVM: define weak_odr hidden ptr @_ZTW11tls_int_dyn() {
+// LLVM: define weak_odr hidden ptr @_ZTW11tls_int_dyn() comdat {
 // LLVM:   call void @_ZTH11tls_int_dyn()
 // LLVM:   %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_int_dyn)
 // LLVM:   ret ptr %[[GET_GLOB]]
@@ -133,7 +133,7 @@ struct CtorDtor {
 // LLVM:   br label 
 // LLVM:   ret void
 
-// LLVM: define weak_odr hidden ptr @_ZTW7tls_int() {
+// LLVM: define weak_odr hidden ptr @_ZTW7tls_int() comdat {
 // LLVM:   %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_int)
 // LLVM:   ret ptr %[[GET_GLOB]]
 // LLVM: }
diff --git a/clang/test/CIR/CodeGen/global-tls-templates.cpp b/clang/test/CIR/CodeGen/global-tls-templates.cpp
index f0384aa3373b9e..f2e6cac958422e 100644
--- a/clang/test/CIR/CodeGen/global-tls-templates.cpp
+++ b/clang/test/CIR/CodeGen/global-tls-templates.cpp
@@ -120,12 +120,12 @@ thread_local T tls_templ = {get_i()};
 // Wrappers: Just opposite ordering, same check lines as LLVM.
 // FIXME: OGCG has these set as 'comdat'. However, CIR doesn't lower comdat to
 // LLVM, so it doesn't show up in the IR here.
-// LLVM-LABEL: define weak_odr hidden {{.*}}ptr @_ZTW9tls_templI8CtorDtorE() {
+// LLVM-LABEL: define weak_odr hidden {{.*}}ptr @_ZTW9tls_templI8CtorDtorE() comdat {
 // LLVM:   call void @_ZTH9tls_templI8CtorDtorE()
 // LLVM:   call {{.*}}ptr @llvm.threadlocal.address.p0(ptr {{.*}}@_Z9tls_templI8CtorDtorE)
 // LLVM: }
 
-// LLVM-LABEL: define weak_odr hidden {{.*}}ptr @_ZTW9tls_templIiE() {
+// LLVM-LABEL: define weak_odr hidden {{.*}}ptr @_ZTW9tls_templIiE() comdat {
 // LLVM:   call void @_ZTH9tls_templIiE()
 // LLVM:   call {{.*}}ptr @llvm.threadlocal.address.p0(ptr {{.*}}@_Z9tls_templIiE)
 // LLVM: }
diff --git a/clang/test/CIR/CodeGen/inherited-ctors.cpp b/clang/test/CIR/CodeGen/inherited-ctors.cpp
index efbd5533c8d5fd..e78279018772b7 100644
--- a/clang/test/CIR/CodeGen/inherited-ctors.cpp
+++ b/clang/test/CIR/CodeGen/inherited-ctors.cpp
@@ -66,7 +66,7 @@ void fallsthrough() {
 // LLVM: call void @_ZN21VirtualDelegatingCtorC1Ei(ptr {{.*}}, i32 {{.*}}1)
 //
 //
-// CIR-LABEL: cir.func no_inline comdat linkonce_odr @_ZN21VirtualDelegatingCtorC1Ei(%{{.*}}: !cir.ptr<!rec_VirtualDelegatingCtor> {{.*}}, %{{.*}}: !s32i {{.*}}) func_info<#cir.cxx_ctor<!rec_VirtualDelegatingCtor, custom>>
+// CIR-LABEL: cir.func no_inline comdat alignment(2) linkonce_odr @_ZN21VirtualDelegatingCtorC1Ei(%{{.*}}: !cir.ptr<!rec_VirtualDelegatingCtor> {{.*}}, %{{.*}}: !s32i {{.*}}) func_info<#cir.cxx_ctor<!rec_VirtualDelegatingCtor, custom>>
 // CIR: %[[THIS_ALLOCA:.*]] = cir.alloca "this" align(8) init : !cir.ptr<!cir.ptr<!rec_VirtualDelegatingCtor>>
 // CIR: %[[X_ALLOCA:.*]] = cir.alloca "x" align(4) init : !cir.ptr<!s32i>
 // CIR: %[[THIS_LOAD:.*]] = cir.load %[[THIS_ALLOCA]] : !cir.ptr<!cir.ptr<!rec_VirtualDelegatingCtor>>, !cir.ptr<!rec_VirtualDelegatingC...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/223773


More information about the cfe-commits mailing list