[Mlir-commits] [mlir] [MLIR][LLVMIR] Restore constant folding for global initializer GEPs (PR #227651)

Henrich Lauko llvmlistbot at llvm.org
Wed Sep 30 04:02:32 PDT 2026


https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/227651

>From c73e88a3347063b9cb944c780fce51fdeb846d94 Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Wed, 30 Sep 2026 10:36:00 +0000
Subject: [PATCH] [MLIR][LLVMIR] Restore constant folding for global
 initializer GEPs

Before #226904, a GEP in a global initializer went through
IRBuilder::CreateGEP, and MLIR's IRBuilder<TargetFolder> folded the result
with ConstantFoldConstant. That combines nested GEPs, folds null and integer
bases, and infers inbounds and nuw when the offset stays within the global.
Building the constant expression directly skipped the folder, so the output
lost those flags.

Fold the constant again for the non-inrange case. The inrange path never
went through the folder and is unchanged.

CIR's vtable, VTT and constant pointer tests check for the inferred flags
(for example CIR/CodeGen/vtt.cpp) and have failed since #226904.

Assisted-by: Claude Code (Claude Fable 5.1).
---
 mlir/lib/Target/LLVMIR/Dialect/LLVMIR/CMakeLists.txt   |  1 +
 .../LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp  |  5 +++++
 mlir/test/Target/LLVMIR/llvmir.mlir                    | 10 ++++++++++
 3 files changed, 16 insertions(+)

diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/CMakeLists.txt
index 616b9fc0fbbaf..99fc9af060083 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/CMakeLists.txt
@@ -20,6 +20,7 @@ add_mlir_translation_library(MLIRLLVMToLLVMIRTranslation
   LLVMToLLVMIRTranslation.cpp
 
   LINK_COMPONENTS
+  Analysis
   Core
 
   LINK_LIBS PUBLIC
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 1a9dd3d260ee1..50e3b59af3cb6 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -19,6 +19,7 @@
 #include "mlir/Target/LLVMIR/ModuleTranslation.h"
 
 #include "llvm/ADT/TypeSwitch.h"
+#include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/IR/ConstantRange.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DIBuilder.h"
@@ -282,6 +283,10 @@ static LogicalResult convertGEPOp(GEPOp op, llvm::IRBuilderBase &builder,
     if (!res)
       return op.emitError("failed to lower " + WhyConstExpr +
                           " to a constant byte offset");
+    // Fold the constant as CreateGEP did through the TargetFolder. This also
+    // infers inbounds and nuw when the offset stays within the global.
+    if (!inrangeAttr)
+      res = llvm::ConstantFoldConstant(cast<llvm::Constant>(res), dataLayout);
   } else {
     res = builder.CreateGEP(elementType, base, indices, "", nwFlags);
   }
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index 5557788b039f7..4c1b00b33bcfd 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -122,6 +122,16 @@ llvm.mlir.global internal constant @int_gep() : !llvm.ptr {
   llvm.return %gepinit : !llvm.ptr
 }
 
+// CHECK: @i32_array = internal constant [4 x i32] [i32 1, i32 2, i32 3, i32 4]
+llvm.mlir.global internal constant @i32_array(dense<[1, 2, 3, 4]> : tensor<4xi32>) : !llvm.array<4 x i32>
+// The offset is within the global, so the folder infers inbounds and nuw.
+// CHECK: @int_gep_inferred_flags = internal constant ptr getelementptr inbounds nuw (i8, ptr @i32_array, i64 8)
+llvm.mlir.global internal constant @int_gep_inferred_flags() : !llvm.ptr {
+  %addr = llvm.mlir.addressof @i32_array : !llvm.ptr
+  %gepinit = llvm.getelementptr %addr[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>
+  llvm.return %gepinit : !llvm.ptr
+}
+
 // CHECK: @vt = external constant { [3 x ptr] }
 llvm.mlir.global external constant @vt() : !llvm.struct<(array<3 x ptr>)>
 // CHECK: @int_gep_inrange = internal constant ptr getelementptr inbounds inrange(-16, 8) (i8, ptr @vt, i64 16)



More information about the Mlir-commits mailing list