[Mlir-commits] [mlir] [mlir][LowerToLLVM] Pass DataLayoutAnalysis to LowerToLLVMOptions in `ArithToLLVM`, `ControlFlowToLLVM`, and `VectorToLLVM` passes (PR #206380)

Federico Bruzzone llvmlistbot at llvm.org
Wed Aug 5 03:17:08 PDT 2026


https://github.com/FedericoBruzzone updated https://github.com/llvm/llvm-project/pull/206380

>From 305f638bb0911c2e2926a76e262710bac00e1746 Mon Sep 17 00:00:00 2001
From: Federico Bruzzone <federico.bruzzone.i at gmail.com>
Date: Mon, 29 Jun 2026 01:54:40 +0200
Subject: [PATCH 1/3] [mlir][conversion] Pass DataLayoutAnalysis to
 LowerToLLVMOptions in `ArithToLLVM`, `ControlFlowToLLVM`, and `VectorToLLVM`
 passes

Signed-off-by: Federico Bruzzone <federico.bruzzone.i at gmail.com>
---
 .../Conversion/ArithToLLVM/ArithToLLVM.cpp    |  7 +-
 .../lib/Conversion/ArithToLLVM/CMakeLists.txt |  2 +
 .../ControlFlowToLLVM/CMakeLists.txt          |  1 +
 .../ControlFlowToLLVM/ControlFlowToLLVM.cpp   |  7 +-
 .../Conversion/VectorToLLVM/CMakeLists.txt    |  2 +
 .../VectorToLLVM/ConvertVectorToLLVMPass.cpp  | 10 ++-
 .../arith-to-llvm-32bit-index.mlir            | 74 ++++++++++++++++++
 .../ControlFlowToLLVM/branch-32bit-index.mlir | 65 ++++++++++++++++
 ...vector-load-store-32bit-index-to-llvm.mlir | 76 +++++++++++++++++++
 9 files changed, 238 insertions(+), 6 deletions(-)
 create mode 100644 mlir/test/Conversion/ArithToLLVM/arith-to-llvm-32bit-index.mlir
 create mode 100644 mlir/test/Conversion/ControlFlowToLLVM/branch-32bit-index.mlir
 create mode 100644 mlir/test/Conversion/VectorToLLVM/vector-load-store-32bit-index-to-llvm.mlir

diff --git a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
index 6bf0fe85bb62f..64f6358dd938d 100644
--- a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
+++ b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
@@ -8,6 +8,7 @@
 
 #include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"
 
+#include "mlir/Analysis/DataLayoutAnalysis.h"
 #include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h"
 #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h"
 #include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
@@ -710,11 +711,13 @@ struct ArithToLLVMConversionPass
     LLVMConversionTarget target(getContext());
     RewritePatternSet patterns(&getContext());
 
-    LowerToLLVMOptions options(&getContext());
+    const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
+    LowerToLLVMOptions options(&getContext(),
+                               dataLayoutAnalysis.getAtOrAbove(getOperation()));
     if (indexBitwidth != kDeriveIndexBitwidthFromDataLayout)
       options.overrideIndexBitwidth(indexBitwidth);
 
-    LLVMTypeConverter converter(&getContext(), options);
+    LLVMTypeConverter converter(&getContext(), options, &dataLayoutAnalysis);
     arith::populateCeilFloorDivExpandOpsPatterns(patterns);
     arith::populateArithToLLVMConversionPatterns(converter, patterns);
 
diff --git a/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt b/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
index 0a0e25e18b47a..8fdfa991a35d3 100644
--- a/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
+++ b/mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt
@@ -14,6 +14,8 @@ add_mlir_conversion_library(MLIRArithToLLVM
   MLIRArithAttrToLLVMConversion
   MLIRArithDialect
   MLIRArithTransforms
+  MLIRAnalysis
+  MLIRDataLayoutInterfaces
   MLIRLLVMCommonConversion
   MLIRLLVMDialect
   )
diff --git a/mlir/lib/Conversion/ControlFlowToLLVM/CMakeLists.txt b/mlir/lib/Conversion/ControlFlowToLLVM/CMakeLists.txt
index dcc78c8367a43..b36c85165d234 100644
--- a/mlir/lib/Conversion/ControlFlowToLLVM/CMakeLists.txt
+++ b/mlir/lib/Conversion/ControlFlowToLLVM/CMakeLists.txt
@@ -13,6 +13,7 @@ add_mlir_conversion_library(MLIRControlFlowToLLVM
 
   LINK_LIBS PUBLIC
   MLIRAnalysis
+  MLIRDataLayoutInterfaces
   MLIRControlFlowDialect
   MLIRLLVMCommonConversion
   MLIRLLVMDialect
diff --git a/mlir/lib/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.cpp b/mlir/lib/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.cpp
index fef78a46d69fc..e3d26cb68859b 100644
--- a/mlir/lib/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.cpp
+++ b/mlir/lib/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.cpp
@@ -13,6 +13,7 @@
 
 #include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
 
+#include "mlir/Analysis/DataLayoutAnalysis.h"
 #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h"
 #include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
 #include "mlir/Conversion/LLVMCommon/Pattern.h"
@@ -273,11 +274,13 @@ struct ConvertControlFlowToLLVM
              ctx->getLoadedDialect<cf::ControlFlowDialect>();
     });
 
