[clang] 0e90a84 - [CIR] Add support for global linkage and visibility (#141973)

via cfe-commits cfe-commits at lists.llvm.org
Fri May 30 13:36:51 PDT 2025


Author: Andy Kaylor
Date: 2025-05-30T13:36:48-07:00
New Revision: 0e90a846d6dd48c0097ade8e0fa2221a8a6aef6c

URL: https://github.com/llvm/llvm-project/commit/0e90a846d6dd48c0097ade8e0fa2221a8a6aef6c
DIFF: https://github.com/llvm/llvm-project/commit/0e90a846d6dd48c0097ade8e0fa2221a8a6aef6c.diff

LOG: [CIR] Add support for global linkage and visibility (#141973)

This change adds support for the CIRGlobalValueInterface and attributes
for visibility and comdat to GlobalOp.

The comdat attribute isn't correctly calculated yet, but it was required
for the CIRGlobalValueInterface interface. There are also some cases
where dso_local isn't set correctly, but it is better than it was before
this change. Those issues will be addressed in a future patch.

Added: 
    

Modified: 
    clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
    clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
    clang/include/clang/CIR/Dialect/IR/CIROps.td
    clang/include/clang/CIR/Dialect/IR/CMakeLists.txt
    clang/include/clang/CIR/MissingFeatures.h
    clang/lib/CIR/CodeGen/CIRGenModule.cpp
    clang/lib/CIR/CodeGen/CIRGenModule.h
    clang/lib/CIR/Dialect/IR/CIRDialect.cpp
    clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
    clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
    clang/test/CIR/CodeGen/array.cpp
    clang/test/CIR/CodeGen/namespace.cpp
    clang/test/CIR/CodeGen/string-literals.c
    clang/test/CIR/CodeGen/struct.c
    clang/test/CIR/CodeGen/struct.cpp
    clang/test/CIR/CodeGen/union.c
    clang/test/CIR/CodeGen/vector-ext.cpp
    clang/test/CIR/CodeGen/vector.cpp
    clang/test/CIR/IR/array.cir
    clang/test/CIR/IR/global-var-linkage.cir
    clang/test/CIR/IR/global.cir
    clang/test/CIR/Lowering/array.cpp
    clang/test/CIR/Lowering/global-var-simple.cpp
    clang/test/CIR/Lowering/hello.c
    clang/test/CIR/global-var-linkage.cpp
    clang/test/CIR/global-var-simple.cpp

Removed: 
    


################################################################################
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..ecbced05a5fdd 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -276,4 +276,46 @@ def ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", [TypedAttrInterface]> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// VisibilityAttr
+//===----------------------------------------------------------------------===//
+
+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 CIR_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 cfa766105812f..07851610a2abd 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<
+                        CIR_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..11c3bd4d7be84 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,134 @@ 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 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
+    // 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 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
+    // -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 !(lOpts.SemanticInterposition || lOpts.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 +1253,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 +1307,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 5c716e2ab9e04..697c2450ec38b 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 c7cc27561c87c..94f61b513741b 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 96dd0a7f6c547..b07e61638c3b4 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -963,8 +963,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 bool isDsoLocal = op.getDsolocal();
   assert(!cir::MissingFeatures::opGlobalThreadLocal());
   const bool isThreadLocal = false;
   const uint64_t alignment = op.getAlignment().value_or(0);
@@ -1018,8 +1017,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 bool 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 9316c0c2c61eb..e8fed724923de 100644
--- a/clang/test/CIR/CodeGen/vector-ext.cpp
+++ b/clang/test/CIR/CodeGen/vector-ext.cpp
@@ -16,21 +16,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
 
@@ -38,7 +38,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
 
@@ -47,7 +47,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 24a30171d59c4..6a0b58d98aa7f 100644
--- a/clang/test/CIR/CodeGen/vector.cpp
+++ b/clang/test/CIR/CodeGen/vector.cpp
@@ -15,21 +15,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
 
@@ -38,7 +38,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 
diff erences 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 
diff erences 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


        


More information about the cfe-commits mailing list