Skip to content

[flang] Lower volatile class types #138607

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 6, 2025

Conversation

ashermancinelli
Copy link
Contributor

So far, only boxes and references have had their volatile attribute set during lowering. This patch enables the volatility of classes to be properly represented in the ir, same as box and ref.

For simple cases, not much needs to change in the codegen or conversion patterns because the prior work on volatile refs/boxes propagates volatility already. I am running further testing with the strict verification enabled to find remaining cases of incorrect/missing volatile propagation.

So far, only boxes and references have had their volatile attribute
set during lowering. This patch enables the volatility of classes
to be properly represented in the ir, same as box/ref.
@ashermancinelli ashermancinelli self-assigned this May 5, 2025
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir labels May 5, 2025
@llvmbot
Copy link
Member

llvmbot commented May 5, 2025

@llvm/pr-subscribers-flang-fir-hlfir

Author: Asher Mancinelli (ashermancinelli)

Changes

So far, only boxes and references have had their volatile attribute set during lowering. This patch enables the volatility of classes to be properly represented in the ir, same as box and ref.

For simple cases, not much needs to change in the codegen or conversion patterns because the prior work on volatile refs/boxes propagates volatility already. I am running further testing with the strict verification enabled to find remaining cases of incorrect/missing volatile propagation.


Full diff: https://github.com/llvm/llvm-project/pull/138607.diff

