https://github.com/andykaylor updated 
https://github.com/llvm/llvm-project/pull/141973

>From 70aa8d668cf610eb7d2486b60112591a19d3db89 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akay...@nvidia.com>
Date: Fri, 23 May 2025 11:03:05 -0700
Subject: [PATCH 1/3] [CIR] Add support for global linkage and visibility

This change adds support for the CIRGlobalValueInterface and attributes
for visibility and comdat to GlobalOp.
---
 clang/include/clang/CIR/Dialect/IR/CIRAttrs.h |   1 +
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  |  43 ++++
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  17 +-
 .../clang/CIR/Dialect/IR/CMakeLists.txt       |   4 +-
 clang/include/clang/CIR/MissingFeatures.h     |   6 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        | 218 ++++++++++++++++--
 clang/lib/CIR/CodeGen/CIRGenModule.h          |  25 +-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       |   3 +
 clang/lib/CIR/Interfaces/CIROpInterfaces.cpp  |  17 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |   6 +-
 clang/test/CIR/CodeGen/array.cpp              |  24 +-
 clang/test/CIR/CodeGen/namespace.cpp          |   2 +-
 clang/test/CIR/CodeGen/string-literals.c      |  12 +-
 clang/test/CIR/CodeGen/struct.c               |  22 +-
 clang/test/CIR/CodeGen/struct.cpp             |   4 +-
 clang/test/CIR/CodeGen/union.c                |   2 +-
 clang/test/CIR/CodeGen/vector-ext.cpp         |  10 +-
 clang/test/CIR/CodeGen/vector.cpp             |   8 +-
 clang/test/CIR/IR/array.cir                   |  16 +-
 clang/test/CIR/IR/global-var-linkage.cir      |  16 +-
 clang/test/CIR/IR/global.cir                  | 108 ++++-----
 clang/test/CIR/Lowering/array.cpp             |  18 +-
 clang/test/CIR/Lowering/global-var-simple.cpp |  66 +++---
 clang/test/CIR/Lowering/hello.c               |   7 +-
 clang/test/CIR/global-var-linkage.cpp         |  14 +-
 clang/test/CIR/global-var-simple.cpp          |   2 +-
 26 files changed, 477 insertions(+), 194 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
index 1451ea47c50c8..64556bcb92baa 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_CLANG_CIR_DIALECT_IR_CIRATTRS_H
 #define LLVM_CLANG_CIR_DIALECT_IR_CIRATTRS_H
 
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
 
 #include "mlir/IR/Attributes.h"
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 8152535930095..bddd7a825c505 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -276,4 +276,47 @@ def ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", 
[TypedAttrInterface]> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// VisibilityAttr
+//===----------------------------------------------------------------------===//
+
+def VK_Default : I32EnumAttrCase<"Default", 1, "default">;
+def VK_Hidden : I32EnumAttrCase<"Hidden", 2, "hidden">;
+def VK_Protected : I32EnumAttrCase<"Protected", 3, "protected">;
+
+def VisibilityKind : I32EnumAttr<"VisibilityKind", "C/C++ visibility", [
+  VK_Default, VK_Hidden, VK_Protected
+]> {
+  let cppNamespace = "::cir";
+}
+
+def VisibilityAttr : CIR_Attr<"Visibility", "visibility"> {
+  let summary = "Visibility attribute";
+  let description = [{
+    Visibility attributes.
+  }];
+  let parameters = (ins "VisibilityKind":$value);
+
+  let assemblyFormat = [{
+    $value
+  }];
+
+  let builders = [
+    AttrBuilder<(ins CArg<"VisibilityKind", 
"cir::VisibilityKind::Default">:$value), [{
+      return $_get($_ctxt, value);
+    }]>
+  ];
+
+  let skipDefaultBuilders = 1;
+
+  // Make DefaultValuedAttr accept VisibilityKind as default value ($0).
+  let constBuilderCall = "cir::VisibilityAttr::get($_builder.getContext(), 
$0)";
+
+  let extraClassDeclaration = [{
+    bool isDefault() const { return getValue() == VisibilityKind::Default; };
+    bool isHidden() const { return getValue() == VisibilityKind::Hidden; };
+    bool isProtected() const { return getValue() == VisibilityKind::Protected; 
};
+  }];
+}
+
 #endif // LLVM_CLANG_CIR_DIALECT_IR_CIRATTRS_TD
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 5ce03c19369cb..6637ad14091cc 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1634,7 +1634,8 @@ def GlobalLinkageKind : I32EnumAttr<
 // properties of a global variable will be added over time as more of ClangIR
 // is upstreamed.
 
