[flang-commits] [flang] [flang] Keep a LOGICAL input item unchanged on big-endian targets (PR #228588)

MMS IT GmbH via flang-commits flang-commits at lists.llvm.org
Sat Oct 3 01:38:00 PDT 2026


https://github.com/mms-it-ch updated https://github.com/llvm/llvm-project/pull/228588

>From 32759409617a749e4189489c359ccd80fc601d9c Mon Sep 17 00:00:00 2001
From: mms-it-ch <info at mms-it.ch>
Date: Fri, 2 Oct 2026 22:49:24 +0200
Subject: [PATCH 1/2] [flang] Keep a LOGICAL input item unchanged on big-endian
 targets

A scalar LOGICAL input item is passed to the runtime as a bool&, and after
the call its first byte is read back and stored into the whole LOGICAL.
If the runtime does not set the item (a null value in list-directed or
namelist input), the old value must be kept. On big-endian targets the
first byte of a LOGICAL(4) .TRUE. is zero, so the value became .FALSE.

Store the current value as a bool into the first byte before the call.

Assisted-by: Claude Code (Anthropic)
---
 flang/lib/Lower/IO.cpp                     | 23 ++++++++++++++++++++--
 flang/test/Lower/io-logical-null-input.f90 | 22 +++++++++++++++++++++
 2 files changed, 43 insertions(+), 2 deletions(-)
 create mode 100644 flang/test/Lower/io-logical-null-input.f90

diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp
index 5636f9e25b9909..fef22a305a4256 100644
--- a/flang/lib/Lower/IO.cpp
+++ b/flang/lib/Lower/IO.cpp
@@ -1132,6 +1132,22 @@ static void boolRefToLogical(mlir::Location loc, fir::FirOpBuilder &builder,
   fir::StoreOp::create(builder, loc, logicalValue, addr);
 }
 
+/// Store the current value of a LOGICAL as a `bool` into the first byte of its
+/// storage before passing it to the runtime as a `bool&`. If the runtime does
+/// not set it (e.g. a null value in list-directed or namelist input), the
+/// following boolRefToLogical then keeps the old value. Without this, the old
+/// value would be lost on big-endian targets, where the first byte of a
+/// LOGICAL(4) .TRUE. is zero.
+static void logicalToBoolRef(mlir::Location loc, fir::FirOpBuilder &builder,
+                             mlir::Value addr) {
+  auto logicalValue = fir::LoadOp::create(builder, loc, addr);
+  auto boolValue =
+      builder.createConvert(loc, builder.getI1Type(), logicalValue);
+  auto boolAddr = builder.createConvert(
+      loc, builder.getRefType(builder.getI1Type()), addr);
+  fir::StoreOp::create(builder, loc, boolValue, boolAddr);
+}
+
 static mlir::Value
 createIoRuntimeCallForItem(Fortran::lower::AbstractConverter &converter,
                            mlir::Location loc, mlir::func::FuncOp inputFunc,
@@ -1167,10 +1183,13 @@ createIoRuntimeCallForItem(Fortran::lower::AbstractConverter &converter,
               mlir::cast<mlir::IntegerType>(itemTy).getWidth() / 8)));
     }
   }
-  auto call = fir::CallOp::create(builder, loc, inputFunc, inputFuncArgs);
   auto itemAddr = fir::getBase(item);
   auto itemTy = fir::unwrapRefType(itemAddr.getType());
-  if (mlir::isa<fir::LogicalType>(itemTy))
+  bool isLogical = mlir::isa<fir::LogicalType>(itemTy);
+  if (isLogical)
+    logicalToBoolRef(loc, builder, itemAddr);
+  auto call = fir::CallOp::create(builder, loc, inputFunc, inputFuncArgs);
+  if (isLogical)
     boolRefToLogical(loc, builder, itemAddr);
   return call.getResult(0);
 }
