https://github.com/adams381 updated 
https://github.com/llvm/llvm-project/pull/198427

>From 5240882812847cdf572e7e7e6e8b6ca781fc0005 Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Mon, 18 May 2026 16:43:16 -0700
Subject: [PATCH 1/4] [mlir][LLVMIR] Allow address-of-global as a leaf in array
 constants
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Large aggregate globals built as nested llvm.insertvalue chains force
LLVMModuleTranslation to call ConstantFoldInsertValueInstruction on each
step, rebuilding the whole ConstantArray each time (O(N²) in the number
of elements). CIR and other frontends hit this when lowering big tables
of pointers (e.g. gcc insn-automata.cc).

Extend llvm.mlir.constant verification so pointer-array aggregates may
use FlatSymbolRefAttr, ZeroAttr, or UndefAttr leaves (not only function
refs). Teach ModuleTranslation::getLLVMConstant to resolve those symbol
refs against globals already registered in the module, and add a
translate test that checks a single LLVM constant array initializer.
---
 .../mlir/Target/LLVMIR/ModuleTranslation.h    | 11 ++++
 mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp    | 14 ++++-
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp  | 53 +++++++++++++++----
 mlir/test/Dialect/LLVMIR/invalid.mlir         | 10 ++++
 .../LLVMIR/llvmir-global-addressof-leaf.mlir  | 19 +++++++
 5 files changed, 96 insertions(+), 11 deletions(-)
 create mode 100644 mlir/test/Target/LLVMIR/llvmir-global-addressof-leaf.mlir

diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h 
b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index 2516818b320aa..c5c4b105ee152 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -262,6 +262,11 @@ class ModuleTranslation {
     return globalsMapping.lookup(op);
   }
 
+  /// Finds an LLVM IR global value by the mlir.global symbol name.
+  llvm::GlobalValue *lookupGlobal(StringRef name) const {
+    return globalsByNameMapping.lookup(name);
+  }
+
   /// Finds an LLVM IR global value that corresponds to the given MLIR 