-    LowerToLLVMOptions options(ctx);
+    const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
+    LowerToLLVMOptions options(ctx,
+                               dataLayoutAnalysis.getAtOrAbove(getOperation()));
     if (indexBitwidth != kDeriveIndexBitwidthFromDataLayout)
       options.overrideIndexBitwidth(indexBitwidth);
 
-    LLVMTypeConverter converter(ctx, options);
+    LLVMTypeConverter converter(ctx, options, &dataLayoutAnalysis);
     RewritePatternSet patterns(ctx);
     mlir::cf::populateControlFlowToLLVMConversionPatterns(converter, patterns);
     mlir::cf::populateAssertToLLVMConversionPattern(converter, patterns);
diff --git a/mlir/lib/Conversion/VectorToLLVM/CMakeLists.txt b/mlir/lib/Conversion/VectorToLLVM/CMakeLists.txt
index 0d700ea65eb4e..ea1a1de75f9bf 100644
--- a/mlir/lib/Conversion/VectorToLLVM/CMakeLists.txt
+++ b/mlir/lib/Conversion/VectorToLLVM/CMakeLists.txt
@@ -38,6 +38,8 @@ add_mlir_conversion_library(MLIRVectorToLLVMPass
   MLIRArmNeonTransforms
   MLIRArmSVEDialect
   MLIRArmSVETransforms
+  MLIRAnalysis
+  MLIRDataLayoutInterfaces
   MLIRX86Dialect
   MLIRX86Transforms
 )
diff --git a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVMPass.cpp b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVMPass.cpp
index 2b358d312dcfe..d80769ec4dc0b 100644
--- a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVMPass.cpp
+++ b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVMPass.cpp
@@ -8,6 +8,7 @@
 
 #include "mlir/Conversion/VectorToLLVM/ConvertVectorToLLVMPass.h"
 
+#include "mlir/Analysis/DataLayoutAnalysis.h"
 #include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
 #include "mlir/Conversion/LLVMCommon/TypeConverter.h"
 #include "mlir/Dialect/Arith/IR/Arith.h"
@@ -108,8 +109,13 @@ void ConvertVectorToLLVMPass::runOnOperation() {
   }
 
   // Convert to the LLVM IR dialect.