-def GlobalOp : CIR_Op<"global"> {
+def GlobalOp : CIR_Op<"global",
+                      [DeclareOpInterfaceMethods<CIRGlobalValueInterface>]> {
   let summary = "Declare or define a global variable";
   let description = [{
     The `cir.global` operation declares or defines a named global variable.
@@ -1643,17 +1644,31 @@ def GlobalOp : CIR_Op<"global"> {
     described by the type of the variable.
 
     The `linkage` tracks C/C++ linkage types, currently very similar to LLVM's.
+    Symbol visibility in `sym_visibility` is defined in terms of MLIR's 
visibility
+    and verified to be in accordance to `linkage`.
   }];
 
+  // Note that both sym_name and sym_visibility are tied to Symbol trait.
+  // TODO: sym_visibility can possibly be represented by implementing the
+  // necessary Symbol's interface in terms of linkage instead.
   let arguments = (ins SymbolNameAttr:$sym_name,
+                       DefaultValuedAttr<
+                        VisibilityAttr,
+                        "VisibilityKind::Default"
+                       >:$global_visibility,
+                       OptionalAttr<StrAttr>:$sym_visibility,
                        TypeAttr:$sym_type,
                        Arg<GlobalLinkageKind, "linkage type">:$linkage,
                        OptionalAttr<AnyAttr>:$initial_value,
+                       UnitAttr:$comdat,
                        UnitAttr:$dsolocal,
                        OptionalAttr<I64Attr>:$alignment);
 
   let assemblyFormat = [{
+    ($sym_visibility^)?
+    (`` $global_visibility^)?
     $linkage
+    (`comdat` $comdat^)?
     (`dsolocal` $dsolocal^)?
     $sym_name
     custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value)
diff --git a/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt 
b/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt
index 6e6d59ea5dadb..6e7f3da4add3e 100644
--- a/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt
+++ b/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt
@@ -14,10 +14,10 @@ mlir_tablegen(CIROpsDialect.cpp.inc -gen-dialect-defs)
 add_public_tablegen_target(MLIRCIROpsIncGen)
 add_dependencies(mlir-headers MLIRCIROpsIncGen)
 
-mlir_tablegen(CIROpsAttributes.h.inc -gen-attrdef-decls)
-mlir_tablegen(CIROpsAttributes.cpp.inc -gen-attrdef-defs)
 mlir_tablegen(CIROpsEnums.h.inc -gen-enum-decls)
 mlir_tablegen(CIROpsEnums.cpp.inc -gen-enum-defs)
+mlir_tablegen(CIROpsAttributes.h.inc -gen-attrdef-decls)
+mlir_tablegen(CIROpsAttributes.cpp.inc -gen-attrdef-defs)
 add_public_tablegen_target(MLIRCIREnumsGen)
 
 set(LLVM_TARGET_DEFINITIONS CIRTypeConstraints.td)
diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 56bf9b1130f12..11250be483edc 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -31,7 +31,6 @@ struct MissingFeatures {
   static bool cgfSymbolTable() { return false; }
 
   // Unhandled global/linkage information.
-  static bool opGlobalDSOLocal() { return false; }
   static bool opGlobalThreadLocal() { return false; }
   static bool opGlobalConstant() { return false; }
   static bool opGlobalWeakRef() { return false; }
@@ -41,11 +40,11 @@ struct MissingFeatures {
   static bool opGlobalVisibility() { return false; }
   static bool opGlobalDLLImportExport() { return false; }
   static bool opGlobalPartition() { return false; }
-  static bool opGlobalCIRGlobalValueInterface() { return false; }
 
   static bool supportIFuncAttr() { return false; }
   static bool supportVisibility() { return false; }
-  static bool supportComdat() { return false; }
+  static bool hiddenVisibility() { return false; }
+  static bool protectedVisibility() { return false; }
 
   // Load/store attributes
   static bool opLoadStoreThreadLocal() { return false; }
@@ -188,7 +187,6 @@ struct MissingFeatures {
   static bool updateCompletedType() { return false; }
   static bool targetSpecificCXXABI() { return false; }
   static bool moduleNameHash() { return false; }
-  static bool setDSOLocal() { return false; }
   static bool constantFoldSwitchStatement() { return false; }
   static bool cudaSupport() { return false; }
   static bool maybeHandleStaticInExternC() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index b31b2b33d7d86..0d315aa277140 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -21,6 +21,7 @@
 #include "clang/AST/GlobalDecl.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Interfaces/CIROpInterfaces.h"
 #include "clang/CIR/MissingFeatures.h"
 
 #include "CIRGenFunctionInfo.h"
@@ -391,9 +392,7 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, 
mlir::Type ty,
     if (d->getTLSKind())
       errorNYI(d->getSourceRange(), "thread local global variable");
 
-    assert(!cir::MissingFeatures::opGlobalDLLImportExport());
-    assert(!cir::MissingFeatures::opGlobalPartition());
-    assert(!cir::MissingFeatures::setDSOLocal());
+    setGVProperties(gv, d);
 
     // If required by the ABI, treat declarations of static data members with
     // inline initializers as definitions.
@@ -401,15 +400,20 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, 
mlir::Type ty,
       errorNYI(d->getSourceRange(), "MS static data member inline definition");
 
     assert(!cir::MissingFeatures::opGlobalSection());
-    assert(!cir::MissingFeatures::opGlobalVisibility());
+    gv.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(d));
 
     // Handle XCore specific ABI requirements.
     if (getTriple().getArch() == llvm::Triple::xcore)
       errorNYI(d->getSourceRange(), "XCore specific ABI requirements");
 
-    // We need to check for external const declarations with initializers here,
-    // but the 'isPublic()' part of the check uses the CIRGlobalValueInterface.
-    assert(!cir::MissingFeatures::opGlobalCIRGlobalValueInterface());
+    // Check if we a have a const declaration with an initializer, we may be
+    // able to emit it as available_externally to expose it's value to the
+    // optimizer.
+    if (getLangOpts().CPlusPlus && gv.isPublic() &&
+        d->getType().isConstQualified() && gv.isDeclaration() &&
+        !d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())
+      errorNYI(d->getSourceRange(),
+               "external const declaration with initializer");
   }
 
   return gv;
@@ -568,7 +572,9 @@ void CIRGenModule::emitGlobalVarDefinition(const 
clang::VarDecl *vd,
 
   // Set CIR linkage and DLL storage class.
   gv.setLinkage(linkage);
-
+  // FIXME(cir): setLinkage should likely set MLIR's visibility automatically.
+  gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
+  assert(!cir::MissingFeatures::opGlobalDLLImportExport());
   if (linkage == cir::GlobalLinkageKind::CommonLinkage)
     errorNYI(initExpr->getSourceRange(), "common linkage");
 }
@@ -632,8 +638,13 @@ CIRGenModule::getConstantArrayFromStringLiteral(const 
StringLiteral *e) {
   return mlir::Attribute();
 }
 
+bool CIRGenModule::supportsCOMDAT() const {
+  return getTriple().supportsCOMDAT();
+}
+
 static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
-  assert(!cir::MissingFeatures::supportComdat());
+  if (!cgm.supportsCOMDAT())
+    return false;
 
   if (d.hasAttr<SelectAnyAttr>())
     return true;
@@ -836,8 +847,11 @@ static cir::GlobalOp generateStringLiteral(mlir::Location 
loc,
   assert(!cir::MissingFeatures::opGlobalThreadLocal());
   assert(!cir::MissingFeatures::opGlobalUnnamedAddr());
   CIRGenModule::setInitializer(gv, c);
-  assert(!cir::MissingFeatures::supportComdat());
-  assert(!cir::MissingFeatures::opGlobalDSOLocal());
+  if (gv.isWeakForLinker()) {
+    assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");
+    gv.setComdat(true);
+  }
+  cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));
   return gv;
 }
 
@@ -894,7 +908,7 @@ cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const 
StringLiteral *s,
   auto typedC = llvm::cast<mlir::TypedAttr>(c);
   cir::GlobalOp gv =
       generateStringLiteral(loc, typedC, *this, uniqueName, alignment);
-  assert(!cir::MissingFeatures::opGlobalDSOLocal());
+  setDSOLocal(static_cast<mlir::Operation *>(gv));
 
   assert(!cir::MissingFeatures::sanitizers());
 
@@ -1075,6 +1089,135 @@ void CIRGenModule::emitTentativeDefinition(const 
VarDecl *d) {
   emitGlobalVarDefinition(d);
 }
 
+static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
+                                 cir::CIRGlobalValueInterface gv) {
+  if (gv.hasLocalLinkage())
+    return true;
+
+  if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
+    return true;
+
+  // DLLImport explicitly marks the GV as external.
+  // so it shouldn't be dso_local
+  // But we don't have the info set now
+  assert(!cir::MissingFeatures::opGlobalDLLImportExport());
+
+  const llvm::Triple &tt = cgm.getTriple();
+  const auto &cgOpts = cgm.getCodeGenOpts();
+  if (tt.isWindowsGNUEnvironment()) {
+    // In MinGW, variables without DLLImport can still be automatically
+    // imported from a DLL by the linker; don't mark variables that
+    // potentially could come from another DLL as DSO local.
+
+    // With EmulatedTLS, TLS variables can be autoimported from other DLLs
+    // (and this actually happens in the public interface of libstdc++), so
+    // such variables can't be marked as DSO local. (Native TLS variables
+    // can't be dllimported at all, though.)
+    cgm.errorNYI("shouldAssumeDSOLocal: MinGW");
+  }
+
+  // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
+  // remain unresolved in the link, they can be resolved to zero, which is
+  // outside the current DSO.
+  if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
+    return false;
+
+  // Every other GV is local on COFF.
+  // Make an exception for windows OS in the triple: Some firmware builds use
+  // *-win32-macho triples. This (accidentally?) produced windows relocations
+  // without GOT tables in older clang versions; Keep this behaviour.
+  // FIXME: even thread local variables?
+  if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
+    return true;
+
+  // Only handle COFF and ELF for now.
+  if (!tt.isOSBinFormatELF())
+    return false;
+
+  llvm::Reloc::Model rm = cgOpts.RelocationModel;
+  const auto &lOpts = cgm.getLangOpts();
+  if (rm != llvm::Reloc::Static && !lOpts.PIE) {
+    // On ELF, if -fno-semantic-interposition is specified and the target
+    // supports local aliases, there will be neither CC1
+    // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
+    // dso_local on the function if using a local alias is preferable (can 
avoid
+    // PLT indirection).
+    if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
+      return false;
+    return !(cgm.getLangOpts().SemanticInterposition ||
+             cgm.getLangOpts().HalfNoSemanticInterposition);
+  }
+
+  // A definition cannot be preempted from an executable.
+  if (!gv.isDeclarationForLinker())
+    return true;
+
+  // Most PIC code sequences that assume that a symbol is local cannot produce 
a
+  // 0 if it turns out the symbol is undefined. While this is ABI and 
relocation
+  // depended, it seems worth it to handle it here.
+  if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
+    return false;
+
+  // PowerPC64 prefers TOC indirection to avoid copy relocations.
+  if (tt.isPPC64())
+    return false;
+
+  if (cgOpts.DirectAccessExternalData) {
+    // If -fdirect-access-external-data (default for -fno-pic), set dso_local
+    // for non-thread-local variables. If the symbol is not defined in the
+    // executable, a copy relocation will be needed at link time. dso_local is
+    // excluded for thread-local variables because they generally don't support
+    // copy relocations.
+    if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
+      // Assume variables are not thread-local until that support is added.
+      assert(!cir::MissingFeatures::opGlobalThreadLocal());
+      return true;
+    }
+
+    // -fno-pic sets dso_local on a function declaration to allow direct
+    // accesses when taking its address (similar to a data symbol). If the
+    // function is not defined in the executable, a canonical PLT entry will be
+    // needed at link time. -fno-direct-access-external-data can avoid the
+    // canonical PLT entry. We don't generalize this condition to -fpie/-fpic 
as
+    // it could just cause trouble without providing perceptible benefits.
+    if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)
+      return true;
+  }
+
+  // If we can use copy relocations we can assume it is local.
+
+  // Otherwise don't assume it is local.
+
+  return false;
+}
+
+void CIRGenModule::setGlobalVisibility(mlir::Operation *gv,
+                                       const NamedDecl *d) const {
+  assert(!cir::MissingFeatures::opGlobalVisibility());
+}
+
+void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {
+  gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));
+}
+
+void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
+  if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
+    setDSOLocal(globalValue);
+}
+
+void CIRGenModule::setGVProperties(mlir::Operation *op,
+                                   const NamedDecl *d) const {
+  assert(!cir::MissingFeatures::opGlobalDLLImportExport());
+  setGVPropertiesAux(op, d);
+}
+
+void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,
+                                      const NamedDecl *d) const {
+  setGlobalVisibility(op, d);
+  setDSOLocal(op);
+  assert(!cir::MissingFeatures::opGlobalPartition());
+}
+
 cir::FuncOp CIRGenModule::getOrCreateCIRFunction(
     StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
     bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
@@ -1111,7 +1254,7 @@ cir::FuncOp CIRGenModule::getOrCreateCIRFunction(
     // Handle dropped DLL attributes.
     if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
       assert(!cir::MissingFeatures::setDLLStorageClass());
-      assert(!cir::MissingFeatures::setDSOLocal());
+      setDSOLocal(entry);
     }
 
     // If there are two attempts to define the same mangled name, issue an
@@ -1165,6 +1308,55 @@ CIRGenModule::createCIRFunction(mlir::Location loc, 
StringRef name,
   return func;
 }
 
+mlir::SymbolTable::Visibility
+CIRGenModule::getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind glk) {
+  switch (glk) {
+  case cir::GlobalLinkageKind::InternalLinkage:
+  case cir::GlobalLinkageKind::PrivateLinkage:
+    return mlir::SymbolTable::Visibility::Private;
+  case cir::GlobalLinkageKind::ExternalLinkage:
+  case cir::GlobalLinkageKind::ExternalWeakLinkage:
+  case cir::GlobalLinkageKind::LinkOnceODRLinkage:
+  case cir::GlobalLinkageKind::AvailableExternallyLinkage:
+  case cir::GlobalLinkageKind::CommonLinkage:
+  case cir::GlobalLinkageKind::WeakAnyLinkage:
+  case cir::GlobalLinkageKind::WeakODRLinkage:
+    return mlir::SymbolTable::Visibility::Public;
+  default: {
+    llvm::errs() << "visibility not implemented for '"
+                 << stringifyGlobalLinkageKind(glk) << "'\n";
+    assert(0 && "not implemented");
+  }
+  }
+  llvm_unreachable("linkage should be handled above!");
+}
+
+cir::VisibilityKind CIRGenModule::getGlobalVisibilityKindFromClangVisibility(
+    clang::VisibilityAttr::VisibilityType visibility) {
+  switch (visibility) {
+  case clang::VisibilityAttr::VisibilityType::Default:
+    return cir::VisibilityKind::Default;
+  case clang::VisibilityAttr::VisibilityType::Hidden:
+    return cir::VisibilityKind::Hidden;
+  case clang::VisibilityAttr::VisibilityType::Protected:
+    return cir::VisibilityKind::Protected;
+  }
+  llvm_unreachable("unexpected visibility value");
+}
+
+cir::VisibilityAttr
+CIRGenModule::getGlobalVisibilityAttrFromDecl(const Decl *decl) {
+  const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();
+  cir::VisibilityAttr cirVisibility =
+      cir::VisibilityAttr::get(&getMLIRContext());
+  if (va) {
+    cirVisibility = cir::VisibilityAttr::get(
+        &getMLIRContext(),
+        getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));
+  }
+  return cirVisibility;
+}
+
 mlir::Type CIRGenModule::convertType(QualType type) {
   return genTypes.convertType(type);
 }
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h 
b/clang/lib/CIR/CodeGen/CIRGenModule.h
index aac8fe72b1890..19cb5eda3507c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -179,6 +179,16 @@ class CIRGenModule : public CIRGenTypeCache {
 
   mlir::Type convertType(clang::QualType type);
 
+  /// Set the visibility for the given global.
+  void setGlobalVisibility(mlir::Operation *op, const NamedDecl *d) const;
+  void setDSOLocal(mlir::Operation *op) const;
+  void setDSOLocal(cir::CIRGlobalValueInterface gv) const;
+
+  /// Set visibility, dllimport/dllexport and dso_local.
+  /// This must be called after dllimport/dllexport is set.
+  void setGVProperties(mlir::Operation *op, const NamedDecl *d) const;
+  void setGVPropertiesAux(mlir::Operation *op, const NamedDecl *d) const;
+
   void emitGlobalDefinition(clang::GlobalDecl gd,
                             mlir::Operation *op = nullptr);
   void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op);