2 Files Affected:

  • (modified) flang/lib/Lower/ConvertExprToHLFIR.cpp (+13-11)
  • (added) flang/test/Lower/volatile-derived-type-pointer.f90 (+43)
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 5981116a6d3f7..dd7f6db6f8dd4 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -205,17 +205,8 @@ class HlfirDesignatorBuilder {
       partInfo.resultShape =
           hlfir::genShape(getLoc(), getBuilder(), *partInfo.base);
 
-    // Dynamic type of polymorphic base must be kept if the designator is
-    // polymorphic.
-    if (isPolymorphic(designatorNode))
-      return fir::ClassType::get(resultValueType);
-    // Character scalar with dynamic length needs a fir.boxchar to hold the
-    // designator length.
-    auto charType = mlir::dyn_cast<fir::CharacterType>(resultValueType);
-    if (charType && charType.hasDynamicLen())
-      return fir::BoxCharType::get(charType.getContext(), charType.getFKind());
-
-    // When volatile is enabled, enable volatility on the designatory type.
+    // Enable volatility on the designatory type if it has the VOLATILE attribute
+    // or if the base is volatile.
     bool isVolatile = false;
 
     // Check if this should be a volatile reference
@@ -236,6 +227,17 @@ class HlfirDesignatorBuilder {
         isVolatile = true;
     }
 
+    // Dynamic type of polymorphic base must be kept if the designator is
+    // polymorphic.
+    if (isPolymorphic(designatorNode))
+      return fir::ClassType::get(resultValueType, isVolatile);
+
+    // Character scalar with dynamic length needs a fir.boxchar to hold the
+    // designator length.
+    auto charType = mlir::dyn_cast<fir::CharacterType>(resultValueType);
+    if (charType && charType.hasDynamicLen())
+      return fir::BoxCharType::get(charType.getContext(), charType.getFKind());
+
     // Check if the base type is volatile
     if (partInfo.base.has_value()) {
       mlir::Type baseType = partInfo.base.value().getType();
diff --git a/flang/test/Lower/volatile-derived-type-pointer.f90 b/flang/test/Lower/volatile-derived-type-pointer.f90
new file mode 100644
index 0000000000000..64c4e64784510
--- /dev/null
+++ b/flang/test/Lower/volatile-derived-type-pointer.f90
@@ -0,0 +1,43 @@
+! RUN: bbc %s -o - --strict-fir-volatile-verifier | FileCheck %s
+
+! Ensure that assignments between volatile classes/derived type pointer/targets
+! lower to the correct hlfir declare/designate operations.
+
+module m
+  type :: dt
+    character :: c0="!"
+    integer   :: i=0
+    character :: c1="!"
+  end type
+  end module
+  program dataptrvolatile
+  use m
+  implicit none
+  type(dt),  volatile , target  :: arr(100, 100), arr1(10000), t(100,100)
+  class(dt), volatile , pointer :: ptr(:, :)
+  integer             :: i, j
+  do i =1, 100
+  do j =i, 100
+    arr(i:, j:) = dt(i=-i)
+    ptr(i:, j:) => arr(i:, j:)
+    t(i:, j:) = ptr(i:, j:)
+  end do
+  end do
+end
+
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}}(%{{.+}}) {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEarr"} : (!fir.ref<!fir.array<100x100x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>, !fir.shape<2>) -> (!fir.ref<!fir.array<100x100x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>, !fir.ref<!fir.array<100x100x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>)
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}}(%{{.+}}) {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEarr1"} : (!fir.ref<!fir.array<10000x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10000x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>, !fir.ref<!fir.array<10000x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>)
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} {uniq_name = "_QFEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEptr"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x?x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>>, volatile>, volatile>) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x?x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>>, volatile>, volatile>, !fir.ref<!fir.class<!fir.ptr<!fir.array<?x?x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>>, volatile>, volatile>)
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}}(%{{.+}}) {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEt"} : (!fir.ref<!fir.array<100x100x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>, !fir.shape<2>) -> (!fir.ref<!fir.array<100x100x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>, !fir.ref<!fir.array<100x100x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>)
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>) -> (!fir.ref<!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, !fir.ref<!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>)
+! CHECK:           %{{.+}} = hlfir.designate %{{.+}}#0{"c0"}   typeparams %{{.+}} : (!fir.ref<!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, index) -> !fir.ref<!fir.char<1>>
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX21"} : (!fir.ref<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
+! CHECK:           %{{.+}} = hlfir.designate %{{.+}}#0{"i"}   : (!fir.ref<!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>) -> !fir.ref<i32>
+! CHECK:           %{{.+}} = hlfir.designate %{{.+}}#0{"c1"}   typeparams %{{.+}} : (!fir.ref<!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, index) -> !fir.ref<!fir.char<1>>
+! CHECK:           %{{.+}}:2 = hlfir.declare %{{.+}} typeparams %{{.+}} {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX21"} : (!fir.ref<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
+! CHECK:           %{{.+}} = hlfir.designate %{{.+}}#0 (%{{.+}}:%{{.+}}:%{{.+}}, %{{.+}}:%{{.+}}:%{{.+}})  shape %{{.+}} : (!fir.ref<!fir.array<100x100x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.box<!fir.array<?x?x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>
+! CHECK:           %{{.+}} = hlfir.designate %{{.+}}#0 (%{{.+}}:%{{.+}}:%{{.+}}, %{{.+}}:%{{.+}}:%{{.+}})  shape %{{.+}} : (!fir.ref<!fir.array<100x100x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.box<!fir.array<?x?x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>
+! CHECK:           %{{.+}} = hlfir.designate %{{.+}} (%{{.+}}:%{{.+}}:%{{.+}}, %{{.+}}:%{{.+}}:%{{.+}})  shape %{{.+}} : (!fir.class<!fir.ptr<!fir.array<?x?x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>>, volatile>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.class<!fir.array<?x?x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>
+! CHECK:           %{{.+}} = hlfir.designate %{{.+}}#0 (%{{.+}}:%{{.+}}:%{{.+}}, %{{.+}}:%{{.+}}:%{{.+}})  shape %{{.+}} : (!fir.ref<!fir.array<100x100x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.box<!fir.array<?x?x!fir.type<_QMmTdt{c0:!fir.char<1>,i:i32,c1:!fir.char<1>}>>, volatile>

Copy link

github-actions bot commented May 5, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@ashermancinelli ashermancinelli requested a review from tblah May 5, 2025 23:06
Copy link
Contributor

@vzakhari vzakhari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ashermancinelli ashermancinelli merged commit 368fbc2 into llvm:main May 6, 2025
11 checks passed
@DanielCChen
Copy link
Contributor

This patch fixed the remaining regressions we had. Thanks.

GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
So far, only boxes and references have had their volatile attribute set
during lowering. This patch enables the volatility of classes to be
properly represented in the ir, same as box and ref.

For simple cases, not much needs to change in the codegen or conversion
patterns because the prior work on volatile refs/boxes propagates
volatility already. I am running further testing with the strict
verification enabled to find remaining cases of incorrect/missing
volatile propagation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:fir-hlfir flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants