[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