-  LowerToLLVMOptions options(&getContext());
-  LLVMTypeConverter converter(&getContext(), options);
+  // Use the module's data layout so that the index bitwidth is derived from the
+  // target (e.g. i32 on 32-bit targets) rather than hard-wired to i64, which
+  // mirrors what FinalizeMemRefToLLVMConversionPass does.
+  const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
+  LowerToLLVMOptions options(&getContext(),
+                             dataLayoutAnalysis.getAtOrAbove(getOperation()));
+  LLVMTypeConverter converter(&getContext(), options, &dataLayoutAnalysis);
   RewritePatternSet patterns(&getContext());
   populateVectorTransferLoweringPatterns(patterns);
   populateVectorToLLVMConversionPatterns(
diff --git a/mlir/test/Conversion/ArithToLLVM/arith-to-llvm-32bit-index.mlir b/mlir/test/Conversion/ArithToLLVM/arith-to-llvm-32bit-index.mlir
new file mode 100644
index 0000000000000..85b0324388b8a
--- /dev/null
+++ b/mlir/test/Conversion/ArithToLLVM/arith-to-llvm-32bit-index.mlir
@@ -0,0 +1,74 @@
+// RUN: mlir-opt %s --convert-arith-to-llvm -split-input-file | FileCheck %s
+
+// Verify that ArithToLLVMConversionPass respects the module's data layout
+// when deriving the index type.  When the module declares a 32-bit index via
+// dlti.dl_spec, index constants and index arithmetic ops must be emitted as
+// i32 instead of the default i64.
+
+// -----
+
+// 32-bit data layout: arith.constant with index type -> i32 constant.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @constant_index_32bit() -> index {
+  %c0 = arith.constant 0 : index
+  return %c0 : index
+}
+
+}
+
+// CHECK-LABEL: func @constant_index_32bit
+// CHECK: llvm.mlir.constant(0 : index) : i32
+
+// -----
+
+// 32-bit data layout: arith.cmpi on index type -> icmp on i32.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @cmpi_index_32bit(%a: index, %b: index) -> i1 {
+  %cmp = arith.cmpi slt, %a, %b : index
+  return %cmp : i1
+}
+
+}
+
+// CHECK-LABEL: func @cmpi_index_32bit
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK: llvm.icmp "slt" %{{.*}}, %{{.*}} : i32
+
+// -----
+
+// 32-bit data layout: arith.addi on index type -> add on i32.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @addi_index_32bit(%a: index, %b: index) -> index {
+  %add = arith.addi %a, %b : index
+  return %add : index
+}
+
+}
+
+// CHECK-LABEL: func @addi_index_32bit
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK: llvm.add %{{.*}}, %{{.*}} : i32
+
+// -----
+
+// Without dlti.dl_spec the default index width (i64) is preserved.
+
+module {
+
+func.func @constant_index_default() -> index {
+  %c0 = arith.constant 0 : index
+  return %c0 : index
+}
+
+}
+
+// CHECK-LABEL: func @constant_index_default
+// CHECK: llvm.mlir.constant(0 : index) : i64
diff --git a/mlir/test/Conversion/ControlFlowToLLVM/branch-32bit-index.mlir b/mlir/test/Conversion/ControlFlowToLLVM/branch-32bit-index.mlir
new file mode 100644
index 0000000000000..fcb32bc86a69d
--- /dev/null
+++ b/mlir/test/Conversion/ControlFlowToLLVM/branch-32bit-index.mlir
@@ -0,0 +1,65 @@
+// RUN: mlir-opt %s --convert-cf-to-llvm -split-input-file | FileCheck %s
+
+// Verify that ConvertControlFlowToLLVMPass respects the module's data layout
+// when deriving the index type for block arguments.  When the module declares
+// a 32-bit index via dlti.dl_spec, cf.br and cf.cond_br must pass index-typed
+// block arguments as i32 instead of the default i64.
+
+// -----
+
+// 32-bit data layout: cf.br with index block argument -> i32 branch arg.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @cf_br_index_32bit(%arg0: index) -> index {
+  cf.br ^bb1(%arg0 : index)
+^bb1(%a: index):
+  return %a : index
+}
+
+}
+
+// CHECK-LABEL: func @cf_br_index_32bit
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK: llvm.br ^{{.*}}(%{{.*}} : i32)
+// CHECK: ^{{.*}}(%{{.*}}: i32):
+
+// -----
+
+// 32-bit data layout: cf.cond_br with index block arguments -> i32 branch args.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @cf_cond_br_index_32bit(%cond: i1, %a: index, %b: index) -> index {
+  cf.cond_br %cond, ^bb1(%a : index), ^bb2(%b : index)
+^bb1(%x: index):
+  return %x : index
+^bb2(%y: index):
+  return %y : index
+}
+
+}
+
+// CHECK-LABEL: func @cf_cond_br_index_32bit
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK: llvm.cond_br %{{.*}}, ^{{.*}}(%{{.*}} : i32), ^{{.*}}(%{{.*}} : i32)
+
+// -----
+
+// Without dlti.dl_spec the default index width (i64) is preserved.
+
+module {
+
+func.func @cf_br_index_default(%arg0: index) -> index {
+  cf.br ^bb1(%arg0 : index)
+^bb1(%a: index):
+  return %a : index
+}
+
+}
+
+// CHECK-LABEL: func @cf_br_index_default
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i64
+// CHECK: llvm.br ^{{.*}}(%{{.*}} : i64)
+// CHECK: ^{{.*}}(%{{.*}}: i64):
diff --git a/mlir/test/Conversion/VectorToLLVM/vector-load-store-32bit-index-to-llvm.mlir b/mlir/test/Conversion/VectorToLLVM/vector-load-store-32bit-index-to-llvm.mlir
new file mode 100644
index 0000000000000..29496be37322f
--- /dev/null
+++ b/mlir/test/Conversion/VectorToLLVM/vector-load-store-32bit-index-to-llvm.mlir
@@ -0,0 +1,76 @@
+// RUN: mlir-opt %s -convert-vector-to-llvm -split-input-file | FileCheck %s --check-prefixes=ALL,DEFAULT
+// RUN: mlir-opt %s -convert-vector-to-llvm='enable-gep-inbounds-nuw=1' -split-input-file | FileCheck %s --check-prefixes=ALL,INBOUNDS
+
+// Verify that ConvertVectorToLLVMPass respects the module's data layout when
+// deriving the index type. When the module declares a 32-bit index (via
+// dlti.dl_spec), GEP arithmetic should be emitted in i32 instead of the
+// default i64.  This also makes enable-gep-inbounds-nuw meaningful on 32-bit
+// targets: the flag emits nsw/nuw on the *narrow* i32 multiply, allowing SCEV
+// to form a clean 32-bit AddRec and enabling LSR to use direct pointer
+// induction instead of per-iteration sign/zero extension.
+
+// -----
+
+// 32-bit data layout: index -> i32 in GEP arithmetic.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @load_32bit_index(%memref : memref<200x100xf32>, %i : index, %j : index) -> vector<8xf32> {
+  %0 = vector.load %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>
+  return %0 : vector<8xf32>
+}
+
+}
+
+// ALL-LABEL: func @load_32bit_index
+// ALL: %[[C100:.*]] = llvm.mlir.constant(100 : index) : i32
+// ALL: %[[MUL:.*]] = llvm.mul %{{.*}}, %[[C100]]
+// ALL: %[[ADD:.*]] = llvm.add %[[MUL]], %{{.*}}
+// DEFAULT: %[[GEP:.*]] = llvm.getelementptr %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
+// INBOUNDS: %[[GEP:.*]] = llvm.getelementptr inbounds|nuw %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
+// ALL: llvm.load %[[GEP]] {alignment = 4 : i64} : !llvm.ptr -> vector<8xf32>
+
+// -----
+
+// With enable-gep-inbounds-nuw, the narrow i32 multiply and add carry
+// nsw/nuw flags, enabling SCEV to form a clean 32-bit AddRec.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @load_32bit_index_nuw_mul(%memref : memref<200x100xf32>, %i : index, %j : index) -> vector<8xf32> {
+  %0 = vector.load %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>
+  return %0 : vector<8xf32>
+}
+
+}
+
+// DEFAULT-LABEL: func @load_32bit_index_nuw_mul
+// DEFAULT: llvm.mul %{{.*}}, %{{.*}} : i32
+// DEFAULT: llvm.add %{{.*}}, %{{.*}} : i32
+// DEFAULT: llvm.getelementptr %{{.*}} : (!llvm.ptr, i32) -> !llvm.ptr, f32
+
+// INBOUNDS-LABEL: func @load_32bit_index_nuw_mul
+// INBOUNDS: llvm.mul %{{.*}}, %{{.*}} overflow<nsw, nuw> : i32
+// INBOUNDS: llvm.add %{{.*}}, %{{.*}} overflow<nsw, nuw> : i32
+// INBOUNDS: llvm.getelementptr inbounds|nuw %{{.*}} : (!llvm.ptr, i32) -> !llvm.ptr, f32
+
+// -----
+
+// Same test for store.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @store_32bit_index(%memref : memref<200x100xf32>, %i : index, %j : index, %val : vector<8xf32>) {
+  vector.store %val, %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>
+  return
+}
+
+}
+
+// ALL-LABEL: func @store_32bit_index
+// ALL: %[[C100:.*]] = llvm.mlir.constant(100 : index) : i32
+// ALL: %[[MUL:.*]] = llvm.mul %{{.*}}, %[[C100]]
+// ALL: %[[ADD:.*]] = llvm.add %[[MUL]], %{{.*}}
+// DEFAULT: %[[GEP:.*]] = llvm.getelementptr %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
+// INBOUNDS: %[[GEP:.*]] = llvm.getelementptr inbounds|nuw %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
+// ALL: llvm.store %{{.*}}, %[[GEP]] {alignment = 4 : i64} : vector<8xf32>, !llvm.ptr

