[Mlir-commits] [mlir] [LLVMIR] Directly lower global initializer GEP to constant expression (PR #226904)

Nikita Popov llvmlistbot at llvm.org
Mon Sep 28 00:17:45 PDT 2026


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/226904

MLIR lowers global initializers in a very unusual way, by using an IRBuilder without insertion point, and relying on the fact that for a well-formed initializer, all the instructions will be converted to constant expressions and no actual instructions that require insertion will be produced.

This causes issues for https://github.com/llvm/llvm-project/pull/226425, which requires an insertion point for CreateGEP to determine the data layout.

To avoid this, make convertGEPOp() directly produce a constant expression GEP if there is no insertion point, reusing the existing code path for inrange GEPs.

>From c0bdb9a7811b2c0dc376a4cff246af22c6af29e9 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 28 Sep 2026 09:00:14 +0200
Subject: [PATCH] [LLVMIR] Directly lower global initializer GEP to constant
 expression

---
 .../LLVMIR/LLVMToLLVMIRTranslation.cpp        | 22 ++++++++++++-------
 mlir/test/Target/LLVMIR/llvmir-invalid.mlir   |  4 ++--
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 3f83a5f7f22ce..1a9dd3d260ee1 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -253,15 +253,23 @@ static LogicalResult convertGEPOp(GEPOp op, llvm::IRBuilderBase &builder,
   llvm::Type *elementType = moduleTranslation.convertType(op.getElemType());
   llvm::GEPNoWrapFlags nwFlags =
       llvm::GEPNoWrapFlags::fromRaw(static_cast<unsigned>(op.getNoWrapFlags()));
+  ConstantRangeAttr inrangeAttr = op.getInrangeAttr();
   llvm::Value *base = moduleTranslation.lookupValue(op.getBase());
   llvm::Value *res;
-  if (ConstantRangeAttr inrangeAttr = op.getInrangeAttr()) {
+  if (inrangeAttr || !builder.GetInsertPoint().isValid()) {
+    StringRef WhyConstExpr =
+        inrangeAttr ? "'inrange' GEP" : "global initializer GEP";
     auto *baseConst = dyn_cast<llvm::Constant>(base);
     if (!baseConst || !llvm::all_of(indices, [](llvm::Value *value) {
           return isa<llvm::Constant>(value);
         }))
-      return op.emitError("'inrange' requires the base and indices to "
-                          "translate to LLVM constants");
+      return op.emitError(WhyConstExpr + " requires the base and indices to "
+                                         "translate to LLVM constants");
+
+    std::optional<llvm::ConstantRange> inrangeCR;
+    if (inrangeAttr)
+      inrangeCR = llvm::ConstantRange::getNonEmpty(inrangeAttr.getLower(),
+                                                   inrangeAttr.getUpper());
 
     SmallVector<llvm::Constant *> constIndices;
     constIndices.reserve(indices.size());
@@ -270,12 +278,10 @@ static LogicalResult convertGEPOp(GEPOp op, llvm::IRBuilderBase &builder,
     const llvm::DataLayout &dataLayout =
         moduleTranslation.getLLVMModule()->getDataLayout();
     res = llvm::ConstantExpr::getGetElementPtr(
-        dataLayout, elementType, baseConst, constIndices, nwFlags,
-        llvm::ConstantRange::getNonEmpty(inrangeAttr.getLower(),
-                                         inrangeAttr.getUpper()));
+        dataLayout, elementType, baseConst, constIndices, nwFlags, inrangeCR);
     if (!res)
-      return op.emitError(
-          "failed to lower 'inrange' GEP to a constant byte offset");
+      return op.emitError("failed to lower " + WhyConstExpr +
+                          " to a constant byte offset");
   } else {
     res = builder.CreateGEP(elementType, base, indices, "", nwFlags);
   }
diff --git a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
index c6bd08fad0585..b9ea9f6c9ace4 100644
--- a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
@@ -1,7 +1,7 @@
 // RUN: mlir-translate -verify-diagnostics -split-input-file -mlir-to-llvmir %s
 
 llvm.func @gep_inrange_nonconstant_base(%ptr: !llvm.ptr) -> !llvm.ptr {
-  // expected-error @below{{'inrange' requires the base and indices to translate to LLVM constants}}
+  // expected-error @below{{'inrange' GEP requires the base and indices to translate to LLVM constants}}
   // expected-error @below{{LLVM Translation failed for operation: llvm.getelementptr}}
   %0 = llvm.getelementptr inrange <i64, -4, 4> %ptr[0] : (!llvm.ptr) -> !llvm.ptr, i8
   llvm.return %0 : !llvm.ptr
@@ -13,7 +13,7 @@ llvm.mlir.global external @gep_base() : i8
 
 llvm.func @gep_inrange_nonconstant_index(%idx: i64) -> !llvm.ptr {
   %addr = llvm.mlir.addressof @gep_base : !llvm.ptr
-  // expected-error @below{{'inrange' requires the base and indices to translate to LLVM constants}}
+  // expected-error @below{{'inrange' GEP requires the base and indices to translate to LLVM constants}}
   // expected-error @below{{LLVM Translation failed for operation: llvm.getelementptr}}
   %0 = llvm.getelementptr inrange <i64, -4, 4> %addr[%idx] : (!llvm.ptr, i64) -> !llvm.ptr, i8
   llvm.return %0 : !llvm.ptr



More information about the Mlir-commits mailing list