@@ -198,6 +208,8 @@ class CIRGenModule : public CIRGenTypeCache {
 
   void emitTentativeDefinition(const VarDecl *d);
 
+  bool supportsCOMDAT() const;
+
   static void setInitializer(cir::GlobalOp &op, mlir::Attribute value);
 
   cir::FuncOp
@@ -217,6 +229,17 @@ class CIRGenModule : public CIRGenTypeCache {
 
   const llvm::Triple &getTriple() const { return target.getTriple(); }
 
+  /// -------
+  /// Visibility and Linkage
+  /// -------
+
+  static mlir::SymbolTable::Visibility
+  getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind GLK);
+  static cir::VisibilityKind getGlobalVisibilityKindFromClangVisibility(
+      clang::VisibilityAttr::VisibilityType visibility);
+  cir::VisibilityAttr getGlobalVisibilityAttrFromDecl(const Decl *decl);
+  static mlir::SymbolTable::Visibility getMLIRVisibility(cir::GlobalOp op);
+
   cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd,
                                                     GVALinkage linkage,
                                                     bool isConstantVariable);
@@ -243,7 +266,7 @@ class CIRGenModule : public CIRGenTypeCache {
     return diags.Report(diagID) << feature;
   }
 
-  DiagnosticBuilder errorNYI(llvm::StringRef feature) {
+  DiagnosticBuilder errorNYI(llvm::StringRef feature) const {
     // TODO: Make a default location? currSrcLoc?
     unsigned diagID = diags.getCustomDiagID(
         DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 9e2b2908b22d8..68bae8ecfdb1c 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -1132,6 +1132,9 @@ void cir::GlobalOp::build(OpBuilder &odsBuilder, 
OperationState &odsState,
   cir::GlobalLinkageKindAttr linkageAttr =
       cir::GlobalLinkageKindAttr::get(odsBuilder.getContext(), linkage);
   odsState.addAttribute(getLinkageAttrName(odsState.name), linkageAttr);
+
+  odsState.addAttribute(getGlobalVisibilityAttrName(odsState.name),
+                        cir::VisibilityAttr::get(odsBuilder.getContext()));
 }
 
 static void printGlobalOpTypeAndInitialValue(OpAsmPrinter &p, cir::GlobalOp op,
diff --git a/clang/lib/CIR/Interfaces/CIROpInterfaces.cpp 
b/clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
index 3ae103c2e65b4..82427e2c12222 100644
--- a/clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
+++ b/clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
@@ -18,9 +18,20 @@ using namespace cir;
 
 #include "clang/CIR/MissingFeatures.h"
 
+bool CIRGlobalValueInterface::hasDefaultVisibility() {
+  assert(!cir::MissingFeatures::hiddenVisibility());
+  assert(!cir::MissingFeatures::protectedVisibility());
+  return isPublic() || isPrivate();
+}
+
 bool CIRGlobalValueInterface::canBenefitFromLocalAlias() {
   assert(!cir::MissingFeatures::supportIFuncAttr());
-  assert(!cir::MissingFeatures::supportVisibility());
-  assert(!cir::MissingFeatures::supportComdat());
-  return false;
+  // hasComdat here should be isDeduplicateComdat, but as far as clang codegen
+  // is concerned, there is no case for Comdat::NoDeduplicate as all comdat
+  // would be Comdat::Any or Comdat::Largest (in the case of MS ABI). And 
CIRGen
+  // wouldn't even generate Comdat::Largest comdat as it tries to leave ABI
+  // specifics to LLVM lowering stage, thus here we don't need test Comdat
+  // selectionKind.
+  return hasDefaultVisibility() && hasExternalLinkage() && !isDeclaration() &&
+         !hasComdat();
 }
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 8e82af7e62bc0..8f43d2564f472 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -966,8 +966,7 @@ void 
CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
   const bool isConst = false;
   assert(!cir::MissingFeatures::addressSpace());
   const unsigned addrSpace = 0;
-  assert(!cir::MissingFeatures::opGlobalDSOLocal());
-  const bool isDsoLocal = true;
+  const auto isDsoLocal = op.getDsolocal();
   assert(!cir::MissingFeatures::opGlobalThreadLocal());
   const bool isThreadLocal = false;
   const uint64_t alignment = op.getAlignment().value_or(0);
@@ -1021,8 +1020,7 @@ mlir::LogicalResult 
CIRToLLVMGlobalOpLowering::matchAndRewrite(
   const bool isConst = false;
   assert(!cir::MissingFeatures::addressSpace());
   const unsigned addrSpace = 0;
-  assert(!cir::MissingFeatures::opGlobalDSOLocal());
-  const bool isDsoLocal = true;
+  const auto isDsoLocal = op.getDsolocal();
   assert(!cir::MissingFeatures::opGlobalThreadLocal());
   const bool isThreadLocal = false;
   const uint64_t alignment = op.getAlignment().value_or(0);
diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp
index 18f30b20ff8f7..7b90c1682ec45 100644
--- a/clang/test/CIR/CodeGen/array.cpp
+++ b/clang/test/CIR/CodeGen/array.cpp
@@ -8,35 +8,35 @@
 int a[10];
 // CIR: cir.global external @a = #cir.zero : !cir.array<!s32i x 10>
 
-// LLVM: @a = dso_local global [10 x i32] zeroinitializer
+// LLVM: @a = global [10 x i32] zeroinitializer
 
 // OGCG: @a = global [10 x i32] zeroinitializer
 
 int aa[10][5];
 // CIR: cir.global external @aa = #cir.zero : !cir.array<!cir.array<!s32i x 5> 
x 10>
 
-// LLVM: @aa = dso_local global [10 x [5 x i32]] zeroinitializer
+// LLVM: @aa = global [10 x [5 x i32]] zeroinitializer
 
 // OGCG: @aa = global [10 x [5 x i32]] zeroinitializer
 
 int c[10] = {};
 // CIR: cir.global external @c = #cir.zero : !cir.array<!s32i x 10>
 
-// LLVM: @c = dso_local global [10 x i32] zeroinitializer
+// LLVM: @c = global [10 x i32] zeroinitializer
 
 // OGCG: @c = global [10 x i32] zeroinitializer
 
 int d[3] = {1, 2, 3};
 // CIR: cir.global external @d = #cir.const_array<[#cir.int<1> : !s32i, 
#cir.int<2> : !s32i, #cir.int<3> : !s32i]> : !cir.array<!s32i x 3>
 
-// LLVM: @d = dso_local global [3 x i32] [i32 1, i32 2, i32 3]
+// LLVM: @d = global [3 x i32] [i32 1, i32 2, i32 3]
 
 // OGCG: @d = global [3 x i32] [i32 1, i32 2, i32 3]
 
 int dd[3][2] = {{1, 2}, {3, 4}, {5, 6}};
 // CIR: cir.global external @dd = 
#cir.const_array<[#cir.const_array<[#cir.int<1> : !s32i, #cir.int<2> : !s32i]> 
: !cir.array<!s32i x 2>, #cir.const_array<[#cir.int<3> : !s32i, #cir.int<4> : 
!s32i]> : !cir.array<!s32i x 2>, #cir.const_array<[#cir.int<5> : !s32i, 
#cir.int<6> : !s32i]> : !cir.array<!s32i x 2>]> : !cir.array<!cir.array<!s32i x 
2> x 3>
 
-// LLVM: @dd = dso_local global [3 x [2 x i32]] [
+// LLVM: @dd = global [3 x [2 x i32]] [
 // LLVM: [2 x i32] [i32 1, i32 2], [2 x i32]
 // LLVM: [i32 3, i32 4], [2 x i32] [i32 5, i32 6]]
 
@@ -47,23 +47,25 @@ int dd[3][2] = {{1, 2}, {3, 4}, {5, 6}};
 int e[10] = {1, 2};
 // CIR: cir.global external @e = #cir.const_array<[#cir.int<1> : !s32i, 
#cir.int<2> : !s32i], trailing_zeros> : !cir.array<!s32i x 10>
 
-// LLVM: @e = dso_local global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, 
i32 0, i32 0, i32 0, i32 0, i32 0]
+// LLVM: @e = global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, i32 0, i32 
0, i32 0, i32 0, i32 0]
+
+// OGCG: @e = global <{ i32, i32, [8 x i32] }> <{ i32 1, i32 2, [8 x i32] 
zeroinitializer }>
 
 int f[5] = {1, 2};
 // CIR: cir.global external @f = #cir.const_array<[#cir.int<1> : !s32i, 
#cir.int<2> : !s32i, #cir.int<0> : !s32i, #cir.int<0> : !s32i, #cir.int<0> : 
!s32i]> : !cir.array<!s32i x 5>
 