>From 0b60d5342adf276f64ae763ad1baf3d5a2ce3e64 Mon Sep 17 00:00:00 2001
From: Federico Bruzzone <federico.bruzzone.i at gmail.com>
Date: Sat, 25 Jul 2026 11:55:16 +0200
Subject: [PATCH 2/3] Address comments

Signed-off-by: Federico Bruzzone <federico.bruzzone.i at gmail.com>
---
 .../arith-to-llvm-32bit-index.mlir            | 74 -----------------
 .../Conversion/ArithToLLVM/arith-to-llvm.mlir | 83 +++++++++++++++++--
 .../ControlFlowToLLVM/branch-32bit-index.mlir | 65 ---------------
 .../Conversion/ControlFlowToLLVM/branch.mlir  | 64 ++++++++++++++
 ...vector-load-store-32bit-index-to-llvm.mlir | 76 -----------------
 .../vector-load-store-to-llvm.mlir            | 70 ++++++++++++++++
 6 files changed, 212 insertions(+), 220 deletions(-)
 delete mode 100644 mlir/test/Conversion/ArithToLLVM/arith-to-llvm-32bit-index.mlir
 delete mode 100644 mlir/test/Conversion/ControlFlowToLLVM/branch-32bit-index.mlir
 delete mode 100644 mlir/test/Conversion/VectorToLLVM/vector-load-store-32bit-index-to-llvm.mlir

diff --git a/mlir/test/Conversion/ArithToLLVM/arith-to-llvm-32bit-index.mlir b/mlir/test/Conversion/ArithToLLVM/arith-to-llvm-32bit-index.mlir
deleted file mode 100644
index 85b0324388b8a..0000000000000
--- a/mlir/test/Conversion/ArithToLLVM/arith-to-llvm-32bit-index.mlir
+++ /dev/null
@@ -1,74 +0,0 @@
-// RUN: mlir-opt %s --convert-arith-to-llvm -split-input-file | FileCheck %s
-
-// Verify that ArithToLLVMConversionPass respects the module's data layout
-// when deriving the index type.  When the module declares a 32-bit index via
-// dlti.dl_spec, index constants and index arithmetic ops must be emitted as
-// i32 instead of the default i64.
-
-// -----
-
-// 32-bit data layout: arith.constant with index type -> i32 constant.
-
-module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
-
-func.func @constant_index_32bit() -> index {
-  %c0 = arith.constant 0 : index
-  return %c0 : index
-}
-
-}
-
-// CHECK-LABEL: func @constant_index_32bit
-// CHECK: llvm.mlir.constant(0 : index) : i32
-
-// -----
-
-// 32-bit data layout: arith.cmpi on index type -> icmp on i32.
-
-module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
-
-func.func @cmpi_index_32bit(%a: index, %b: index) -> i1 {
-  %cmp = arith.cmpi slt, %a, %b : index
-  return %cmp : i1
-}
-
-}
-
-// CHECK-LABEL: func @cmpi_index_32bit
-// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
-// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
-// CHECK: llvm.icmp "slt" %{{.*}}, %{{.*}} : i32
-
-// -----
-
-// 32-bit data layout: arith.addi on index type -> add on i32.
-
-module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
-
-func.func @addi_index_32bit(%a: index, %b: index) -> index {
-  %add = arith.addi %a, %b : index
-  return %add : index
-}
-
-}
-
-// CHECK-LABEL: func @addi_index_32bit
-// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
-// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
-// CHECK: llvm.add %{{.*}}, %{{.*}} : i32
-
-// -----
-
-// Without dlti.dl_spec the default index width (i64) is preserved.
-
-module {
-
-func.func @constant_index_default() -> index {
-  %c0 = arith.constant 0 : index
-  return %c0 : index
-}
-
-}
-
-// CHECK-LABEL: func @constant_index_default
-// CHECK: llvm.mlir.constant(0 : index) : i64
diff --git a/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir b/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir
index 43f21561e6544..db4a2b6f0cee7 100644
--- a/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir
+++ b/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir
@@ -1,4 +1,4 @@
-// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-arith-to-llvm))" %s -split-input-file | FileCheck %s
+// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-arith-to-llvm))" %s -split-input-file | FileCheck %s --check-prefixes=CHECK,CHECK-DERIVE
 
 // Same below, but using the `ConvertToLLVMPatternInterface` entry point
 // and the generic `convert-to-llvm` pass.