diff --git a/flang/test/Lower/io-logical-null-input.f90 b/flang/test/Lower/io-logical-null-input.f90
new file mode 100644
index 00000000000000..47d3ed6556522d
--- /dev/null
+++ b/flang/test/Lower/io-logical-null-input.f90
@@ -0,0 +1,22 @@
+! A LOGICAL input item is passed to the runtime as a bool&. Its current value
+! is stored as a bool before the call, so that it is kept when the runtime does
+! not set it (null value in list-directed or namelist input). Otherwise the old
+! value would be lost on big-endian targets, where the first byte of a
+! LOGICAL(4) .TRUE. is zero.
+! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
+
+! CHECK-LABEL: func.func @_QPread_logical(
+subroutine read_logical(l)
+  logical :: l
+  read (*, *) l
+end subroutine
+! CHECK:  %[[L:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFread_logicalEl"}
+! CHECK:  %[[ARG:.*]] = fir.convert %[[L]]#0 : (!fir.ref<!fir.logical<4>>) -> !fir.ref<i1>
+! CHECK:  %[[OLD:.*]] = fir.load %[[L]]#0 : !fir.ref<!fir.logical<4>>
+! CHECK:  %[[B:.*]] = fir.convert %[[OLD]] : (!fir.logical<4>) -> i1
+! CHECK:  %[[BA:.*]] = fir.convert %[[L]]#0 : (!fir.ref<!fir.logical<4>>) -> !fir.ref<i1>
+! CHECK:  fir.store %[[B]] to %[[BA]] : !fir.ref<i1>
+! CHECK:  fir.call @_FortranAioInputLogical(%{{.*}}, %[[ARG]])
+! CHECK:  %[[NEW:.*]] = fir.load %{{.*}} : !fir.ref<i1>
+! CHECK:  %[[V:.*]] = fir.convert %[[NEW]] : (i1) -> !fir.logical<4>
+! CHECK:  fir.store %[[V]] to %[[L]]#0 : !fir.ref<!fir.logical<4>>

>From dbc4b790ce3f96a5a191989149987a9f14a50eed Mon Sep 17 00:00:00 2001
From: mms-it-ch <info at mms-it.ch>
Date: Sat, 3 Oct 2026 10:37:45 +0200
Subject: [PATCH 2/2] Format with clang-format; match both hlfir.declare
 syntaxes in the test

Assisted-by: Claude Code (Anthropic)
---
 flang/lib/Lower/IO.cpp                     | 4 ++--
 flang/test/Lower/io-logical-null-input.f90 | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp
index fef22a305a4256..c9a00e79ab92af 100644
--- a/flang/lib/Lower/IO.cpp
+++ b/flang/lib/Lower/IO.cpp
@@ -1143,8 +1143,8 @@ static void logicalToBoolRef(mlir::Location loc, fir::FirOpBuilder &builder,
   auto logicalValue = fir::LoadOp::create(builder, loc, addr);
   auto boolValue =
       builder.createConvert(loc, builder.getI1Type(), logicalValue);
-  auto boolAddr = builder.createConvert(
-      loc, builder.getRefType(builder.getI1Type()), addr);
+  auto boolAddr =
+      builder.createConvert(loc, builder.getRefType(builder.getI1Type()), addr);
   fir::StoreOp::create(builder, loc, boolValue, boolAddr);
 }
 
diff --git a/flang/test/Lower/io-logical-null-input.f90 b/flang/test/Lower/io-logical-null-input.f90
index 47d3ed6556522d..d49a569e862028 100644
--- a/flang/test/Lower/io-logical-null-input.f90
+++ b/flang/test/Lower/io-logical-null-input.f90
@@ -10,7 +10,7 @@ subroutine read_logical(l)
   logical :: l
   read (*, *) l
 end subroutine
-! CHECK:  %[[L:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFread_logicalEl"}
+! CHECK:  %[[L:.*]]:2 = hlfir.declare {{.*}}"_QFread_logicalEl"
 ! CHECK:  %[[ARG:.*]] = fir.convert %[[L]]#0 : (!fir.ref<!fir.logical<4>>) -> !fir.ref<i1>
 ! CHECK:  %[[OLD:.*]] = fir.load %[[L]]#0 : !fir.ref<!fir.logical<4>>
 ! CHECK:  %[[B:.*]] = fir.convert %[[OLD]] : (!fir.logical<4>) -> i1



More information about the flang-commits mailing list