-// LLVM: @f = dso_local global [5 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0]
+// LLVM: @f = global [5 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0]
 
 // OGCG: @f = global [5 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0]
 
 extern int b[10];
-// CIR: cir.global external @b : !cir.array<!s32i x 10>
-// LLVM: @b = external dso_local global [10 x i32]
+// CIR: cir.global "private" external @b : !cir.array<!s32i x 10>
+// LLVM: @b = external global [10 x i32]
 // OGCG: @b = external global [10 x i32]
 
 extern int bb[10][5];
-// CIR: cir.global external @bb : !cir.array<!cir.array<!s32i x 5> x 10>
-// LLVM: @bb = external dso_local global [10 x [5 x i32]]
+// CIR: cir.global "private" external @bb : !cir.array<!cir.array<!s32i x 5> x 
10>
+// LLVM: @bb = external global [10 x [5 x i32]]
 // OGCG: @bb = external global [10 x [5 x i32]]
 
 // This function is only here to make sure the external globals are emitted.
diff --git a/clang/test/CIR/CodeGen/namespace.cpp 
b/clang/test/CIR/CodeGen/namespace.cpp
index bfb4e37c2fa74..e0cf6333c1197 100644
--- a/clang/test/CIR/CodeGen/namespace.cpp
+++ b/clang/test/CIR/CodeGen/namespace.cpp
@@ -20,7 +20,7 @@ namespace test {
   }
 }
 
-// CHECK-DAG: cir.global internal @_ZN12_GLOBAL__N_12g1E = #cir.int<1> : !s32i
+// CHECK-DAG: cir.global "private" internal @_ZN12_GLOBAL__N_12g1E = 
#cir.int<1> : !s32i
 // CHECK-DAG: cir.global external @_ZN4test2g2E = #cir.int<2> : !s32i
 // CHECK-DAG: cir.global external @_ZN4test5test22g3E = #cir.int<3> : !s32i
 // CHECK-DAG: cir.func @_ZN12_GLOBAL__N_12f1Ev()
diff --git a/clang/test/CIR/CodeGen/string-literals.c 
b/clang/test/CIR/CodeGen/string-literals.c
index 81d2a27591295..549fdcb74f48a 100644
--- a/clang/test/CIR/CodeGen/string-literals.c
+++ b/clang/test/CIR/CodeGen/string-literals.c
@@ -5,13 +5,13 @@
 // RUN: %clang_cc1 -triple aarch64-none-linux-android21 -emit-llvm %s -o %t.ll
 // RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
 
-// CIR: cir.global external @[[STR1_GLOBAL:.*]] = #cir.const_array<"1\00" : 
!cir.array<!s8i x 2>> : !cir.array<!s8i x 2>
-// CIR: cir.global external @[[STR2_GLOBAL:.*]] = #cir.zero : !cir.array<!s8i 
x 1>
-// CIR: cir.global external @[[STR3_GLOBAL:.*]] = #cir.zero : !cir.array<!s8i 
x 2>
+// CIR: cir.global "private" external @[[STR1_GLOBAL:.*]] = 
#cir.const_array<"1\00" : !cir.array<!s8i x 2>> : !cir.array<!s8i x 2>
+// CIR: cir.global "private" external @[[STR2_GLOBAL:.*]] = #cir.zero : 
!cir.array<!s8i x 1>
+// CIR: cir.global "private" external @[[STR3_GLOBAL:.*]] = #cir.zero : 
!cir.array<!s8i x 2>
 
-// LLVM: @[[STR1_GLOBAL:.*]] = dso_local global [2 x i8] c"1\00"
-// LLVM: @[[STR2_GLOBAL:.*]] = dso_local global [1 x i8] zeroinitializer
-// LLVM: @[[STR3_GLOBAL:.*]] = dso_local global [2 x i8] zeroinitializer
+// LLVM: @[[STR1_GLOBAL:.*]] = global [2 x i8] c"1\00"
+// LLVM: @[[STR2_GLOBAL:.*]] = global [1 x i8] zeroinitializer
+// LLVM: @[[STR3_GLOBAL:.*]] = global [2 x i8] zeroinitializer
 
 // OGCG: @[[STR1_GLOBAL:.*]] = private unnamed_addr constant [2 x i8] c"1\00"
 // OGCG: @[[STR2_GLOBAL:.*]] = private unnamed_addr constant [1 x i8] 
zeroinitializer
diff --git a/clang/test/CIR/CodeGen/struct.c b/clang/test/CIR/CodeGen/struct.c
index 4c18de295c68c..ed84edd97e5d0 100644
--- a/clang/test/CIR/CodeGen/struct.c
+++ b/clang/test/CIR/CodeGen/struct.c
@@ -48,13 +48,13 @@ struct CompleteS {
 } cs;
 
 // CIR:       cir.global external @cs = #cir.zero : !rec_CompleteS
-// LLVM-DAG:  @cs = dso_local global %struct.CompleteS zeroinitializer
+// LLVM-DAG:  @cs = global %struct.CompleteS zeroinitializer
 // OGCG-DAG:  @cs = global %struct.CompleteS zeroinitializer, align 4
 
 struct IncompleteS *p;
 
 // CIR:      cir.global external @p = #cir.ptr<null> : 
!cir.ptr<!rec_IncompleteS>
-// LLVM-DAG: @p = dso_local global ptr null
+// LLVM-DAG: @p = global ptr null
 // OGCG-DAG: @p = global ptr null, align 8
 
 struct InnerS {
@@ -70,7 +70,7 @@ struct OuterS {
 struct OuterS os;
 
 // CIR:       cir.global external @os = #cir.zero : !rec_OuterS
-// LLVM-DAG:  @os = dso_local global %struct.OuterS zeroinitializer
+// LLVM-DAG:  @os = global %struct.OuterS zeroinitializer
 // OGCG-DAG:  @os = global %struct.OuterS zeroinitializer, align 4
 
 #pragma pack(push)
@@ -82,7 +82,7 @@ struct PackedS {
 } ps;
 
 // CIR:       cir.global external @ps = #cir.zero : !rec_PackedS
-// LLVM-DAG:  @ps = dso_local global %struct.PackedS zeroinitializer
+// LLVM-DAG:  @ps = global %struct.PackedS zeroinitializer
 // OGCG-DAG:  @ps = global %struct.PackedS zeroinitializer, align 1
 
 struct PackedAndPaddedS {
@@ -91,7 +91,7 @@ struct PackedAndPaddedS {
 } __attribute__((aligned(2))) pps;
 
 // CIR:       cir.global external @pps = #cir.zero : !rec_PackedAndPaddedS
-// LLVM-DAG:  @pps = dso_local global %struct.PackedAndPaddedS zeroinitializer
+// LLVM-DAG:  @pps = global %struct.PackedAndPaddedS zeroinitializer
 // OGCG-DAG:  @pps = global %struct.PackedAndPaddedS zeroinitializer, align 2
 
 #pragma pack(pop)
@@ -102,7 +102,7 @@ struct NodeS {
 } node;
 
 // CIR:      cir.global{{.*}} @node = #cir.zero : !rec_NodeS
-// LLVM-DAG:  @node = dso_local global %struct.NodeS zeroinitializer
+// LLVM-DAG:  @node = global %struct.NodeS zeroinitializer
 // OGCG-DAG:  @node = global %struct.NodeS zeroinitializer
 
 // Mutually dependent types
@@ -112,7 +112,7 @@ struct LeftS {
 } ls;
 
 // CIR:      cir.global{{.*}} @ls = #cir.zero : !rec_LeftS
-// LLVM-DAG:  @ls = dso_local global %struct.LeftS zeroinitializer
+// LLVM-DAG:  @ls = global %struct.LeftS zeroinitializer
 // OGCG-DAG:  @ls = global %struct.LeftS zeroinitializer
 
 struct RightS {
@@ -120,7 +120,7 @@ struct RightS {
 } rs;
 
 // CIR:      cir.global{{.*}} @rs = #cir.zero : !rec_RightS
-// LLVM-DAG:  @rs = dso_local global %struct.RightS zeroinitializer
+// LLVM-DAG:  @rs = global %struct.RightS zeroinitializer
 // OGCG-DAG:  @rs = global %struct.RightS zeroinitializer
 
 struct CycleMiddle;
@@ -130,7 +130,7 @@ struct CycleStart {
 } start;
 
 // CIR:      cir.global{{.*}} @start = #cir.zero : !rec_CycleStart
-// LLVM-DAG:  @start = dso_local global %struct.CycleStart zeroinitializer
+// LLVM-DAG:  @start = global %struct.CycleStart zeroinitializer
 // OGCG-DAG:  @start = global %struct.CycleStart zeroinitializer
 
 struct CycleMiddle {
@@ -138,7 +138,7 @@ struct CycleMiddle {
 } middle;
 
 // CIR:      cir.global{{.*}} @middle = #cir.zero : !rec_CycleMiddle
-// LLVM-DAG:  @middle = dso_local global %struct.CycleMiddle zeroinitializer
+// LLVM-DAG:  @middle = global %struct.CycleMiddle zeroinitializer
 // OGCG-DAG:  @middle = global %struct.CycleMiddle zeroinitializer
 
 struct CycleEnd {
@@ -146,7 +146,7 @@ struct CycleEnd {
 } end;
 
 // CIR:      cir.global{{.*}} @end = #cir.zero : !rec_CycleEnd
-// LLVM-DAG:  @end = dso_local global %struct.CycleEnd zeroinitializer
+// LLVM-DAG:  @end = global %struct.CycleEnd zeroinitializer
 // OGCG-DAG:  @end = global %struct.CycleEnd zeroinitializer
 
 void f(void) {
diff --git a/clang/test/CIR/CodeGen/struct.cpp 
b/clang/test/CIR/CodeGen/struct.cpp
index 5948d1423d448..8b9c51bebf97f 100644
--- a/clang/test/CIR/CodeGen/struct.cpp
+++ b/clang/test/CIR/CodeGen/struct.cpp
@@ -9,7 +9,7 @@ struct IncompleteS;
 IncompleteS *p;
 
 // CIR: cir.global external @p = #cir.ptr<null> : !cir.ptr<!rec_IncompleteS>
-// LLVM: @p = dso_local global ptr null
+// LLVM: @p = global ptr null
 // OGCG: @p = global ptr null, align 8
 
 struct CompleteS {
@@ -20,7 +20,7 @@ struct CompleteS {
 CompleteS cs;
 
 // CIR:       cir.global external @cs = #cir.zero : !rec_CompleteS
-// LLVM-DAG:  @cs = dso_local global %struct.CompleteS zeroinitializer
+// LLVM-DAG:  @cs = global %struct.CompleteS zeroinitializer
 // OGCG-DAG:  @cs = global %struct.CompleteS zeroinitializer, align 4
 
 void f(void) {
diff --git a/clang/test/CIR/CodeGen/union.c b/clang/test/CIR/CodeGen/union.c
index 96c1e420e5ef0..d998b5add41a3 100644
--- a/clang/test/CIR/CodeGen/union.c
+++ b/clang/test/CIR/CodeGen/union.c
@@ -47,7 +47,7 @@ union U4 {
 union IncompleteU *p;
 
 // CIR:  cir.global external @p = #cir.ptr<null> : !cir.ptr<!rec_IncompleteU>
-// LLVM: @p = dso_local global ptr null
+// LLVM: @p = global ptr null
 // OGCG: @p = global ptr null, align 8
 
 void f1(void) {
diff --git a/clang/test/CIR/CodeGen/vector-ext.cpp 
b/clang/test/CIR/CodeGen/vector-ext.cpp
index aab723f041edf..b86cf94c83092 100644
--- a/clang/test/CIR/CodeGen/vector-ext.cpp
+++ b/clang/test/CIR/CodeGen/vector-ext.cpp
@@ -15,21 +15,21 @@ typedef double vd2 __attribute__((ext_vector_type(2)));
 vi4 vec_a;
 // CIR: cir.global external @[[VEC_A:.*]] = #cir.zero : !cir.vector<4 x !s32i>
 
-// LLVM: @[[VEC_A:.*]] = dso_local global <4 x i32> zeroinitializer
+// LLVM: @[[VEC_A:.*]] = global <4 x i32> zeroinitializer
 
 // OGCG: @[[VEC_A:.*]] = global <4 x i32> zeroinitializer
 
 vi3 vec_b;
 // CIR: cir.global external @[[VEC_B:.*]] = #cir.zero : !cir.vector<3 x !s32i>
 
-// LLVM: @[[VEC_B:.*]] = dso_local global <3 x i32> zeroinitializer
+// LLVM: @[[VEC_B:.*]] = global <3 x i32> zeroinitializer
 
 // OGCG: @[[VEC_B:.*]] = global <3 x i32> zeroinitializer
 
 vi2 vec_c;
 // CIR: cir.global external @[[VEC_C:.*]] = #cir.zero : !cir.vector<2 x !s32i>
 
-// LLVM: @[[VEC_C:.*]] = dso_local global <2 x i32> zeroinitializer
+// LLVM: @[[VEC_C:.*]] = global <2 x i32> zeroinitializer
 
 // OGCG: @[[VEC_C:.*]] = global <2 x i32> zeroinitializer
 
@@ -37,7 +37,7 @@ vd2 vec_d;
 
 // CIR: cir.global external @[[VEC_D:.*]] = #cir.zero : !cir.vector<2 x 
!cir.double>
 
-// LLVM: @[[VEC_D:.*]] = dso_local global <2 x double> zeroinitialize
+// LLVM: @[[VEC_D:.*]] = global <2 x double> zeroinitialize
 
 // OGCG: @[[VEC_D:.*]] = global <2 x double> zeroinitializer
 
@@ -46,7 +46,7 @@ vi4 vec_e = { 1, 2, 3, 4 };
 // CIR: cir.global external @[[VEC_E:.*]] = #cir.const_vector<[#cir.int<1> : 
!s32i, #cir.int<2> :
 // CIR-SAME: !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i]> : !cir.vector<4 
x !s32i>
 
-// LLVM: @[[VEC_E:.*]] = dso_local global <4 x i32> <i32 1, i32 2, i32 3, i32 
4>
+// LLVM: @[[VEC_E:.*]] = global <4 x i32> <i32 1, i32 2, i32 3, i32 4>
 
 // OGCG: @[[VEC_E:.*]] = global <4 x i32> <i32 1, i32 2, i32 3, i32 4>
 
diff --git a/clang/test/CIR/CodeGen/vector.cpp 
b/clang/test/CIR/CodeGen/vector.cpp
index f5a4fcacac4d4..7ffc68d55f2ce 100644
--- a/clang/test/CIR/CodeGen/vector.cpp
+++ b/clang/test/CIR/CodeGen/vector.cpp
@@ -14,21 +14,21 @@ typedef long long vll2 __attribute__((vector_size(16)));
 vi4 vec_a;
 // CIR: cir.global external @[[VEC_A:.*]] = #cir.zero : !cir.vector<4 x !s32i>
 
-// LLVM: @[[VEC_A:.*]] = dso_local global <4 x i32> zeroinitializer
+// LLVM: @[[VEC_A:.*]] = global <4 x i32> zeroinitializer
 
 // OGCG: @[[VEC_A:.*]] = global <4 x i32> zeroinitializer
 
 vd2 b;
 // CIR: cir.global external @[[VEC_B:.*]] = #cir.zero : !cir.vector<2 x 
!cir.double>
 
-// LLVM: @[[VEC_B:.*]] = dso_local global <2 x double> zeroinitialize
+// LLVM: @[[VEC_B:.*]] = global <2 x double> zeroinitialize
 
 // OGCG: @[[VEC_B:.*]] = global <2 x double> zeroinitializer
 
 vll2 c;
 // CIR: cir.global external @[[VEC_C:.*]] = #cir.zero : !cir.vector<2 x !s64i>
 
-// LLVM: @[[VEC_C:.*]] = dso_local global <2 x i64> zeroinitialize
+// LLVM: @[[VEC_C:.*]] = global <2 x i64> zeroinitialize
 
 // OGCG: @[[VEC_C:.*]] = global <2 x i64> zeroinitializer
 
@@ -37,7 +37,7 @@ vi4 d = { 1, 2, 3, 4 };
 // CIR: cir.global external @[[VEC_D:.*]] = #cir.const_vector<[#cir.int<1> : 
!s32i, #cir.int<2> :
 // CIR-SAME: !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i]> : !cir.vector<4 
x !s32i>
 
-// LLVM: @[[VEC_D:.*]] = dso_local global <4 x i32> <i32 1, i32 2, i32 3, i32 
4>
+// LLVM: @[[VEC_D:.*]] = global <4 x i32> <i32 1, i32 2, i32 3, i32 4>
 
 // OGCG: @[[VEC_D:.*]] = global <4 x i32> <i32 1, i32 2, i32 3, i32 4>
 
diff --git a/clang/test/CIR/IR/array.cir b/clang/test/CIR/IR/array.cir
index 5995c393730ae..4930fc493c5a7 100644
--- a/clang/test/CIR/IR/array.cir
+++ b/clang/test/CIR/IR/array.cir
@@ -4,17 +4,17 @@
 
 module  {
 
-cir.global external @a : !cir.array<!s32i x 10>
-// CHECK: cir.global external @a : !cir.array<!s32i x 10>
+cir.global external @a = #cir.zero : !cir.array<!s32i x 10>
+// CHECK: cir.global external @a = #cir.zero  : !cir.array<!s32i x 10>
 
-cir.global external @aa : !cir.array<!cir.array<!s32i x 10> x 10>
-// CHECK: cir.global external @aa : !cir.array<!cir.array<!s32i x 10> x 10>
+cir.global external @aa = #cir.zero : !cir.array<!cir.array<!s32i x 10> x 10>
+// CHECK: cir.global external @aa = #cir.zero : !cir.array<!cir.array<!s32i x 
10> x 10>
 
-cir.global external @b : !cir.array<!s32i x 10>
-// CHECK: cir.global external @b : !cir.array<!s32i x 10>
+cir.global external @b = #cir.zero : !cir.array<!s32i x 10>
+// CHECK: cir.global external @b = #cir.zero : !cir.array<!s32i x 10>
 
-cir.global external @bb : !cir.array<!cir.array<!s32i x 10> x 10>
-// CHECK: cir.global external @bb : !cir.array<!cir.array<!s32i x 10> x 10>
+cir.global external @bb = #cir.zero : !cir.array<!cir.array<!s32i x 10> x 10>
+// CHECK: cir.global external @bb = #cir.zero : !cir.array<!cir.array<!s32i x 
10> x 10>
 
 cir.global external @c = #cir.zero : !cir.array<!s32i x 10>
 // CHECK: cir.global external @c = #cir.zero : !cir.array<!s32i x 10>
diff --git a/clang/test/CIR/IR/global-var-linkage.cir 
b/clang/test/CIR/IR/global-var-linkage.cir
index 6486b700bdbb2..e1b7de4bb2156 100644
--- a/clang/test/CIR/IR/global-var-linkage.cir
+++ b/clang/test/CIR/IR/global-var-linkage.cir
@@ -4,17 +4,17 @@
 !s32i = !cir.int<s, 32>
 
 module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
-  cir.global external @aaaa : !s32i
-  cir.global internal @bbbb : !s32i
-  cir.global linkonce_odr @cccc : !s32i
+  cir.global external @aaaa = #cir.int<0> : !s32i
+  cir.global internal @bbbb = #cir.int<0> : !s32i
+  cir.global linkonce_odr @cccc = #cir.int<0> : !s32i
   cir.global internal @ffff = #cir.int<0> : !s32i
-  cir.global weak_odr @dddd : !s32i
+  cir.global weak_odr @dddd = #cir.int<0> : !s32i
 }
 
 // CHECK: module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
-// CHECK:   cir.global external @aaaa : !s32i
-// CHECK:   cir.global internal @bbbb : !s32i
-// CHECK:   cir.global linkonce_odr @cccc : !s32i
+// CHECK:   cir.global external @aaaa = #cir.int<0> : !s32i
+// CHECK:   cir.global internal @bbbb = #cir.int<0> : !s32i
+// CHECK:   cir.global linkonce_odr @cccc = #cir.int<0> : !s32i
 // CHECK:   cir.global internal @ffff = #cir.int<0> : !s32i
-// CHECK:   cir.global weak_odr @dddd : !s32i
+// CHECK:   cir.global weak_odr @dddd = #cir.int<0> : !s32i
 // CHECK: }
diff --git a/clang/test/CIR/IR/global.cir b/clang/test/CIR/IR/global.cir
index e46a30c7cce40..28fad6bbf4471 100644
--- a/clang/test/CIR/IR/global.cir
+++ b/clang/test/CIR/IR/global.cir
@@ -13,69 +13,69 @@
 !void = !cir.void
 
 module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
-  cir.global external @c : !s8i
-  cir.global external @sc : !s8i
-  cir.global external @uc : !u8i
-  cir.global external @ss : !s16i
+  cir.global external @c = #cir.int<0> : !s8i
+  cir.global external @sc = #cir.int<0> : !s8i
+  cir.global external @uc = #cir.int<0> : !u8i
+  cir.global external @ss = #cir.int<0> : !s16i
   cir.global external @us = #cir.int<100> : !u16i
   cir.global external @si = #cir.int<42> : !s32i
-  cir.global external @ui : !u32i
-  cir.global external @sl : !s64i
-  cir.global external @ul : !u64i
-  cir.global external @sll : !s64i
+  cir.global external @ui = #cir.int<0> : !u32i
+  cir.global external @sl = #cir.int<0> : !s64i
+  cir.global external @ul = #cir.int<0> : !u64i
+  cir.global external @sll = #cir.int<0> : !s64i
   cir.global external @ull = #cir.int<123456> : !u64i
-  cir.global external @s128 : !s128i
-  cir.global external @u128 : !u128i
-  cir.global external @wc : !s32i
-  cir.global external @c8 : !u8i
-  cir.global external @c16 : !u16i
-  cir.global external @c32 : !u32i
-  cir.global external @sb20 : !cir.int<s, 20>
-  cir.global external @ub48 : !cir.int<u, 48>
-  cir.global external @f16 : !cir.f16
-  cir.global external @bf16 : !cir.bf16
-  cir.global external @f : !cir.float
+  cir.global external @s128 = #cir.int<0> : !s128i
+  cir.global external @u128 = #cir.int<0> : !u128i
+  cir.global external @wc = #cir.int<0> : !s32i
+  cir.global external @c8 = #cir.int<0> : !u8i
+  cir.global external @c16 = #cir.int<0> : !u16i
+  cir.global external @c32 = #cir.int<0> : !u32i
+  cir.global external @sb20 = #cir.int<0> : !cir.int<s, 20>
+  cir.global external @ub48 = #cir.int<0> : !cir.int<u, 48>
+  cir.global external @f16 = #cir.fp<0.000000e+00> : !cir.f16
+  cir.global external @bf16 = #cir.fp<0.000000e+00> : !cir.bf16
+  cir.global external @f = #cir.fp<0.000000e+00> : !cir.float
   cir.global external @d = #cir.fp<1.250000e+00> : !cir.double
-  cir.global external @ld : !cir.long_double<!cir.f80>
-  cir.global external @f128 : !cir.f128
-  cir.global external @vp : !cir.ptr<!void>
+  cir.global external @ld = #cir.fp<0.000000e+00> : !cir.long_double<!cir.f80>
+  cir.global external @f128 = #cir.fp<0.000000e+00> : !cir.f128
+  cir.global external @vp = #cir.ptr<null> : !cir.ptr<!void>
   cir.global external @ip = #cir.ptr<null> : !cir.ptr<!s32i>
-  cir.global external @dp : !cir.ptr<!cir.double>
-  cir.global external @cpp : !cir.ptr<!cir.ptr<!s8i>>
-  cir.global external @fp : !cir.ptr<!cir.func<()>>
+  cir.global external @dp = #cir.ptr<null> : !cir.ptr<!cir.double>
+  cir.global external @cpp = #cir.ptr<null> : !cir.ptr<!cir.ptr<!s8i>>
+  cir.global external @fp = #cir.ptr<null> : !cir.ptr<!cir.func<()>>
   cir.global external @fpii = #cir.ptr<null> : !cir.ptr<!cir.func<(!s32i) -> 
!s32i>>
-  cir.global external @fpvar : !cir.ptr<!cir.func<(!s32i, ...)>>
+  cir.global external @fpvar = #cir.ptr<null> : !cir.ptr<!cir.func<(!s32i, 
...)>>
 }
 
-// CHECK: cir.global external @c : !s8i
-// CHECK: cir.global external @sc : !s8i
-// CHECK: cir.global external @uc : !u8i
-// CHECK: cir.global external @ss : !s16i
-// CHECK: cir.global external @us = #cir.int<100>
-// CHECK: cir.global external @si = #cir.int<42>
-// CHECK: cir.global external @ui : !u32i
-// CHECK: cir.global external @sl : !s64i
-// CHECK: cir.global external @ul : !u64i
-// CHECK: cir.global external @sll : !s64i
+// CHECK: cir.global external @c = #cir.int<0> : !s8i
+// CHECK: cir.global external @sc = #cir.int<0> : !s8i
+// CHECK: cir.global external @uc = #cir.int<0> : !u8i
+// CHECK: cir.global external @ss = #cir.int<0> : !s16i
+// CHECK: cir.global external @us = #cir.int<100> : !u16i
+// CHECK: cir.global external @si = #cir.int<42> : !s32i
+// CHECK: cir.global external @ui = #cir.int<0> : !u32i
+// CHECK: cir.global external @sl = #cir.int<0> : !s64i
+// CHECK: cir.global external @ul = #cir.int<0> : !u64i
+// CHECK: cir.global external @sll = #cir.int<0> : !s64i
 // CHECK: cir.global external @ull = #cir.int<123456> : !u64i
-// CHECK: cir.global external @s128 : !s128i
-// CHECK: cir.global external @u128 : !u128i
-// CHECK: cir.global external @wc : !s32i
-// CHECK: cir.global external @c8 : !u8i
-// CHECK: cir.global external @c16 : !u16i
-// CHECK: cir.global external @c32 : !u32i
-// CHECK: cir.global external @sb20 : !cir.int<s, 20>
-// CHECK: cir.global external @ub48 : !cir.int<u, 48>
-// CHECK: cir.global external @f16 : !cir.f16
-// CHECK: cir.global external @bf16 : !cir.bf16
-// CHECK: cir.global external @f : !cir.float
+// CHECK: cir.global external @s128 = #cir.int<0> : !s128i
+// CHECK: cir.global external @u128 = #cir.int<0> : !u128i
+// CHECK: cir.global external @wc = #cir.int<0> : !s32i
+// CHECK: cir.global external @c8 = #cir.int<0> : !u8i
+// CHECK: cir.global external @c16 = #cir.int<0> : !u16i
+// CHECK: cir.global external @c32 = #cir.int<0> : !u32i
+// CHECK: cir.global external @sb20 = #cir.int<0> : !cir.int<s, 20>
+// CHECK: cir.global external @ub48 = #cir.int<0> : !cir.int<u, 48>
+// CHECK: cir.global external @f16 = #cir.fp<0.000000e+00> : !cir.f16
+// CHECK: cir.global external @bf16 = #cir.fp<0.000000e+00> : !cir.bf16
+// CHECK: cir.global external @f = #cir.fp<0.000000e+00> : !cir.float
 // CHECK: cir.global external @d = #cir.fp<1.250000e+00> : !cir.double
-// CHECK: cir.global external @ld : !cir.long_double<!cir.f80>
-// CHECK: cir.global external @f128 : !cir.f128
-// CHECK: cir.global external @vp : !cir.ptr<!void>
+// CHECK: cir.global external @ld = #cir.fp<0.000000e+00> : 
!cir.long_double<!cir.f80>
+// CHECK: cir.global external @f128 = #cir.fp<0.000000e+00> : !cir.f128
+// CHECK: cir.global external @vp = #cir.ptr<null> : !cir.ptr<!void>
 // CHECK: cir.global external @ip = #cir.ptr<null> : !cir.ptr<!s32i>
-// CHECK: cir.global external @dp : !cir.ptr<!cir.double>
-// CHECK: cir.global external @cpp : !cir.ptr<!cir.ptr<!s8i>>
-// CHECK: cir.global external @fp : !cir.ptr<!cir.func<()>>
+// CHECK: cir.global external @dp = #cir.ptr<null> : !cir.ptr<!cir.double>
+// CHECK: cir.global external @cpp = #cir.ptr<null> : !cir.ptr<!cir.ptr<!s8i>>
+// CHECK: cir.global external @fp = #cir.ptr<null> : !cir.ptr<!cir.func<()>>
 // CHECK: cir.global external @fpii = #cir.ptr<null> : 
!cir.ptr<!cir.func<(!s32i) -> !s32i>>
-// CHECK: cir.global external @fpvar : !cir.ptr<!cir.func<(!s32i, ...)>>
+// CHECK: cir.global external @fpvar = #cir.ptr<null> : 
!cir.ptr<!cir.func<(!s32i, ...)>>
diff --git a/clang/test/CIR/Lowering/array.cpp 
b/clang/test/CIR/Lowering/array.cpp
index 335042ca68f4c..9bd3464dc3145 100644
--- a/clang/test/CIR/Lowering/array.cpp
+++ b/clang/test/CIR/Lowering/array.cpp
@@ -2,33 +2,33 @@
 // RUN: FileCheck --input-file=%t-cir.ll %s
 
 int a[10];
-// CHECK: @a = dso_local global [10 x i32] zeroinitializer
+// CHECK: @a = global [10 x i32] zeroinitializer
 
 int aa[10][5];
-// CHECK: @aa = dso_local global [10 x [5 x i32]] zeroinitializer
+// CHECK: @aa = global [10 x [5 x i32]] zeroinitializer
 
 int c[10] = {};
-// CHECK: @c = dso_local global [10 x i32] zeroinitializer
+// CHECK: @c = global [10 x i32] zeroinitializer
 
 int d[3] = {1, 2, 3};
-// CHECK: @d = dso_local global [3 x i32] [i32 1, i32 2, i32 3]
+// CHECK: @d = global [3 x i32] [i32 1, i32 2, i32 3]
 
 int dd[3][2] = {{1, 2}, {3, 4}, {5, 6}};
-// CHECK: @dd = dso_local global [3 x [2 x i32]] [
+// CHECK: @dd = global [3 x [2 x i32]] [
 // CHECK: [2 x i32] [i32 1, i32 2], [2 x i32]
 // CHECK: [i32 3, i32 4], [2 x i32] [i32 5, i32 6]]
 
 int e[10] = {1, 2};
-// CHECK: @e = dso_local global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, 
i32 0, i32 0, i32 0, i32 0, i32 0]
+// CHECK: @e = global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, i32 0, 
i32 0, i32 0, i32 0, i32 0]
 
 int f[5] = {1, 2};
-// CHECK: @f = dso_local global [5 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0]
+// CHECK: @f = global [5 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0]
 
 extern int b[10];
-// CHECK: @b = external dso_local global [10 x i32]
+// CHECK: @b = external global [10 x i32]
 
 extern int bb[10][5];
-// CHECK: @bb = external dso_local global [10 x [5 x i32]]
+// CHECK: @bb = external global [10 x [5 x i32]]
 
 // This function is only here to make sure the external globals are emitted.
 void reference_externs() {
diff --git a/clang/test/CIR/Lowering/global-var-simple.cpp 
b/clang/test/CIR/Lowering/global-var-simple.cpp
index 5ff1c3ee96ee2..ecb766694ab50 100644
--- a/clang/test/CIR/Lowering/global-var-simple.cpp
+++ b/clang/test/CIR/Lowering/global-var-simple.cpp
@@ -8,133 +8,133 @@
 //       with ClangIR enabled and will be fixed in a future patch.
 
 char c;
-// CHECK: @c = dso_local global i8 0, align 1
+// CHECK: @c = global i8 0, align 1
 // OGCG:  @c = global i8 0, align 1
 
 signed char sc;
-// CHECK: @sc = dso_local global i8 0, align 1
+// CHECK: @sc = global i8 0, align 1
 // OGCG:  @sc = global i8 0, align 1
 
 unsigned char uc;
-// CHECK: @uc = dso_local global i8 0, align 1
+// CHECK: @uc = global i8 0, align 1
 // OGCG:  @uc = global i8 0, align 1
 
 short ss;
-// CHECK: @ss = dso_local global i16 0, align 2
+// CHECK: @ss = global i16 0, align 2
 // OGCG:  @ss = global i16 0, align 2
 
 unsigned short us = 100;
-// CHECK: @us = dso_local global i16 100, align 2
+// CHECK: @us = global i16 100, align 2
 // OGCG:  @us = global i16 100, align 2
 
 int si = 42;
-// CHECK: @si = dso_local global i32 42, align 4
+// CHECK: @si = global i32 42, align 4
 // OGCG:  @si = global i32 42, align 4
 
 unsigned ui;
-// CHECK: @ui = dso_local global i32 0, align 4
+// CHECK: @ui = global i32 0, align 4
 // OGCG:  @ui = global i32 0, align 4
 
 long sl;
-// CHECK: @sl = dso_local global i64 0, align 8
+// CHECK: @sl = global i64 0, align 8
 // OGCG:  @sl = global i64 0, align 8
 
 unsigned long ul;
-// CHECK: @ul = dso_local global i64 0, align 8
+// CHECK: @ul = global i64 0, align 8
 // OGCG:  @ul = global i64 0, align 8
 
 long long sll;
-// CHECK: @sll = dso_local global i64 0, align 8
+// CHECK: @sll = global i64 0, align 8
 // OGCG:  @sll = global i64 0, align 8
 
 unsigned long long ull = 123456;
-// CHECK: @ull = dso_local global i64 123456, align 8
+// CHECK: @ull = global i64 123456, align 8
 // OGCG:  @ull = global i64 123456, align 8
 
 __int128 s128;
-// CHECK: @s128 = dso_local global i128 0, align 16
+// CHECK: @s128 = global i128 0, align 16
 // OGCG:  @s128 = global i128 0, align 16
 
 unsigned __int128 u128;
-// CHECK: @u128 = dso_local global i128 0, align 16
+// CHECK: @u128 = global i128 0, align 16
 // OGCG:  @u128 = global i128 0, align 16
 
 wchar_t wc;
-// CHECK: @wc = dso_local global i32 0, align 4
+// CHECK: @wc = global i32 0, align 4
 // OGCG:  @wc = global i32 0, align 4
 
 char8_t c8;
-// CHECK: @c8 = dso_local global i8 0, align 1
+// CHECK: @c8 = global i8 0, align 1
 // OGCG:  @c8 = global i8 0, align 1
 
 char16_t c16;
-// CHECK: @c16 = dso_local global i16 0, align 2
+// CHECK: @c16 = global i16 0, align 2
 // OGCG:  @c16 = global i16 0, align 2
 
 char32_t c32;
-// CHECK: @c32 = dso_local global i32 0, align 4
+// CHECK: @c32 = global i32 0, align 4
 // OGCG:  @c32 = global i32 0, align 4
 
 _BitInt(20) sb20;
-// CHECK: @sb20 = dso_local global i20 0, align 4
+// CHECK: @sb20 = global i20 0, align 4
 // OGCG:  @sb20 = global i32 0, align 4
 
 unsigned _BitInt(48) ub48;
-// CHECK: @ub48 = dso_local global i48 0, align 8
+// CHECK: @ub48 = global i48 0, align 8
 // OGCG:  @ub48 = global i64 0, align 8
 
 bool boolfalse = false;
-// CHECK: @boolfalse = dso_local global i8 0, align 1
+// CHECK: @boolfalse = global i8 0, align 1
 // OGCG:  @boolfalse = global i8 0, align 1
 
 _Float16 f16;
-// CHECK: @f16 = dso_local global half 0xH0000, align 2
+// CHECK: @f16 = global half 0xH0000, align 2
 // OGCG:  @f16 = global half 0xH0000, align 2
 
 __bf16 bf16;
-// CHECK: @bf16 = dso_local global bfloat 0xR0000, align 2
+// CHECK: @bf16 = global bfloat 0xR0000, align 2
 // OGCG:  @bf16 = global bfloat 0xR0000, align 2
 
 float f;
-// CHECK: @f = dso_local global float 0.000000e+00, align 4
+// CHECK: @f = global float 0.000000e+00, align 4
 // OGCG:  @f = global float 0.000000e+00, align 4
 
 double d = 1.25;
-// CHECK: @d = dso_local global double 1.250000e+00, align 8
+// CHECK: @d = global double 1.250000e+00, align 8
 // OGCG:  @d = global double 1.250000e+00, align 8
 
 long double ld;
-// CHECK: @ld = dso_local global x86_fp80 0xK00000000000000000000, align 16
+// CHECK: @ld = global x86_fp80 0xK00000000000000000000, align 16
 // OGCG:  @ld = global x86_fp80 0xK00000000000000000000, align 16
 
 __float128 f128;
-// CHECK: @f128 = dso_local global fp128 0xL00000000000000000000000000000000, 
align 16
+// CHECK: @f128 = global fp128 0xL00000000000000000000000000000000, align 16
 // OGCG:  @f128 = global fp128 0xL00000000000000000000000000000000, align 16
 
 void *vp;
-// CHECK: @vp = dso_local global ptr null, align 8
+// CHECK: @vp = global ptr null, align 8
 // OGCG:  @vp = global ptr null, align 8
 
 int *ip = 0;
-// CHECK: @ip = dso_local global ptr null, align 8
+// CHECK: @ip = global ptr null, align 8
 // OGCG:  @ip = global ptr null, align 8
 
 double *dp;
-// CHECK: @dp = dso_local global ptr null, align 8
+// CHECK: @dp = global ptr null, align 8
 // OGCG:  @dp = global ptr null, align 8
 
 char **cpp;
-// CHECK: @cpp = dso_local global ptr null, align 8
+// CHECK: @cpp = global ptr null, align 8
 // OGCG:  @cpp = global ptr null, align 8
 
 void (*fp)();
-// CHECK: @fp = dso_local global ptr null, align 8
+// CHECK: @fp = global ptr null, align 8
 // OGCG:  @fp = global ptr null, align 8
 
 int (*fpii)(int) = 0;
-// CHECK: @fpii = dso_local global ptr null, align 8
+// CHECK: @fpii = global ptr null, align 8
 // OGCG:  @fpii = global ptr null, align 8
 
 void (*fpvar)(int, ...);
-// CHECK: @fpvar = dso_local global ptr null, align 8
+// CHECK: @fpvar = global ptr null, align 8
 // OGCG:  @fpvar = global ptr null, align 8
diff --git a/clang/test/CIR/Lowering/hello.c b/clang/test/CIR/Lowering/hello.c
index 42552f796914a..e462cb58ae269 100644
--- a/clang/test/CIR/Lowering/hello.c
+++ b/clang/test/CIR/Lowering/hello.c
@@ -4,15 +4,12 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
 // RUN: FileCheck %s -check-prefix=OGCG --input-file %t.ll
 
-// Note: The differences between CHECK and OGCG represent incorrect IR lowering
-//       with ClangIR enabled and will be fixed in a future patch.
-
 int b = 2;
 
-// CHECK: @b = dso_local global i32 2, align 4
+// CHECK: @b = global i32 2, align 4
 // OGCG:  @b = global i32 2, align 4
 
 int a;
 
-// CHECK: @a = dso_local global i32 0, align 4
+// CHECK: @a = global i32 0, align 4
 // OGCG:  @a = global i32 0, align 4
diff --git a/clang/test/CIR/global-var-linkage.cpp 
b/clang/test/CIR/global-var-linkage.cpp
index 7256583432736..1c0c1b121427f 100644
--- a/clang/test/CIR/global-var-linkage.cpp
+++ b/clang/test/CIR/global-var-linkage.cpp
@@ -6,27 +6,27 @@
 // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm %s 
-o %t.ll
 // RUN: FileCheck %s -check-prefix=OGCG --input-file %t.ll
 
-// Note: The differences between CHECK and OGCG represent incorrect IR lowering
-//       with ClangIR enabled and will be fixed in a future patch.
-
 int aaaa;
 // CIR: cir.global external @aaaa
-// LLVM: @aaaa = dso_local global i32 0
+// LLVM: @aaaa = global i32 0
 // OGCG: @aaaa = global i32 0
 
 [[gnu::selectany]] int dddd;
 // CIR: cir.global weak_odr @dddd
-// LLVM: @dddd = weak_odr dso_local global i32 0
+// LLVM: @dddd = weak_odr global i32 0
+// This actually should be here, but we aren't emitting it yet so I want the
+// test to reflect that.
+// LLVM-NOT: comdat
 // OGCG: @dddd = weak_odr global i32 0, comdat
 
 static int bbbb;
-// CIR: cir.global internal @_ZL4bbbb
+// CIR: cir.global "private" internal @_ZL4bbbb
 // LLVM: @_ZL4bbbb = internal global i32 0
 // OGCG: @_ZL4bbbb = internal global i32 0
 
 inline int cccc;
 // CIR: cir.global linkonce_odr @cccc
-// LLVM: @cccc = linkonce_odr dso_local global i32 0
+// LLVM: @cccc = linkonce_odr global i32 0
 // OGCG: @cccc = linkonce_odr global i32 0
 
 // Force the global variables to be emitted
diff --git a/clang/test/CIR/global-var-simple.cpp 
b/clang/test/CIR/global-var-simple.cpp
index 9a52925303504..4608089058fb4 100644
--- a/clang/test/CIR/global-var-simple.cpp
+++ b/clang/test/CIR/global-var-simple.cpp
@@ -68,7 +68,7 @@ __bf16 bf16;
 // CHECK: cir.global external @bf16 = #cir.fp<0.000000e+00> : !cir.bf16
 
 float f;
-// CHECK: cir.global external @f = #cir.fp<0.000000e+00>  : !cir.float
+// CHECK: cir.global external @f = #cir.fp<0.000000e+00> : !cir.float
 
 double d = 1.25;
 // CHECK: cir.global external @d = #cir.fp<1.250000e+00> : !cir.double

>From bbd6992cc4bd8b978a33318da6d7166c64a195f6 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akay...@nvidia.com>
Date: Fri, 30 May 2025 10:29:11 -0700
Subject: [PATCH 2/3] Address review feedback

---
 clang/include/clang/CIR/Dialect/IR/CIRAttrs.td      | 13 ++++++-------
 clang/include/clang/CIR/Dialect/IR/CIROps.td        |  2 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp              |  8 ++++----
 clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  4 ++--
 4 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index bddd7a825c505..ecbced05a5fdd 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -280,17 +280,16 @@ def ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", 
[TypedAttrInterface]> {
 // VisibilityAttr
 
//===----------------------------------------------------------------------===//
 
-def VK_Default : I32EnumAttrCase<"Default", 1, "default">;
-def VK_Hidden : I32EnumAttrCase<"Hidden", 2, "hidden">;
-def VK_Protected : I32EnumAttrCase<"Protected", 3, "protected">;
-
-def VisibilityKind : I32EnumAttr<"VisibilityKind", "C/C++ visibility", [
-  VK_Default, VK_Hidden, VK_Protected
+def CIR_VisibilityKind : I32EnumAttr<"VisibilityKind", "C/C++ visibility", [
+  I32EnumAttrCase<"Default", 1, "default">,
+  I32EnumAttrCase<"Hidden", 2, "hidden">,
+  I32EnumAttrCase<"Protected", 3, "protected">
 ]> {
+  let genSpecializedAttr = 0;
   let cppNamespace = "::cir";
 }
 
-def VisibilityAttr : CIR_Attr<"Visibility", "visibility"> {
+def CIR_VisibilityAttr : CIR_Attr<"Visibility", "visibility"> {
   let summary = "Visibility attribute";
   let description = [{
     Visibility attributes.
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 6637ad14091cc..2efc540dbed1f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1653,7 +1653,7 @@ def GlobalOp : CIR_Op<"global",
   // necessary Symbol's interface in terms of linkage instead.
   let arguments = (ins SymbolNameAttr:$sym_name,
                        DefaultValuedAttr<
-                        VisibilityAttr,
+                        CIR_VisibilityAttr,
                         "VisibilityKind::Default"
                        >:$global_visibility,
                        OptionalAttr<StrAttr>:$sym_visibility,
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 0d315aa277140..7e9b98f0f5fde 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1103,7 +1103,7 @@ static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
   assert(!cir::MissingFeatures::opGlobalDLLImportExport());
 
   const llvm::Triple &tt = cgm.getTriple();
-  const auto &cgOpts = cgm.getCodeGenOpts();
+  const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
   if (tt.isWindowsGNUEnvironment()) {
     // In MinGW, variables without DLLImport can still be automatically
     // imported from a DLL by the linker; don't mark variables that
@@ -1135,7 +1135,7 @@ static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
     return false;
 
   llvm::Reloc::Model rm = cgOpts.RelocationModel;
-  const auto &lOpts = cgm.getLangOpts();
+  const LangOptions &lOpts = cgm.getLangOpts();
   if (rm != llvm::Reloc::Static && !lOpts.PIE) {
     // On ELF, if -fno-semantic-interposition is specified and the target
     // supports local aliases, there will be neither CC1
@@ -1144,8 +1144,8 @@ static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
     // PLT indirection).
     if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
       return false;
-    return !(cgm.getLangOpts().SemanticInterposition ||
-             cgm.getLangOpts().HalfNoSemanticInterposition);
+    return !(lOpts.SemanticInterposition ||
+             lOpts.HalfNoSemanticInterposition);
   }
 
   // A definition cannot be preempted from an executable.
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 8f43d2564f472..c8ba4005f00e6 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -966,7 +966,7 @@ void 
CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
   const bool isConst = false;
   assert(!cir::MissingFeatures::addressSpace());
   const unsigned addrSpace = 0;
-  const auto isDsoLocal = op.getDsolocal();
+  const bool isDsoLocal = op.getDsolocal();
   assert(!cir::MissingFeatures::opGlobalThreadLocal());
   const bool isThreadLocal = false;
   const uint64_t alignment = op.getAlignment().value_or(0);
@@ -1020,7 +1020,7 @@ mlir::LogicalResult 
CIRToLLVMGlobalOpLowering::matchAndRewrite(
   const bool isConst = false;
   assert(!cir::MissingFeatures::addressSpace());
   const unsigned addrSpace = 0;
-  const auto isDsoLocal = op.getDsolocal();
+  const bool isDsoLocal = op.getDsolocal();
   assert(!cir::MissingFeatures::opGlobalThreadLocal());
   const bool isThreadLocal = false;
   const uint64_t alignment = op.getAlignment().value_or(0);

>From edf60eaeacdc1520b03a058e228f7bc31a335bf8 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akay...@nvidia.com>
Date: Fri, 30 May 2025 11:04:38 -0700
Subject: [PATCH 3/3] Fix formatting

---
 clang/lib/CIR/CodeGen/CIRGenModule.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 7e9b98f0f5fde..11c3bd4d7be84 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1144,8 +1144,7 @@ static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
     // PLT indirection).
     if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
       return false;
-    return !(lOpts.SemanticInterposition ||
-             lOpts.HalfNoSemanticInterposition);
+    return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
   }
 
   // A definition cannot be preempted from an executable.

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to