@@ -969,11 +969,11 @@ func.func @unsupported_fp_type(%arg0: f4E2M1FN, %arg1: vector<4xf4E2M1FN>, %arg2
 
 // -----
 
-//   CHECK-LABEL: func @supported_fp_type
-//         CHECK:   llvm.fadd {{.*}} : f32
-//         CHECK:   llvm.fadd {{.*}} : vector<4xf32>
+// CHECK-LABEL: func @supported_fp_type
+//       CHECK:   llvm.fadd {{.*}} : f32
+//       CHECK:   llvm.fadd {{.*}} : vector<4xf32>
 // CHECK-COUNT-4:   llvm.fadd {{.*}} : vector<8xf32>
-//         CHECK:   llvm.fcmp {{.*}} : f32
+//       CHECK:   llvm.fcmp {{.*}} : f32
 func.func @supported_fp_type(%arg0: f32, %arg1: vector<4xf32>, %arg2: vector<4x8xf32>, %arg3: f32) {
   %0 = arith.addf %arg0, %arg0 : f32
   %1 = arith.addf %arg1, %arg1 : vector<4xf32>
@@ -982,3 +982,76 @@ func.func @supported_fp_type(%arg0: f32, %arg1: vector<4xf32>, %arg2: vector<4x8
   return
 }
 
+// -----
+
+// Verify that the pass respects the module's data layout when deriving the
+// index type.  When the module declares a 32-bit index via dlti.dl_spec,
+// index constants and index arithmetic ops must be emitted as i32 instead of
+// the default i64.
+
+// 32-bit data layout: arith.constant with index type -> i32 constant.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @constant_index_32bit() -> index {
+  %c0 = arith.constant 0 : index
+  return %c0 : index
+}
+
+}
+
+// CHECK-DERIVE-LABEL: func @constant_index_32bit
+// CHECK-DERIVE: llvm.mlir.constant(0 : index) : i32
+
+// -----
+
+// 32-bit data layout: arith.cmpi on index type -> icmp on i32.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @cmpi_index_32bit(%a: index, %b: index) -> i1 {
+  %cmp = arith.cmpi slt, %a, %b : index
+  return %cmp : i1
+}
+
+}
+
+// CHECK-DERIVE-LABEL: func @cmpi_index_32bit
+// CHECK-DERIVE: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK-DERIVE: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK-DERIVE: llvm.icmp "slt" %{{.*}}, %{{.*}} : i32
+
+// -----
+
+// 32-bit data layout: arith.addi on index type -> add on i32.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @addi_index_32bit(%a: index, %b: index) -> index {
+  %add = arith.addi %a, %b : index
+  return %add : index
+}
+
+}
+
+// CHECK-DERIVE-LABEL: func @addi_index_32bit
+// CHECK-DERIVE: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK-DERIVE: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK-DERIVE: llvm.add %{{.*}}, %{{.*}} : i32
+
+// -----
+
+// Without dlti.dl_spec the default index width (i64) is preserved.
+
+module {
+
+func.func @constant_index_default() -> index {
+  %c0 = arith.constant 0 : index
+  return %c0 : index
+}
+
+}
+
+// CHECK-DERIVE-LABEL: func @constant_index_default
+// CHECK-DERIVE: llvm.mlir.constant(0 : index) : i64
+
diff --git a/mlir/test/Conversion/ControlFlowToLLVM/branch-32bit-index.mlir b/mlir/test/Conversion/ControlFlowToLLVM/branch-32bit-index.mlir
deleted file mode 100644
index fcb32bc86a69d..0000000000000
--- a/mlir/test/Conversion/ControlFlowToLLVM/branch-32bit-index.mlir
+++ /dev/null
@@ -1,65 +0,0 @@
-// RUN: mlir-opt %s --convert-cf-to-llvm -split-input-file | FileCheck %s
-
-// Verify that ConvertControlFlowToLLVMPass respects the module's data layout
-// when deriving the index type for block arguments.  When the module declares
-// a 32-bit index via dlti.dl_spec, cf.br and cf.cond_br must pass index-typed
-// block arguments as i32 instead of the default i64.
-
-// -----
-
-// 32-bit data layout: cf.br with index block argument -> i32 branch arg.
-
-module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
-
-func.func @cf_br_index_32bit(%arg0: index) -> index {
-  cf.br ^bb1(%arg0 : index)
-^bb1(%a: index):
-  return %a : index
-}
-
-}
-
-// CHECK-LABEL: func @cf_br_index_32bit
-// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
-// CHECK: llvm.br ^{{.*}}(%{{.*}} : i32)
-// CHECK: ^{{.*}}(%{{.*}}: i32):
-
-// -----
-
-// 32-bit data layout: cf.cond_br with index block arguments -> i32 branch args.
-
-module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
-
-func.func @cf_cond_br_index_32bit(%cond: i1, %a: index, %b: index) -> index {
-  cf.cond_br %cond, ^bb1(%a : index), ^bb2(%b : index)
-^bb1(%x: index):
-  return %x : index
-^bb2(%y: index):
-  return %y : index
-}
-
-}
-
-// CHECK-LABEL: func @cf_cond_br_index_32bit
-// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
-// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
-// CHECK: llvm.cond_br %{{.*}}, ^{{.*}}(%{{.*}} : i32), ^{{.*}}(%{{.*}} : i32)
-
-// -----
-
-// Without dlti.dl_spec the default index width (i64) is preserved.
-
-module {
-
-func.func @cf_br_index_default(%arg0: index) -> index {
-  cf.br ^bb1(%arg0 : index)
-^bb1(%a: index):
-  return %a : index
-}
-
-}
-
-// CHECK-LABEL: func @cf_br_index_default
-// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i64
-// CHECK: llvm.br ^{{.*}}(%{{.*}} : i64)
-// CHECK: ^{{.*}}(%{{.*}}: i64):
diff --git a/mlir/test/Conversion/ControlFlowToLLVM/branch.mlir b/mlir/test/Conversion/ControlFlowToLLVM/branch.mlir
index 7c78211d59010..7d2aa0bc5d86e 100644
--- a/mlir/test/Conversion/ControlFlowToLLVM/branch.mlir
+++ b/mlir/test/Conversion/ControlFlowToLLVM/branch.mlir
@@ -81,3 +81,67 @@ func.func @cf_cond_br_with_weights(%cond: i1, %a: index, %b: index) -> index {
 ^bb2(%arg2: index):
   return %arg2 : index
 }
