[flang-commits] [flang] [flang] Correct OutputAscii memory-effects attribute (PR #227485)

via flang-commits flang-commits at lists.llvm.org
Tue Sep 29 14:48:00 PDT 2026


https://github.com/nvptm created https://github.com/llvm/llvm-project/pull/227485

`OutputAscii` accesses mutable I/O state through pointers loaded from its opaque cookie. The generic memory-effects attribute incorrectly marked it as not accessing other memory, allowing stale I/O state to be reused across consecutive calls.
Add an `OutputAscii` specialization that marks other memory as readwrite, and update the attribute test.

Other I/O entry points accept the same opaque cookie and may require similar
memory effects, including `OutputInteger*`, `OutputReal*`, `OutputComplex*`,
`OutputLogical`, `OutputCharacter`, `EndIoStatement`, and the corresponding
input routines.

This patch is limited to `OutputAscii`, for which there is a reduced executable
reproducer and verified memory behavior. The remaining cookie-taking routines
should be reviewed separately because their precise memory effects may differ.

>From 0bdf248aaff756ec5a452e51d8d9f5dcf5f0d750 Mon Sep 17 00:00:00 2001
From: nvpm <pmathew at nvidia.com>
Date: Mon, 28 Sep 2026 11:54:58 -0700
Subject: [PATCH] [flang] Correct OutputAscii memory-effects attribute

---
 .../Transforms/SetRuntimeCallAttributes.cpp     | 17 +++++++++++++++++
 .../Transforms/set-runtime-call-attributes.fir  |  2 +-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Optimizer/Transforms/SetRuntimeCallAttributes.cpp b/flang/lib/Optimizer/Transforms/SetRuntimeCallAttributes.cpp
index 1891bb9c3bcce4..32861a053877a0 100644
--- a/flang/lib/Optimizer/Transforms/SetRuntimeCallAttributes.cpp
+++ b/flang/lib/Optimizer/Transforms/SetRuntimeCallAttributes.cpp
@@ -118,6 +118,23 @@ struct MemoryAttrDesc {
     return getGenericMemoryAttr(callOp);
   }
 };
+
+// OutputAscii accesses I/O state through pointers loaded from its opaque
+// cookie. That state is not based directly on a call argument, so it must be
+// represented as "other" memory rather than only argument memory.
+template <>
+struct MemoryAttrDesc<mkIOKey(OutputAscii)> {
+  static mlir::LLVM::MemoryEffectsAttr get(fir::CallOp callOp) {
+    return mlir::LLVM::MemoryEffectsAttr::get(
+        callOp->getContext(),
+        {/*other=*/mlir::LLVM::ModRefInfo::ModRef,
+         /*argMem=*/mlir::LLVM::ModRefInfo::ModRef,
+         /*inaccessibleMem=*/mlir::LLVM::ModRefInfo::ModRef,
+         /*errnoMem=*/mlir::LLVM::ModRefInfo::NoModRef,
+         /*targetMem0=*/mlir::LLVM::ModRefInfo::NoModRef,
+         /*targetMem1=*/mlir::LLVM::ModRefInfo::NoModRef});
+  }
+};
 } // end anonymous namespace
 
 // NosyncAttrDesc type provides get() method for computing
diff --git a/flang/test/Transforms/set-runtime-call-attributes.fir b/flang/test/Transforms/set-runtime-call-attributes.fir
index c3d6e4dd5797f9..fb3349f7c989a3 100644
--- a/flang/test/Transforms/set-runtime-call-attributes.fir
+++ b/flang/test/Transforms/set-runtime-call-attributes.fir
@@ -596,7 +596,7 @@ module {
 // CHECK-SAME:                                           %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>,
 // CHECK-SAME:                                           %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i8>,
 // CHECK-SAME:                                           %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: i64) -> i1 {
-// CHECK:           %[[VAL_3:.*]] = fir.call @_FortranAioOutputAscii(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = none, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1
+// CHECK:           %[[VAL_3:.*]] = fir.call @_FortranAioOutputAscii(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {fir.llvm_memory = #llvm.memory_effects<other = readwrite, argMem = readwrite, inaccessibleMem = readwrite, errnoMem = none, targetMem0 = none, targetMem1 = none>, llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1
 // CHECK:           return %[[VAL_3]] : i1
 // CHECK:         }
   func.func @test__FortranAioOutputAscii(%arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 {



More information about the flang-commits mailing list