[flang-commits] [flang] [flang] Lower volatile class types (PR #138607)
via flang-commits
flang-commits at lists.llvm.org
Mon May 5 15:57:17 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Asher Mancinelli (ashermancinelli)
<details>
<summary>Changes</summary>
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
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>
``````````
</details>
https://github.com/llvm/llvm-project/pull/138607
More information about the flang-commits
mailing list