[flang-commits] [flang] [flang] Use the target index width during FIR-to-LLVM lowering (PR #226424)
Anutosh Bhat via flang-commits
flang-commits at lists.llvm.org
Fri Sep 25 05:14:58 PDT 2026
https://github.com/anutosh491 updated https://github.com/llvm/llvm-project/pull/226424
>From 7b8a3627a73a09c53c5e7a3b0a4aac2b23448f5f Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Fri, 25 Sep 2026 15:34:33 +0530
Subject: [PATCH] [flang] Use the target index width during FIR-to-LLVM
lowering
---
flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp | 14 ++++++++++----
flang/lib/Optimizer/CodeGen/TypeConverter.cpp | 10 +++++++---
flang/test/Fir/alloc-32.fir | 10 ++++------
flang/test/Fir/convert-to-llvm-target.fir | 19 +++++++++++++++++++
flang/test/Fir/convert-to-llvm.fir | 18 +++++++++++++++++-
5 files changed, 57 insertions(+), 14 deletions(-)
diff --git a/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp b/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp
index 995a2efba25a4d..6ad44901345338 100644
--- a/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp
+++ b/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp
@@ -66,10 +66,16 @@ mlir::Value ConvertFIRToLLVMPattern::integerCast(
mlir::Location loc, mlir::ConversionPatternRewriter &rewriter,
mlir::Type ty, mlir::Value val, bool fold) const {
auto valTy = val.getType();
- // If the value was not yet lowered, lower its type so that it can
- // be used in getPrimitiveTypeSizeInBits.
- if (!mlir::isa<mlir::IntegerType>(valTy))
- valTy = convertType(valTy);
+ // If the value was not yet lowered, convert it to the LLVM integer type.
+ if (!mlir::isa<mlir::IntegerType>(valTy)) {
+ mlir::Type llvmValTy = convertType(valTy);
+ if (llvmValTy && llvmValTy != valTy) {
+ val = getTypeConverter()->materializeTargetConversion(rewriter, loc,
+ llvmValTy, val);
+ assert(val && "failed to materialize integer target conversion");
+ valTy = llvmValTy;
+ }
+ }
auto toSize = mlir::LLVM::getPrimitiveTypeSizeInBits(ty);
auto fromSize = mlir::LLVM::getPrimitiveTypeSizeInBits(valTy);
if (fold) {
diff --git a/flang/lib/Optimizer/CodeGen/TypeConverter.cpp b/flang/lib/Optimizer/CodeGen/TypeConverter.cpp
index 31194f9c274f36..c901bf4b2f453d 100644
--- a/flang/lib/Optimizer/CodeGen/TypeConverter.cpp
+++ b/flang/lib/Optimizer/CodeGen/TypeConverter.cpp
@@ -37,7 +37,10 @@ static mlir::LowerToLLVMOptions MakeLowerOptions(mlir::ModuleOp module) {
auto options = mlir::LowerToLLVMOptions(module.getContext());
auto llvmDL = llvm::DataLayout(dataLayoutString);
- if (llvmDL.getPointerSizeInBits(0) == 32) {
+ bool use32BitIndices = dataLayoutString.empty()
+ ? fir::getTargetTriple(module).isArch32Bit()
+ : llvmDL.getPointerSizeInBits(0) == 32;
+ if (use32BitIndices) {
// FIXME: Should translateDataLayout in the MLIR layer be doing this?
options.overrideIndexBitwidth(32);
}
@@ -174,9 +177,10 @@ mlir::Type LLVMTypeConverter::offsetType() const {
return mlir::IntegerType::get(&getContext(), 32);
}
-// i64 can be used to index into aggregates like arrays
+// Index width follows the LLVM lowering options / data layout (i32 on
+// 32-bit targets, i64 otherwise).
mlir::Type LLVMTypeConverter::indexType() const {
- return mlir::IntegerType::get(&getContext(), 64);
+ return mlir::IntegerType::get(&getContext(), getIndexTypeBitwidth());
}
// fir.type<name(p : TY'...){f : TY...}> --> llvm<"%name = { ty... }">
diff --git a/flang/test/Fir/alloc-32.fir b/flang/test/Fir/alloc-32.fir
index a3cbf200c24fcd..0a5325e3b394b6 100644
--- a/flang/test/Fir/alloc-32.fir
+++ b/flang/test/Fir/alloc-32.fir
@@ -18,12 +18,10 @@ func.func @allocmem_scalar_nonchar() -> !fir.heap<i32> {
// CHECK-LABEL: define ptr @allocmem_scalar_dynchar(
// CHECK-SAME: i32 %[[len:.*]])
-// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
-// CHECK: %[[mul2:.*]] = mul i64 1, %[[mul1]]
-// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0
-// CHECK: %[[sz:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1
-// CHECK: %[[trunc:.*]] = trunc i64 %[[sz]] to i32
-// CHECK: call ptr @malloc(i32 %[[trunc]])
+// CHECK: %[[mul:.*]] = mul i32 1, %[[len]]
+// CHECK: %[[cmp:.*]] = icmp sgt i32 %[[mul]], 0
+// CHECK: %[[sz:.*]] = select i1 %[[cmp]], i32 %[[mul]], i32 1
+// CHECK: call ptr @malloc(i32 %[[sz]])
func.func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap<!fir.char<1,?>> {
%1 = fir.allocmem !fir.char<1,?>(%l : i32)
return %1 : !fir.heap<!fir.char<1,?>>
diff --git a/flang/test/Fir/convert-to-llvm-target.fir b/flang/test/Fir/convert-to-llvm-target.fir
index 6adc5cd4b737fc..c37c27e4489efa 100644
--- a/flang/test/Fir/convert-to-llvm-target.fir
+++ b/flang/test/Fir/convert-to-llvm-target.fir
@@ -147,3 +147,22 @@ func.func @boxchar_len_i32_i64(%arg0 : !fir.boxchar<4>) -> (i64) {
// INT32: %[[len:.*]] = llvm.extractvalue %[[box_char]][1] : !llvm.struct<(ptr, i32)>
// INT32: %{{.*}} = llvm.sext %0 : i32 to i64
// INT32-NEXT: llvm.return
+
+// -----
+
+// Test that dynamic allocation uses the target index width.
+
+func.func @dynamic_alloca(%extent : index) {
+ %0 = fir.alloca !fir.array<?xi32>, %extent
+ return
+}
+
+// INT64-LABEL: llvm.func @dynamic_alloca
+// INT64-SAME: %[[extent:.*]]: i64
+// INT64: %[[count:.*]] = llvm.mul %[[extent]], %{{.*}} : i64
+// INT64: llvm.alloca %[[count]] x i32 : (i64) -> !llvm.ptr
+
+// INT32-LABEL: llvm.func @dynamic_alloca
+// INT32-SAME: %[[extent:.*]]: i32
+// INT32: %[[count:.*]] = llvm.mul %[[extent]], %{{.*}} : i32
+// INT32: llvm.alloca %[[count]] x i32 : (i32) -> !llvm.ptr
diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir
index d00aae198bf138..5e34c574775d78 100644
--- a/flang/test/Fir/convert-to-llvm.fir
+++ b/flang/test/Fir/convert-to-llvm.fir
@@ -1,6 +1,8 @@
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
-// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
+// The generic checks assume a 64-bit index width. Keep representative i386
+// coverage under a target-specific prefix.
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=I386,CHECK-COMDAT
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-pc-win32" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-apple-darwin" %s | FileCheck %s --check-prefixes=CHECK,CHECK-NO-COMDAT,GENERIC
@@ -1093,6 +1095,10 @@ func.func @alloca_one() -> !fir.ref<i32> {
// AMDGPU: [[A:%.*]] = llvm.addrspacecast [[AA]] : !llvm.ptr<5> to !llvm.ptr
// CHECK: llvm.return [[A]] : !llvm.ptr
+// I386-LABEL: llvm.func @alloca_one() -> !llvm.ptr
+// I386: %[[ONE:.*]] = llvm.mlir.constant(1 : i32) : i32
+// I386: llvm.alloca %[[ONE]] x i32 : (i32) -> !llvm.ptr
+
// -----
@@ -2128,6 +2134,12 @@ func.func @ext_array_coor5(%arg0: !fir.ref<!fir.array<?xi32>>, %idx1 : index, %i
// CHECK: %[[VAL_16:.*]] = llvm.getelementptr nusw|nuw %[[VAL_0]][%[[VAL_13]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// CHECK: }
+// I386-LABEL: llvm.func @ext_array_coor5(
+// I386-SAME: %[[BASE:[^,]+]]: !llvm.ptr, %[[EXTENT:[^,]+]]: i32
+// I386: %[[ONE:.*]] = llvm.mlir.constant(1 : i32) : i32
+// I386: %[[STRIDE:.*]] = llvm.mul %[[ONE]], %[[EXTENT]] overflow<nsw, nuw> : i32
+// I386: llvm.getelementptr nusw|nuw %[[BASE]][%{{.*}}] : (!llvm.ptr, i32) -> !llvm.ptr, i32
+
// Conversion for 3-d array
func.func @ext_array_coor6(%arg0: !fir.ref<!fir.array<?x?x?xi32>>, %idx1 : index, %idx2 : index, %idx3 : index, %idx4 : index, %idx5 : index) {
@@ -2439,6 +2451,10 @@ func.func @coordinate_box_array_1d(%arg0: !fir.box<!fir.array<10 x f32>>, %arg1:
// CHECK-NEXT: %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ARRAY_OBJECT]][%[[SUBOJECT_OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
// CHECK-NEXT: llvm.return
+// I386-LABEL: llvm.func @coordinate_box_array_1d(
+// I386-SAME: %[[BOX:.*]]: !llvm.ptr, %[[COORDINATE:.*]]: i32)
+// I386: llvm.mul %[[COORDINATE]], %{{.*}} overflow<nsw> : i32
+
// `fir.array` inside a `fir.box` (1d) - dynamic size
func.func @coordinate_of_box_dynamic_array_1d(%arg0: !fir.box<!fir.array<? x f32>>, %arg1: index) {
%p = fir.coordinate_of %arg0, %arg1 : (!fir.box<!fir.array<? x f32>>, index) -> !fir.ref<f32>
More information about the flang-commits
mailing list