+
+// -----
+
+// Verify that the pass respects the module's data layout when deriving the
+// index type for block arguments.  When the module declares a 32-bit index
+// via dlti.dl_spec, cf.br and cf.cond_br must pass index-typed block
+// arguments as i32 instead of the default i64.
+
+// 32-bit data layout: cf.br with index block argument -> i32 branch arg.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @cf_br_index_32bit(%arg0: index) -> index {
+  cf.br ^bb1(%arg0 : index)
+^bb1(%a: index):
+  return %a : index
+}
+
+}
+
+// CHECK-LABEL: func @cf_br_index_32bit
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK: llvm.br ^{{.*}}(%{{.*}} : i32)
+// CHECK: ^{{.*}}(%{{.*}}: i32):
+
+// -----
+
+// 32-bit data layout: cf.cond_br with index block arguments -> i32 branch args.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @cf_cond_br_index_32bit(%cond: i1, %a: index, %b: index) -> index {
+  cf.cond_br %cond, ^bb1(%a : index), ^bb2(%b : index)
+^bb1(%x: index):
+  return %x : index
+^bb2(%y: index):
+  return %y : index
+}
+
+}
+
+// CHECK-LABEL: func @cf_cond_br_index_32bit
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i32
+// CHECK: llvm.cond_br %{{.*}}, ^{{.*}}(%{{.*}} : i32), ^{{.*}}(%{{.*}} : i32)
+
+// -----
+
+// Without dlti.dl_spec the default index width (i64) is preserved.
+
+module {
+
+func.func @cf_br_index_default(%arg0: index) -> index {
+  cf.br ^bb1(%arg0 : index)
+^bb1(%a: index):
+  return %a : index
+}
+
+}
+
+// CHECK-LABEL: func @cf_br_index_default
+// CHECK: builtin.unrealized_conversion_cast %{{.*}} : index to i64
+// CHECK: llvm.br ^{{.*}}(%{{.*}} : i64)
+// CHECK: ^{{.*}}(%{{.*}}: i64):
diff --git a/mlir/test/Conversion/VectorToLLVM/vector-load-store-32bit-index-to-llvm.mlir b/mlir/test/Conversion/VectorToLLVM/vector-load-store-32bit-index-to-llvm.mlir
deleted file mode 100644
index 29496be37322f..0000000000000
--- a/mlir/test/Conversion/VectorToLLVM/vector-load-store-32bit-index-to-llvm.mlir
+++ /dev/null
@@ -1,76 +0,0 @@
-// RUN: mlir-opt %s -convert-vector-to-llvm -split-input-file | FileCheck %s --check-prefixes=ALL,DEFAULT
-// RUN: mlir-opt %s -convert-vector-to-llvm='enable-gep-inbounds-nuw=1' -split-input-file | FileCheck %s --check-prefixes=ALL,INBOUNDS
-
-// Verify that ConvertVectorToLLVMPass respects the module's data layout when
-// deriving the index type. When the module declares a 32-bit index (via
-// dlti.dl_spec), GEP arithmetic should be emitted in i32 instead of the
-// default i64.  This also makes enable-gep-inbounds-nuw meaningful on 32-bit
-// targets: the flag emits nsw/nuw on the *narrow* i32 multiply, allowing SCEV
-// to form a clean 32-bit AddRec and enabling LSR to use direct pointer
-// induction instead of per-iteration sign/zero extension.
-
-// -----
-
-// 32-bit data layout: index -> i32 in GEP arithmetic.
-
-module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
-
-func.func @load_32bit_index(%memref : memref<200x100xf32>, %i : index, %j : index) -> vector<8xf32> {
-  %0 = vector.load %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>
-  return %0 : vector<8xf32>
-}
-
-}
-
-// ALL-LABEL: func @load_32bit_index
-// ALL: %[[C100:.*]] = llvm.mlir.constant(100 : index) : i32
-// ALL: %[[MUL:.*]] = llvm.mul %{{.*}}, %[[C100]]
-// ALL: %[[ADD:.*]] = llvm.add %[[MUL]], %{{.*}}
-// DEFAULT: %[[GEP:.*]] = llvm.getelementptr %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
-// INBOUNDS: %[[GEP:.*]] = llvm.getelementptr inbounds|nuw %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
-// ALL: llvm.load %[[GEP]] {alignment = 4 : i64} : !llvm.ptr -> vector<8xf32>
-
-// -----
-
-// With enable-gep-inbounds-nuw, the narrow i32 multiply and add carry
-// nsw/nuw flags, enabling SCEV to form a clean 32-bit AddRec.
-
-module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
-
-func.func @load_32bit_index_nuw_mul(%memref : memref<200x100xf32>, %i : index, %j : index) -> vector<8xf32> {
-  %0 = vector.load %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>
-  return %0 : vector<8xf32>
-}
-
-}
-
-// DEFAULT-LABEL: func @load_32bit_index_nuw_mul
-// DEFAULT: llvm.mul %{{.*}}, %{{.*}} : i32
-// DEFAULT: llvm.add %{{.*}}, %{{.*}} : i32
-// DEFAULT: llvm.getelementptr %{{.*}} : (!llvm.ptr, i32) -> !llvm.ptr, f32
-
-// INBOUNDS-LABEL: func @load_32bit_index_nuw_mul
-// INBOUNDS: llvm.mul %{{.*}}, %{{.*}} overflow<nsw, nuw> : i32
-// INBOUNDS: llvm.add %{{.*}}, %{{.*}} overflow<nsw, nuw> : i32
-// INBOUNDS: llvm.getelementptr inbounds|nuw %{{.*}} : (!llvm.ptr, i32) -> !llvm.ptr, f32
-
-// -----
-
-// Same test for store.
-
-module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
-
-func.func @store_32bit_index(%memref : memref<200x100xf32>, %i : index, %j : index, %val : vector<8xf32>) {
-  vector.store %val, %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>
-  return
-}
-
-}
-
-// ALL-LABEL: func @store_32bit_index
-// ALL: %[[C100:.*]] = llvm.mlir.constant(100 : index) : i32
-// ALL: %[[MUL:.*]] = llvm.mul %{{.*}}, %[[C100]]
-// ALL: %[[ADD:.*]] = llvm.add %[[MUL]], %{{.*}}
-// DEFAULT: %[[GEP:.*]] = llvm.getelementptr %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
-// INBOUNDS: %[[GEP:.*]] = llvm.getelementptr inbounds|nuw %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
-// ALL: llvm.store %{{.*}}, %[[GEP]] {alignment = 4 : i64} : vector<8xf32>, !llvm.ptr
diff --git a/mlir/test/Conversion/VectorToLLVM/vector-load-store-to-llvm.mlir b/mlir/test/Conversion/VectorToLLVM/vector-load-store-to-llvm.mlir
index cab462efee2b5..3cddf0acaa89d 100644
--- a/mlir/test/Conversion/VectorToLLVM/vector-load-store-to-llvm.mlir
+++ b/mlir/test/Conversion/VectorToLLVM/vector-load-store-to-llvm.mlir
@@ -236,3 +236,73 @@ func.func @store_with_alignment(%memref : memref<200x100xf32>, %i : index, %j :
 
 // ALL-LABEL: func @store_with_alignment
 // ALL: llvm.store %{{.*}} {alignment = 8 : i64} :  vector<4xf32>, !llvm.ptr
+
+// -----
+
+// Verify that the pass respects the module's data layout when deriving the
+// index type. When the module declares a 32-bit index (via dlti.dl_spec),
+// GEP arithmetic should be emitted in i32 instead of the default i64.
+
+// 32-bit data layout: index -> i32 in GEP arithmetic.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @load_32bit_index(%memref : memref<200x100xf32>, %i : index, %j : index) -> vector<8xf32> {
+  %0 = vector.load %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>
+  return %0 : vector<8xf32>
+}
+
+}
+
+// ALL-LABEL: func @load_32bit_index
+// ALL: %[[C100:.*]] = llvm.mlir.constant(100 : index) : i32
+// ALL: %[[MUL:.*]] = llvm.mul %{{.*}}, %[[C100]]
+// ALL: %[[ADD:.*]] = llvm.add %[[MUL]], %{{.*}}
+// DEFAULT: %[[GEP:.*]] = llvm.getelementptr %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
+// INBOUNDS: %[[GEP:.*]] = llvm.getelementptr inbounds|nuw %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
+// ALL: llvm.load %[[GEP]] {alignment = 4 : i64} : !llvm.ptr -> vector<8xf32>
+
+// -----
+
+// With enable-gep-inbounds-nuw, the narrow i32 multiply and add carry
+// nsw/nuw flags, enabling SCEV to form a clean 32-bit AddRec.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @load_32bit_index_nuw_mul(%memref : memref<200x100xf32>, %i : index, %j : index) -> vector<8xf32> {
+  %0 = vector.load %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>
+  return %0 : vector<8xf32>
+}
+
+}
+
+// DEFAULT-LABEL: func @load_32bit_index_nuw_mul
+// DEFAULT: llvm.mul %{{.*}}, %{{.*}} : i32
+// DEFAULT: llvm.add %{{.*}}, %{{.*}} : i32
+// DEFAULT: llvm.getelementptr %{{.*}} : (!llvm.ptr, i32) -> !llvm.ptr, f32
+
+// INBOUNDS-LABEL: func @load_32bit_index_nuw_mul
+// INBOUNDS: llvm.mul %{{.*}}, %{{.*}} overflow<nsw, nuw> : i32
+// INBOUNDS: llvm.add %{{.*}}, %{{.*}} overflow<nsw, nuw> : i32
+// INBOUNDS: llvm.getelementptr inbounds|nuw %{{.*}} : (!llvm.ptr, i32) -> !llvm.ptr, f32
+
+// -----
+
+// Same test for store.
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
+
+func.func @store_32bit_index(%memref : memref<200x100xf32>, %i : index, %j : index, %val : vector<8xf32>) {
+  vector.store %val, %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>
+  return
+}
+
+}
+
+// ALL-LABEL: func @store_32bit_index
+// ALL: %[[C100:.*]] = llvm.mlir.constant(100 : index) : i32
+// ALL: %[[MUL:.*]] = llvm.mul %{{.*}}, %[[C100]]
+// ALL: %[[ADD:.*]] = llvm.add %[[MUL]], %{{.*}}
+// DEFAULT: %[[GEP:.*]] = llvm.getelementptr %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
+// INBOUNDS: %[[GEP:.*]] = llvm.getelementptr inbounds|nuw %{{.*}}[%[[ADD]]] : (!llvm.ptr, i32) -> !llvm.ptr, f32
+// ALL: llvm.store %{{.*}}, %[[GEP]] {alignment = 4 : i64} : vector<8xf32>, !llvm.ptr