operation
   /// defining a global alias value.
   llvm::GlobalValue *lookupAlias(Operation *op) {
@@ -470,6 +475,12 @@ class ModuleTranslation {
   /// Mappings between llvm.mlir.global definitions and corresponding globals.
   DenseMap<Operation *, llvm::GlobalValue *> globalsMapping;
 
+  /// Name-keyed mirror of `globalsMapping`, populated alongside it during
+  /// `convertGlobalsAndAliases`.  Lets `getLLVMConstant` resolve
+  /// `FlatSymbolRefAttr` leaves of aggregate constants that name a global
+  /// (mirroring how `functionMapping` resolves function names).
+  llvm::StringMap<llvm::GlobalValue *> globalsByNameMapping;
+
   /// Mappings between llvm.mlir.alias definitions and corresponding global
   /// aliases.
   DenseMap<Operation *, llvm::GlobalValue *> aliasesMapping;
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp 
b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 2b603efadb476..63bd9f8a3d625 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3469,7 +3469,19 @@ static LogicalResult 
verifyStructArrayConstant(LLVM::ConstantOp op,
   // from a symbol and cannot be represented in a DenseElementsAttr, but no 
MLIR
   // user needs this so far, and it seems better to avoid people misusing the
   // ArrayAttr for simple types.
-  auto structType = dyn_cast<LLVM::LLVMStructType>(arrayType.getElementType());
+  Type elementType = arrayType.getElementType();
+  if (isa<LLVM::LLVMPointerType>(elementType)) {
+    for (auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
+      if (isa<FlatSymbolRefAttr, LLVM::ZeroAttr, LLVM::UndefAttr,
+              LLVM::PoisonAttr>(elementAttr))
+        continue;
+      return op.emitOpError()
+             << "pointer array element at index " << idx
+             << " must be a flat symbol reference, zero, undef, or poison";
+    }
+    return success();
+  }
+  auto structType = dyn_cast<LLVM::LLVMStructType>(elementType);
   if (!structType)
     return op.emitOpError() << "for array with an array attribute must have a "
                                "struct element type";
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp 
b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 9d0ce97ddbbdf..8b1c2bcf6e1d7 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -618,9 +618,15 @@ llvm::Constant *mlir::LLVM::detail::getLLVMConstant(
     }
     return llvm::ConstantFP::get(llvmType, floatAttr.getValue());
   }
-  if (auto funcAttr = dyn_cast<FlatSymbolRefAttr>(attr))
-    return llvm::ConstantExpr::getBitCast(
-        moduleTranslation.lookupFunction(funcAttr.getValue()), llvmType);
+  if (auto symAttr = dyn_cast<FlatSymbolRefAttr>(attr)) {
+    StringRef name = symAttr.getValue();
+    if (llvm::Function *func = moduleTranslation.lookupFunction(name))
+      return llvm::ConstantExpr::getBitCast(func, llvmType);
+    if (llvm::GlobalValue *global = moduleTranslation.lookupGlobal(name))
+      return llvm::ConstantExpr::getBitCast(global, llvmType);
+    emitError(loc, "unknown symbol reference '") << name << "' in constant";
+    return nullptr;
+  }
   if (auto splatAttr = dyn_cast<SplatElementsAttr>(attr)) {
     llvm::Type *elementType;
     uint64_t numElements;
@@ -1197,16 +1203,16 @@ LogicalResult 
ModuleTranslation::convertGlobalsAndAliases() {
   for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
     llvm::Type *type = convertType(op.getType());
     llvm::Constant *cst = nullptr;
-    if (op.getValueOrNull()) {
+    const bool deferValueAttrToPass2 = op.getValueOrNull() &&
+                                       !op.getInitializerBlock() &&
+                                       !isa<StringAttr>(op.getValueOrNull());
+    if (op.getValueOrNull() && !deferValueAttrToPass2) {
       // String attributes are treated separately because they cannot appear as
       // in-function constants and are thus not supported by getLLVMConstant.
       if (auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
         cst = llvm::ConstantDataArray::getString(
             llvmModule->getContext(), strAttr.getValue(), /*AddNull=*/false);
         type = cst->getType();
-      } else if (!(cst = getLLVMConstant(type, op.getValueOrNull(), 
op.getLoc(),
-                                         *this))) {
-        return failure();
       }
     }
 
@@ -1216,10 +1222,14 @@ LogicalResult 
ModuleTranslation::convertGlobalsAndAliases() {
     // external to have initializers. If MLIR does not provide an initializer,
     // default to undef.
     bool dropInitializer = shouldDropGlobalInitializer(linkage, cst);
-    if (!dropInitializer && !cst)
-      cst = llvm::UndefValue::get(type);
-    else if (dropInitializer && cst)
+    if (!deferValueAttrToPass2) {
+      if (!dropInitializer && !cst)
+        cst = llvm::UndefValue::get(type);
+      else if (dropInitializer && cst)
+        cst = nullptr;
+    } else {
       cst = nullptr;
+    }
 
     auto *var = new llvm::GlobalVariable(
         *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
@@ -1249,6 +1259,7 @@ LogicalResult 
ModuleTranslation::convertGlobalsAndAliases() {
     var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
 
     globalsMapping.try_emplace(op, var);
+    globalsByNameMapping.try_emplace(op.getSymName(), var);
 
     // Add debug information if present.
     if (op.getDbgExprs()) {
@@ -1306,6 +1317,28 @@ LogicalResult 
ModuleTranslation::convertGlobalsAndAliases() {
     var->addAttributes(*convertedTargetSpecificAttrs);
   }
 
+  // Value-attribute initializers may reference other globals by symbol name.
+  // Register every global above before materializing those constants.
+  for (auto op : getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
+    if (!op.getValueOrNull() || op.getInitializerBlock() ||
+        isa<StringAttr>(op.getValueOrNull()))
+      continue;
+
+    llvm::Type *type = convertType(op.getType());
+    llvm::Constant *cst =
+        getLLVMConstant(type, op.getValueOrNull(), op.getLoc(), *this);
+    if (!cst)
+      return failure();
+
+    auto linkage = convertLinkageToLLVM(op.getLinkage());
+    bool dropInitializer = shouldDropGlobalInitializer(linkage, cst);
+    auto *var = cast<llvm::GlobalVariable>(lookupGlobal(op));
+    if (dropInitializer)
+      var->setInitializer(nullptr);
+    else
+      var->setInitializer(cst);
+  }
+
   // Create all llvm::GlobalAlias
   for (auto op : getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
     llvm::Type *type = convertType(op.getType());
diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir 
b/mlir/test/Dialect/LLVMIR/invalid.mlir
index cb5148a0ca9ae..e80094df1eed2 100644
--- a/mlir/test/Dialect/LLVMIR/invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/invalid.mlir
@@ -1957,6 +1957,16 @@ llvm.mlir.global internal constant 
@bad_array_attr_simple_type() : !llvm.array<2
 
 // -----
 
+llvm.mlir.global internal constant @bad_ptr_array_attr_leaf() : !llvm.array<2 
x ptr> {
+  // expected-error@below {{pointer array element at index 0 must be a flat 
symbol reference, zero, undef, or poison}}
+  %0 = llvm.mlir.constant([1 : i32, @s0]) : !llvm.array<2 x ptr>
+  llvm.return %0 : !llvm.array<2 x ptr>
+}
+
+llvm.mlir.global private constant @s0("a\00") {addr_space = 0 : i32} : 
!llvm.array<2 x i8>
+
+// -----
+
 llvm.func @inlineAsmMustTail(%arg0: i32, %arg1 : !llvm.ptr) {
   // expected-error@+1 {{op tail call kind 'musttail' is not supported}}
   %8 = llvm.inline_asm tail_call_kind = <musttail> "foo", "=r,=r,r" %arg0 : 
(i32) -> !llvm.struct<(i8, i8)>
diff --git a/mlir/test/Target/LLVMIR/llvmir-global-addressof-leaf.mlir 
b/mlir/test/Target/LLVMIR/llvmir-global-addressof-leaf.mlir
new file mode 100644
index 0000000000000..93b43537ed71f
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/llvmir-global-addressof-leaf.mlir
@@ -0,0 +1,19 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// Per-element string globals referenced by the array-of-pointers global below.
+llvm.mlir.global private constant @s0("a\00") {addr_space = 0 : i32} : 
!llvm.array<2 x i8>
+llvm.mlir.global private constant @s1("b\00") {addr_space = 0 : i32} : 
!llvm.array<2 x i8>
+llvm.mlir.global private constant @s2("c\00") {addr_space = 0 : i32} : 
!llvm.array<2 x i8>
+
+// Single llvm.mlir.constant with a FlatSymbolRefAttr leaf per array element,
+// emitted inside the global's initializer region.  This shape lets MLIR's
+// translator route the lowering through llvm::ConstantArray::get once
+// (the existing array-of-ArrayAttr path in getLLVMConstant), avoiding the
+// O(N^2) per-element ConstantFoldInsertValueInstruction blowup that a chain
+// of llvm.insertvalue ops would otherwise force on large arrays.
+llvm.mlir.global external constant @ptrs() : !llvm.array<3 x ptr> {
+  %0 = llvm.mlir.constant([@s0, @s1, @s2]) : !llvm.array<3 x ptr>
+  llvm.return %0 : !llvm.array<3 x ptr>
+}
+
+// CHECK: @ptrs = constant [3 x ptr] [ptr @s0, ptr @s1, ptr @s2]

>From 28cce6cb25599e6beb38347fde7641ee20f2a632 Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Mon, 18 May 2026 16:44:51 -0700
Subject: [PATCH 2/4] [CIR] Lower pointer const_array globals without
 insertvalue chains

When a cir.global initializer is a const_array of global_view or null
pointer elements with no trailing zero padding, emit the global with a
single aggregate value attribute instead of an initializer region full
of llvm.insertvalue ops. That pairs with the MLIR change that lets
llvm.mlir.global carry [@g0, @g1, ...] on pointer arrays and translates
them to one llvm::ConstantArray.

Indexed global_view elements and non-attribute representable cases still
use the existing insertvalue lowering path.
---
 clang/include/clang/CIR/LoweringHelpers.h     |  3 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 20 ++++-
 clang/lib/CIR/Lowering/LoweringHelpers.cpp    | 90 ++++++++++++++++++-
 .../global-pointer-array-fast-lowering.cpp    | 16 ++++
 .../CIR/Lowering/const-array-of-pointers.cir  | 18 ++++
 5 files changed, 144 insertions(+), 3 deletions(-)
 create mode 100644 
clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp
 create mode 100644 clang/test/CIR/Lowering/const-array-of-pointers.cir

diff --git a/clang/include/clang/CIR/LoweringHelpers.h 
b/clang/include/clang/CIR/LoweringHelpers.h
index 66e99c7e84416..3f3e939621c37 100644
--- a/clang/include/clang/CIR/LoweringHelpers.h
+++ b/clang/include/clang/CIR/LoweringHelpers.h
@@ -35,7 +35,8 @@ convertToDenseElementsAttr(cir::ConstArrayAttr attr,
 
 std::optional<mlir::Attribute>
 lowerConstArrayAttr(cir::ConstArrayAttr constArr,
-                    const mlir::TypeConverter *converter);
+                    const mlir::TypeConverter *converter,
+                    mlir::ModuleOp moduleOp = {});
 
 mlir::Value getConstAPInt(mlir::OpBuilder &bld, mlir::Location loc,
                           mlir::Type typ, const llvm::APInt &val);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 2720dd2500a94..ddf4df9ff42bc 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -483,7 +483,6 @@ mlir::Value 
CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
   // Iteratively lower each constant element of the array.
   if (auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
     for (auto [idx, elt] : llvm::enumerate(arrayAttr)) {
-      mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
       mlir::Value init = visit(elt);
       result =
           mlir::LLVM::InsertValueOp::create(rewriter, loc, result, init, idx);
@@ -2510,6 +2509,25 @@ mlir::LogicalResult 
CIRToLLVMGlobalOpLowering::matchAndRewrite(
                          cir::ConstComplexAttr, cir::GlobalViewAttr,
                          cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
                          cir::VTableAttr, cir::ZeroAttr>(init.value())) {
+      if (auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(init.value())) {
+        if (!hasTrailingZeros(constArr)) {
+          mlir::Type elTy = constArr.getType();
+          while (auto arrTy = mlir::dyn_cast<cir::ArrayType>(elTy))
+            elTy = arrTy.getElementType();
+          if (mlir::isa<cir::PointerType>(elTy)) {
+            mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
+            if (std::optional<mlir::Attribute> bulkInit =
+                    lowerConstArrayAttr(constArr, typeConverter, module)) {
+              mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
+              rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
+                  op, llvmType, isConst, linkage, symbol, bulkInit.value(),
+                  alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr,
+                  attributes);
+              return mlir::success();
+            }
+          }
+        }
+      }
       // TODO(cir): once LLVM's dialect has proper equivalent attributes this
       // should be updated. For now, we use a custom op to initialize globals
       // to the appropriate value.
diff --git a/clang/lib/CIR/Lowering/LoweringHelpers.cpp 
b/clang/lib/CIR/Lowering/LoweringHelpers.cpp
index 0786579a601b1..5244b84548945 100644
--- a/clang/lib/CIR/Lowering/LoweringHelpers.cpp
+++ b/clang/lib/CIR/Lowering/LoweringHelpers.cpp
@@ -12,6 +12,8 @@
 
 #include "clang/CIR/LoweringHelpers.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
+#include "mlir/IR/SymbolTable.h"
 #include "clang/CIR/MissingFeatures.h"
 
 mlir::DenseElementsAttr
@@ -115,9 +117,71 @@ mlir::DenseElementsAttr convertToDenseElementsAttr(
       llvm::ArrayRef(values));
 }
 
+/// Return true when \p gv can be lowered to a \c FlatSymbolRefAttr leaf 
without
+/// addrspacecast or bitcast (mirrors \c CIRAttrToValue::visitCirAttr).
+static bool globalViewMatchesPointerLeaf(cir::GlobalViewAttr gv,
+                                         mlir::ModuleOp moduleOp,
+                                         const mlir::TypeConverter *converter) 
{
+  if (gv.getIndices() || mlir::isa<cir::IntType, cir::VPtrType>(gv.getType()))
+    return false;
+
+  auto ptrTy = mlir::dyn_cast<cir::PointerType>(gv.getType());
+  if (!ptrTy)
+    return false;
+
+  unsigned sourceAddrSpace = 0;
+  mlir::Type sourceType;
+  auto sourceSymbol =
+      mlir::SymbolTable::lookupSymbolIn(moduleOp, gv.getSymbol());
+  if (auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
+    sourceType = llvmSymbol.getType();
+    sourceAddrSpace = llvmSymbol.getAddrSpace();
+  } else if (auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(sourceSymbol)) {
+    sourceType = converter->convertType(cirSymbol.getSymType());
+    if (auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
+            cirSymbol.getAddrSpaceAttr()))
+      sourceAddrSpace = targetAS.getValue();
+  } else {
+    return false;
+  }
+
+  auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
+  if (llvmDstTy.getAddressSpace() != sourceAddrSpace)
+    return false;
+
+  mlir::Type llvmEltTy = converter->convertType(ptrTy.getPointee());
+  if (llvmEltTy == sourceType)
+    return true;
+  if (auto arrTy = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(sourceType))
+    return llvmEltTy == arrTy.getElementType();
+  return false;
+}
+
+/// Lower a single pointer-element of a \c cir.const_array to an LLVM-dialect
+/// constant leaf suitable for a bulk \c llvm.mlir.constant.  Only handles
+/// address-of-global without indices and null pointers; indexed global views
+/// must use the per-element \c llvm.insertvalue fallback.
+static std::optional<mlir::Attribute>
+lowerPointerElementAttr(mlir::Attribute elt, mlir::MLIRContext *ctx,
+                        mlir::ModuleOp moduleOp,
+                        const mlir::TypeConverter *converter) {
+  if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(elt)) {
+    if (!moduleOp || !globalViewMatchesPointerLeaf(gv, moduleOp, converter))
+      return std::nullopt;
+    return gv.getSymbol();
+  }
+  if (auto nullPtr = mlir::dyn_cast<cir::ConstPtrAttr>(elt)) {
+    if (nullPtr.isNullValue())
+      return mlir::LLVM::ZeroAttr::get(ctx);
+    return std::nullopt;
+  }
+  return std::nullopt;
+}
+
 std::optional<mlir::Attribute>
 lowerConstArrayAttr(cir::ConstArrayAttr constArr,
-                    const mlir::TypeConverter *converter) {
+                    const mlir::TypeConverter *converter,
+                    mlir::ModuleOp moduleOp) {
   // Ensure ConstArrayAttr has a type.
   const auto typedConstArr = mlir::cast<mlir::TypedAttr>(constArr);
 
@@ -132,6 +196,13 @@ lowerConstArrayAttr(cir::ConstArrayAttr constArr,
     type = arrayType.getElementType();
   }
 
+  if (auto eltsArr = mlir::dyn_cast<mlir::ArrayAttr>(constArr.getElts())) {
+    for (mlir::Attribute elt : eltsArr) {
+      if (mlir::isa<cir::PoisonAttr>(elt))
+        return std::nullopt;
+    }
+  }
+
   if (mlir::isa<mlir::StringAttr>(constArr.getElts()))
     return convertStringAttrToDenseElementsAttr(constArr,
                                                 converter->convertType(type));
@@ -143,6 +214,23 @@ lowerConstArrayAttr(cir::ConstArrayAttr constArr,
     return convertToDenseElementsAttr<cir::FPAttr, mlir::APFloat>(
         constArr, dims, type, converter->convertType(type));
 
+  if (mlir::isa<cir::PointerType>(type)) {
+    auto eltsArr = mlir::dyn_cast<mlir::ArrayAttr>(constArr.getElts());
+    if (!eltsArr)
+      return std::nullopt;
+    llvm::SmallVector<mlir::Attribute> lowered;
+    lowered.reserve(eltsArr.size());
+    mlir::MLIRContext *ctx = constArr.getContext();
+    for (mlir::Attribute elt : eltsArr) {
+      std::optional<mlir::Attribute> llvmElt =
+          lowerPointerElementAttr(elt, ctx, moduleOp, converter);
+      if (!llvmElt)
+        return std::nullopt;
+      lowered.push_back(*llvmElt);
+    }
+    return mlir::ArrayAttr::get(ctx, lowered);
+  }
+
   return std::nullopt;
 }
 
diff --git a/clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp 
b/clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp
new file mode 100644
index 0000000000000..ecb4fb8e4722d
--- /dev/null
+++ b/clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+const char *names[] = { "a", "b", "c" };
+int len() { return sizeof(names)/sizeof(*names); }
+
+// CIR: cir.global {{.*}}@names = #cir.const_array<[#cir.global_view<@".str"> 
: !cir.ptr<!s8i>, #cir.global_view<@".str.1"> : !cir.ptr<!s8i>, 
#cir.global_view<@".str.2"> : !cir.ptr<!s8i>]>
+
+// LLVM:       @names = {{.*}}global [3 x ptr] [ptr @.str{{.*}}, ptr 
@.str{{.*}}, ptr @.str{{.*}}]
+// LLVM-NOT:   insertvalue
+
+// OGCG:       @names = {{.*}}global [3 x ptr] [ptr @.str{{.*}}, ptr 
@.str{{.*}}, ptr @.str{{.*}}]
diff --git a/clang/test/CIR/Lowering/const-array-of-pointers.cir 
b/clang/test/CIR/Lowering/const-array-of-pointers.cir
new file mode 100644
index 0000000000000..47797c0cf3271
--- /dev/null
+++ b/clang/test/CIR/Lowering/const-array-of-pointers.cir
@@ -0,0 +1,18 @@
+// RUN: cir-opt %s --cir-to-llvm -o - | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.global "private" constant cir_private dso_local @g0 = #cir.int<0> : !s32i
+  cir.global "private" constant cir_private dso_local @g1 = #cir.int<1> : !s32i
+  cir.global "private" constant cir_private dso_local @g2 = #cir.int<2> : !s32i
+
+  cir.global constant external dso_local @ptrs = #cir.const_array<[
+      #cir.global_view<@g0> : !cir.ptr<!s32i>,
+      #cir.global_view<@g1> : !cir.ptr<!s32i>,
+      #cir.global_view<@g2> : !cir.ptr<!s32i>
+  ]> : !cir.array<!cir.ptr<!s32i> x 3>
+}
+
+// CHECK-LABEL: llvm.mlir.global external constant @ptrs(
+// CHECK-NOT:   llvm.insertvalue

>From 7c831ffdb94f4ed05caff5790a6b6e552fb99944 Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Wed, 20 May 2026 10:46:01 -0700
Subject: [PATCH 3/4] [CIR] Extend bulk const_array global lowering for review
 on #198427

Review follow-up: allow the fast llvm.mlir.global aggregate path for
const_array globals whose leaves are integers or floats (not only
pointers), document when bulk lowering is skipped, speed up
hasTrailingZeros on large arrays, recurse poison checks through nested
const_array attributes, and hoist const_array handling out of the
shared region-initializer branch.

Tests cover int and multi-dim int codegen, trailing-zero and
address-space mismatch fallbacks (mlir insertvalue regions), and
multi-dim int bulk lowering in cir-opt.
---
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 79 ++++++++++++-------
 clang/lib/CIR/Lowering/LoweringHelpers.cpp    | 24 ++++--
 .../global-pointer-array-fast-lowering.cpp    | 16 +++-
 .../const-array-bulk-lowering-fallbacks.cir   | 29 +++++++
 4 files changed, 113 insertions(+), 35 deletions(-)
 create mode 100644 
clang/test/CIR/Lowering/const-array-bulk-lowering-fallbacks.cir

diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index ddf4df9ff42bc..b14d4ae3a9051 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1958,13 +1958,33 @@ mlir::LogicalResult 
CIRToLLVMStoreOpLowering::matchAndRewrite(
   return mlir::LogicalResult::success();
 }
 
+static mlir::Type getConstArrayLeafType(mlir::Type ty) {
+  while (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
+    ty = arrTy.getElementType();
+  return ty;
+}
+
+static bool isBulkLowerableConstArrayLeaf(mlir::Type leafTy) {
+  return mlir::isa<cir::PointerType, cir::IntType, cir::FPTypeInterface>(
+      leafTy);
+}
+
 bool hasTrailingZeros(cir::ConstArrayAttr attr) {
-  auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
-  return attr.hasTrailingZeros() ||
-         (array && std::count_if(array.begin(), array.end(), [](auto elt) {
-            auto ar = dyn_cast<cir::ConstArrayAttr>(elt);
-            return ar && hasTrailingZeros(ar);
-          }));
+  if (attr.hasTrailingZeros())
+    return true;
+
+  auto elts = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
+  if (!elts)
+    return false;
+
+  auto cirArrTy = mlir::dyn_cast<cir::ArrayType>(attr.getType());
+  if (!cirArrTy || !mlir::isa<cir::ArrayType>(cirArrTy.getElementType()))
+    return false;
+
+  return llvm::any_of(elts, [](mlir::Attribute elt) {
+    auto nested = mlir::dyn_cast<cir::ConstArrayAttr>(elt);
+    return nested && hasTrailingZeros(nested);
+  });
 }
 
 mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
@@ -2504,30 +2524,33 @@ mlir::LogicalResult 
CIRToLLVMGlobalOpLowering::matchAndRewrite(
         op.emitError() << "unsupported initializer '" << init.value() << "'";
         return mlir::failure();
       }
-    } else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
-                         cir::ConstRecordAttr, cir::ConstPtrAttr,
-                         cir::ConstComplexAttr, cir::GlobalViewAttr,
-                         cir::TypeInfoAttr, cir::UndefAttr, cir::PoisonAttr,
-                         cir::VTableAttr, cir::ZeroAttr>(init.value())) {
-      if (auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(init.value())) {
-        if (!hasTrailingZeros(constArr)) {
-          mlir::Type elTy = constArr.getType();
-          while (auto arrTy = mlir::dyn_cast<cir::ArrayType>(elTy))
-            elTy = arrTy.getElementType();
-          if (mlir::isa<cir::PointerType>(elTy)) {
-            mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
-            if (std::optional<mlir::Attribute> bulkInit =
-                    lowerConstArrayAttr(constArr, typeConverter, module)) {
-              mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
-              rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
-                  op, llvmType, isConst, linkage, symbol, bulkInit.value(),
-                  alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr,
-                  attributes);
-              return mlir::success();
-            }
-          }
+    } else if (auto constArr =
+                   mlir::dyn_cast<cir::ConstArrayAttr>(init.value())) {
+      // Bulk-emit llvm.mlir.global when lowerConstArrayAttr can build the
+      // whole initializer as one aggregate attribute (no insertvalue
+      // region). Skip arrays with trailing-zero compression: those need
+      // per-element zero/undef setup. Leaf type must match what
+      // lowerConstArrayAttr handles (pointers, integers, floats today).
+      if (!hasTrailingZeros(constArr) &&
+          isBulkLowerableConstArrayLeaf(
+              getConstArrayLeafType(constArr.getType()))) {
+        mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>();
+        if (std::optional<mlir::Attribute> bulkInit =
+                lowerConstArrayAttr(constArr, typeConverter, module)) {
+          mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
+          rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
+              op, llvmType, isConst, linkage, symbol, bulkInit.value(),
+              alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr,
+              attributes);
+          return mlir::success();
         }
       }
+      return matchAndRewriteRegionInitializedGlobal(op, init.value(), 
rewriter);
+    } else if (mlir::isa<cir::ConstVectorAttr, cir::ConstRecordAttr,
+                         cir::ConstPtrAttr, cir::ConstComplexAttr,
+                         cir::GlobalViewAttr, cir::TypeInfoAttr, 
cir::UndefAttr,
+                         cir::PoisonAttr, cir::VTableAttr, cir::ZeroAttr>(
+                   init.value())) {
       // TODO(cir): once LLVM's dialect has proper equivalent attributes this
       // should be updated. For now, we use a custom op to initialize globals
       // to the appropriate value.
diff --git a/clang/lib/CIR/Lowering/LoweringHelpers.cpp 
b/clang/lib/CIR/Lowering/LoweringHelpers.cpp
index 5244b84548945..a89816949ef43 100644
--- a/clang/lib/CIR/Lowering/LoweringHelpers.cpp
+++ b/clang/lib/CIR/Lowering/LoweringHelpers.cpp
@@ -142,6 +142,8 @@ static bool 
globalViewMatchesPointerLeaf(cir::GlobalViewAttr gv,
             cirSymbol.getAddrSpaceAttr()))
       sourceAddrSpace = targetAS.getValue();
   } else {
+    // cir.func and other symbols not yet lowered to globals cannot be used as
+    // bulk constant leaves; those cases keep the insertvalue fallback.
     return false;
   }
 
@@ -178,6 +180,20 @@ lowerPointerElementAttr(mlir::Attribute elt, 
mlir::MLIRContext *ctx,
   return std::nullopt;
 }
 
+static bool containsPoison(mlir::Attribute attr) {
+  if (mlir::isa<cir::PoisonAttr>(attr))
+    return true;
+  if (auto elts = mlir::dyn_cast<mlir::ArrayAttr>(attr))
+    return llvm::any_of(elts, containsPoison);
+  if (auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(attr)) {
+    if (mlir::isa<mlir::StringAttr>(constArr.getElts()))
+      return false;
+    if (auto elts = mlir::dyn_cast<mlir::ArrayAttr>(constArr.getElts()))
+      return llvm::any_of(elts, containsPoison);
+  }
+  return false;
+}
+
 std::optional<mlir::Attribute>
 lowerConstArrayAttr(cir::ConstArrayAttr constArr,
                     const mlir::TypeConverter *converter,
@@ -196,12 +212,8 @@ lowerConstArrayAttr(cir::ConstArrayAttr constArr,
     type = arrayType.getElementType();
   }
 
-  if (auto eltsArr = mlir::dyn_cast<mlir::ArrayAttr>(constArr.getElts())) {
-    for (mlir::Attribute elt : eltsArr) {
-      if (mlir::isa<cir::PoisonAttr>(elt))
-        return std::nullopt;
-    }
-  }
+  if (containsPoison(constArr))
+    return std::nullopt;
 
   if (mlir::isa<mlir::StringAttr>(constArr.getElts()))
     return convertStringAttrToDenseElementsAttr(constArr,
diff --git a/clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp 
b/clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp
index ecb4fb8e4722d..1252ccfa72de1 100644
--- a/clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp
+++ b/clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp
@@ -6,7 +6,11 @@
 // RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
 
 const char *names[] = { "a", "b", "c" };
-int len() { return sizeof(names)/sizeof(*names); }
+const int table[] = { 0, 1, 2, 3 };
+const int matrix[2][2] = { { 1, 2 }, { 3, 4 } };
+int len() {
+  return sizeof(names) / sizeof(*names) + table[0] + matrix[1][1];
+}
 
 // CIR: cir.global {{.*}}@names = #cir.const_array<[#cir.global_view<@".str"> 
: !cir.ptr<!s8i>, #cir.global_view<@".str.1"> : !cir.ptr<!s8i>, 
#cir.global_view<@".str.2"> : !cir.ptr<!s8i>]>
 
@@ -14,3 +18,13 @@ int len() { return sizeof(names)/sizeof(*names); }
 // LLVM-NOT:   insertvalue
 
 // OGCG:       @names = {{.*}}global [3 x ptr] [ptr @.str{{.*}}, ptr 
@.str{{.*}}, ptr @.str{{.*}}]
+
+// CIR: cir.global {{.*}}table = #cir.const_array<[#cir.int<0> : !s32i, 
#cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i]>
+// LLVM:       {{.*}}table{{.*}} = {{.*}}constant [4 x i32] [i32 0, i32 1, i32 
2, i32 3]
+// LLVM-NOT:   insertvalue
+// OGCG:       {{.*}}table{{.*}} = {{.*}}constant [4 x i32] [i32 0, i32 1, i32 
2, i32 3]
+
+// CIR: cir.global {{.*}}matrix = #cir.const_array<
+// LLVM:       {{.*}}matrix{{.*}} = {{.*}}constant [2 x [2 x i32]]
+// LLVM-NOT:   insertvalue
+// OGCG:       {{.*}}matrix{{.*}} = {{.*}}constant [2 x [2 x i32]]
diff --git a/clang/test/CIR/Lowering/const-array-bulk-lowering-fallbacks.cir 
b/clang/test/CIR/Lowering/const-array-bulk-lowering-fallbacks.cir
new file mode 100644
index 0000000000000..1e305e64c86d2
--- /dev/null
+++ b/clang/test/CIR/Lowering/const-array-bulk-lowering-fallbacks.cir
@@ -0,0 +1,29 @@
+// RUN: cir-opt %s --cir-to-llvm -o - | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+!s8i = !cir.int<s, 8>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.global external @tz_arr =
+      #cir.const_array<"ab" : !cir.array<!s8i x 2>, trailing_zeros> :
+      !cir.array<!s8i x 8>
+
+  cir.global external target_address_space(1) @as1 = #cir.int<1> : !s32i
+  cir.global external @as_mismatch =
+      #cir.const_array<[#cir.global_view<@as1> : !cir.ptr<!s32i>]> :
+      !cir.array<!cir.ptr<!s32i> x 1>
+
+  cir.global external @matrix = #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.array<!cir.array<!s32i x 2> x 2>
+}
+
+// CHECK-LABEL: llvm.mlir.global external @tz_arr
+// CHECK:       llvm.insertvalue
+
+// CHECK-LABEL: llvm.mlir.global external @as_mismatch
+// CHECK:       llvm.insertvalue
+
+// CHECK-LABEL: llvm.mlir.global external @matrix(
+// CHECK-SAME:    dense<

>From 8fa2f0d6a94afc6425a969d69ea6dcad8f2d0635 Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Wed, 20 May 2026 13:03:47 -0700
Subject: [PATCH 4/4] [CIR] Add bool bulk globals and #198427 fallback tests

Extend bulk const_array global lowering to cir.bool leaves and add
review-requested coverage: multi-dim pointer-array insertvalue fallback
(@ptr2d) and bool constant-array codegen without insertvalue chains.
---
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  6 +++---
 clang/lib/CIR/Lowering/LoweringHelpers.cpp    | 13 +++++++++++-
 .../global-pointer-array-fast-lowering.cpp    |  9 ++++++++-
 .../const-array-bulk-lowering-fallbacks.cir   | 20 +++++++++++++++++++
 4 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index b14d4ae3a9051..ba0b62ed710d1 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1965,8 +1965,8 @@ static mlir::Type getConstArrayLeafType(mlir::Type ty) {
 }
 
 static bool isBulkLowerableConstArrayLeaf(mlir::Type leafTy) {
-  return mlir::isa<cir::PointerType, cir::IntType, cir::FPTypeInterface>(
-      leafTy);
+  return mlir::isa<cir::PointerType, cir::IntType, cir::BoolType,
+                   cir::FPTypeInterface>(leafTy);
 }
 
 bool hasTrailingZeros(cir::ConstArrayAttr attr) {
@@ -2530,7 +2530,7 @@ mlir::LogicalResult 
CIRToLLVMGlobalOpLowering::matchAndRewrite(
       // whole initializer as one aggregate attribute (no insertvalue
       // region). Skip arrays with trailing-zero compression: those need
       // per-element zero/undef setup. Leaf type must match what
-      // lowerConstArrayAttr handles (pointers, integers, floats today).
+      // lowerConstArrayAttr handles (pointers, integers, bools, floats).
       if (!hasTrailingZeros(constArr) &&
           isBulkLowerableConstArrayLeaf(
               getConstArrayLeafType(constArr.getType()))) {
diff --git a/clang/lib/CIR/Lowering/LoweringHelpers.cpp 
b/clang/lib/CIR/Lowering/LoweringHelpers.cpp
index a89816949ef43..3f6b9ac0dcdf4 100644
--- a/clang/lib/CIR/Lowering/LoweringHelpers.cpp
+++ b/clang/lib/CIR/Lowering/LoweringHelpers.cpp
@@ -35,7 +35,8 @@ convertStringAttrToDenseElementsAttr(cir::ConstArrayAttr attr,
 }
 
 template <> mlir::APInt getZeroInitFromType(mlir::Type ty) {
-  assert(mlir::isa<cir::IntType>(ty) && "expected int type");
+  if (mlir::isa<cir::BoolType>(ty))
+    return mlir::APInt::getZero(1);
   const auto intTy = mlir::cast<cir::IntType>(ty);
   return mlir::APInt::getZero(intTy.getWidth());
 }
@@ -80,6 +81,12 @@ void convertToDenseElementsAttrImpl(
 
   auto arrayAttr = mlir::cast<mlir::ArrayAttr>(attr.getElts());
   for (auto eltAttr : arrayAttr) {
+    if (auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(eltAttr)) {
+      if constexpr (std::is_same_v<StorageTy, mlir::APInt>) {
+        values[currentIndex++] = mlir::APInt(1, (uint64_t)boolAttr.getValue());
+        continue;
+      }
+    }
     if (auto valueAttr = mlir::dyn_cast<AttrTy>(eltAttr)) {
       values[currentIndex++] = valueAttr.getValue();
       continue;
@@ -222,6 +229,10 @@ lowerConstArrayAttr(cir::ConstArrayAttr constArr,
     return convertToDenseElementsAttr<cir::IntAttr, mlir::APInt>(
         constArr, dims, type, converter->convertType(type));
 
+  if (mlir::isa<cir::BoolType>(type))
+    return convertToDenseElementsAttr<cir::IntAttr, mlir::APInt>(
+        constArr, dims, type, converter->convertType(type));
+
   if (mlir::isa<cir::FPTypeInterface>(type))
     return convertToDenseElementsAttr<cir::FPAttr, mlir::APFloat>(
         constArr, dims, type, converter->convertType(type));
diff --git a/clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp 
b/clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp
index 1252ccfa72de1..8cab446ad63ac 100644
--- a/clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp
+++ b/clang/test/CIR/CodeGen/global-pointer-array-fast-lowering.cpp
@@ -8,8 +8,10 @@
 const char *names[] = { "a", "b", "c" };
 const int table[] = { 0, 1, 2, 3 };
 const int matrix[2][2] = { { 1, 2 }, { 3, 4 } };
+const bool flags[] = { true, false, true };
 int len() {
-  return sizeof(names) / sizeof(*names) + table[0] + matrix[1][1];
+  return sizeof(names) / sizeof(*names) + table[0] + matrix[1][1] +
+         flags[2];
 }
 
 // CIR: cir.global {{.*}}@names = #cir.const_array<[#cir.global_view<@".str"> 
: !cir.ptr<!s8i>, #cir.global_view<@".str.1"> : !cir.ptr<!s8i>, 
#cir.global_view<@".str.2"> : !cir.ptr<!s8i>]>
@@ -28,3 +30,8 @@ int len() {
 // LLVM:       {{.*}}matrix{{.*}} = {{.*}}constant [2 x [2 x i32]]
 // LLVM-NOT:   insertvalue
 // OGCG:       {{.*}}matrix{{.*}} = {{.*}}constant [2 x [2 x i32]]
+
+// CIR: cir.global {{.*}}flags = #cir.const_array<[#true, #false, #true]> : 
!cir.array<!cir.bool x 3>
+// LLVM:       {{.*}}flags{{.*}} = {{.*}}constant [3 x i8]
+// LLVM-NOT:   insertvalue
+// OGCG:       {{.*}}flags{{.*}} = {{.*}}constant [3 x i8]
diff --git a/clang/test/CIR/Lowering/const-array-bulk-lowering-fallbacks.cir 
b/clang/test/CIR/Lowering/const-array-bulk-lowering-fallbacks.cir
index 1e305e64c86d2..41864da616e3c 100644
--- a/clang/test/CIR/Lowering/const-array-bulk-lowering-fallbacks.cir
+++ b/clang/test/CIR/Lowering/const-array-bulk-lowering-fallbacks.cir
@@ -17,6 +17,23 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
       #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.array<!cir.array<!s32i x 2> x 2>
+
+  cir.global "private" constant cir_private dso_local @s0 =
+      #cir.const_array<"x" : !cir.array<!s8i x 1>, trailing_zeros> :
+      !cir.array<!s8i x 2>
+  cir.global "private" constant cir_private dso_local @s1 =
+      #cir.const_array<"y" : !cir.array<!s8i x 1>, trailing_zeros> :
+      !cir.array<!s8i x 2>
+  cir.global external @ptr2d = #cir.const_array<[
+      #cir.const_array<[
+          #cir.global_view<@s0> : !cir.ptr<!s8i>,
+          #cir.global_view<@s1> : !cir.ptr<!s8i>
+      ]> : !cir.array<!cir.ptr<!s8i> x 2>,
+      #cir.const_array<[
+          #cir.global_view<@s0> : !cir.ptr<!s8i>,
+          #cir.global_view<@s1> : !cir.ptr<!s8i>
+      ]> : !cir.array<!cir.ptr<!s8i> x 2>
+  ]> : !cir.array<!cir.array<!cir.ptr<!s8i> x 2> x 2>
 }
 
 // CHECK-LABEL: llvm.mlir.global external @tz_arr
@@ -27,3 +44,6 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
 
 // CHECK-LABEL: llvm.mlir.global external @matrix(
 // CHECK-SAME:    dense<
+
+// CHECK-LABEL: llvm.mlir.global external @ptr2d
+// CHECK:       llvm.insertvalue

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

Reply via email to