[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 03:08:06 PDT 2026
https://github.com/anutosh491 created https://github.com/llvm/llvm-project/pull/226424
I'm interested in Flang cross-compilation to wasm32/wasm64 (as my [RFC](https://discourse.llvm.org/t/rfc-proposing-an-interactive-fortran-workflow-with-flang-using-jupyter-notebooks/89116) here says).
While working on it I noticed that FIR-to-LLVM lowering still hard-coded `i64` as its aggregate/index type, even when the target uses 32-bit indices.
This patch:
- uses the index width configured by `LowerToLLVMOptions`;
- materializes target conversions before emitting LLVM integer operations;
This is a general cross-compilation fix and does not contain any Wasm-specific logic. Tested with `fir-opt` for i386, x86-64 and other targets.
>From c9d7ebd024f4ba917f6cea5b3b0a08ec811fe7a7 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/convert-to-llvm-target.fir | 19 +++++++++++++++++++
3 files changed, 36 insertions(+), 7 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/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
More information about the flang-commits
mailing list