>From 055af22f0ffb49c80147bec87ecc1d165e7de232 Mon Sep 17 00:00:00 2001
From: Federico Bruzzone <federico.bruzzone.i at gmail.com>
Date: Wed, 5 Aug 2026 12:16:45 +0200
Subject: [PATCH 3/3] Address comments

Signed-off-by: Federico Bruzzone <federico.bruzzone.i at gmail.com>
---
 .../lib/Conversion/VectorToLLVM/ConvertVectorToLLVMPass.cpp | 6 +++---
 mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir         | 4 ++++
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVMPass.cpp b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVMPass.cpp
index d80769ec4dc0b..e0355222cff54 100644
--- a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVMPass.cpp
+++ b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVMPass.cpp
@@ -109,9 +109,9 @@ void ConvertVectorToLLVMPass::runOnOperation() {
   }
 
   // Convert to the LLVM IR dialect.
-  // Use the module's data layout so that the index bitwidth is derived from the
-  // target (e.g. i32 on 32-bit targets) rather than hard-wired to i64, which
-  // mirrors what FinalizeMemRefToLLVMConversionPass does.
+  // Use the data layout in scope (if any) so that the index bitwidth is taken
+  // from it rather than hard-wired to i64, mirroring what
+  // FinalizeMemRefToLLVMConversionPass does.
   const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
   LowerToLLVMOptions options(&getContext(),
                              dataLayoutAnalysis.getAtOrAbove(getOperation()));
diff --git a/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir b/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir
index db4a2b6f0cee7..a42b736ce2c24 100644
--- a/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir
+++ b/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir
@@ -988,6 +988,10 @@ func.func @supported_fp_type(%arg0: f32, %arg1: vector<4xf32>, %arg2: vector<4x8
 // index type.  When the module declares a 32-bit index via dlti.dl_spec,
 // index constants and index arithmetic ops must be emitted as i32 instead of
 // the default i64.
+//
+// These cases use the CHECK-DERIVE prefix: the `convert-to-llvm` RUN lines
+// above use the static pass implementation, which builds its type converter
+// without a data layout, so it always lowers `index` to i64.
 
 // 32-bit data layout: arith.constant with index type -> i32 constant.
 



More information about the Mlir-commits mailing list