[flang-commits] [flang] [flang] Preserve capture metadata for host-associated globals (PR #233433)
via flang-commits
flang-commits at lists.llvm.org
Mon Oct 19 06:52:12 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Sergey Shcherbinin (SergeyShch01)
<details>
<summary>Changes</summary>
Host-associated globals accessed directly inside internal procedures are missing `internal_assoc`. For SAVE variables, FIR alias analysis can then treat a sibling internal call as `NoModRef`, allowing FIR LICM to hoist loads incorrectly.
Use the host procedure's existing global-capture set when lowering canonical host globals. Exact symbol identity keeps OpenMP private copies separate from their originals, and the existing alias-analysis handling of `internal_assoc` protects the captured storage.
For example:
```fortran
program p
integer, save :: x = 0
print *, f()
contains
integer function f()
integer :: i
f = 0
do i = 1, 3
call bump()
f = f + x
end do
end function
subroutine bump()
x = x + 1
end subroutine
end program
```
The expected result is **6**. Runtime checks on AArch64, comparing unpatched upstream `b0e32db0ae5a` with the same revision plus this fix, produced:
| Build | `-O0` | `-O1` | `-O2` | `-O3` |
| --- | ---: | ---: | ---: | ---: |
| Unpatched upstream | **6** | 0 | 0 | 0 |
| With this fix | **6** | **6** | **6** | **6** |
Disabling FIR LICM on unpatched upstream with `-O2 -mmlir -disable-fir-licm` also restores **6**. No `-fsave-main-program` flag is needed for this reproducer.
Regression coverage includes explicit and initialization-implied SAVE, `-fsave-main-program`, `-fno-automatic`, and private/firstprivate/reduction copies.
---
Patch is 29.87 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/233433.diff
12 Files Affected:
- (modified) flang/include/flang/Lower/HostAssociations.h (+5)
- (modified) flang/include/flang/Optimizer/Dialect/FIRAttr.td (+1-1)
- (modified) flang/lib/Lower/ConvertVariable.cpp (+13-1)
- (modified) flang/test/Lower/MIF/coarray_alloc_many_declare.f90 (+1-1)
- (added) flang/test/Lower/OpenMP/host-associated-globals-private.f90 (+39)
- (modified) flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 (+3-3)
- (modified) flang/test/Lower/OpenMP/threadprivate-host-association-3.f90 (+3-3)
- (modified) flang/test/Lower/OpenMP/threadprivate-host-association.f90 (+3-3)
- (modified) flang/test/Lower/equivalence-with-host-assoc.f90 (+10-10)
- (added) flang/test/Lower/host-associated-globals-licm.f90 (+96)
- (modified) flang/test/Lower/host-associated-globals.f90 (+5-5)
- (modified) flang/test/Lower/volatile4.f90 (+3-3)
``````````diff
diff --git a/flang/include/flang/Lower/HostAssociations.h b/flang/include/flang/Lower/HostAssociations.h
index 599dcb18d7e45..ee9136d80ea94 100644
--- a/flang/include/flang/Lower/HostAssociations.h
+++ b/flang/include/flang/Lower/HostAssociations.h
@@ -56,6 +56,11 @@ class HostAssociations {
return tupleSymbols.contains(&symbol) || globalSymbols.contains(&symbol);
}
+ /// Is the canonical symbol captured as a global instead of a tuple entry?
+ bool isAssociatedGlobal(const Fortran::semantics::Symbol &symbol) const {
+ return globalSymbols.contains(&symbol);
+ }
+
private:
/// Canonical vector of host associated local symbols.
llvm::SetVector<const Fortran::semantics::Symbol *> tupleSymbols;
diff --git a/flang/include/flang/Optimizer/Dialect/FIRAttr.td b/flang/include/flang/Optimizer/Dialect/FIRAttr.td
index 581c831c8985e..c8ee7f88291c5 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRAttr.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRAttr.td
@@ -82,7 +82,7 @@ def FIRvalue : I32BitEnumAttrCaseBit<"value", 11>;
def FIRvolatile : I32BitEnumAttrCaseBit<"fortran_volatile", 12, "volatile">;
// Used inside internal procedure to flag variables host associated from parent procedure.
def FIRHostAssoc : I32BitEnumAttrCaseBit<"host_assoc", 13>;
-// Used inside parent procedure to flag variables host associated in internal procedure.
+// Marks storage accessible to internal procedures through host association.
def FIRInternalAssoc : I32BitEnumAttrCaseBit<"internal_assoc", 14>;
// Used by alias analysis
def FIRcray_pointer : I32BitEnumAttrCaseBit<"cray_pointer", 15>;
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 59f46a31256fe..cc5bdfbcda0d9 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -2550,12 +2550,24 @@ fir::FortranVariableFlagsAttr Fortran::lower::translateSymbolAttributes(
return fir::FortranVariableFlagsAttr::get(mlirContext, flags);
}
+/// Whether storage may be accessed indirectly through internal procedure calls.
static bool
isCapturedInInternalProcedure(Fortran::lower::AbstractConverter &converter,
const Fortran::semantics::Symbol &sym) {
const Fortran::lower::pft::FunctionLikeUnit *funit =
converter.getCurrentFunctionUnit();
- if (!funit || funit->getHostAssoc().empty())
+ if (!funit)
+ return false;
+ if (const auto *host =
+ funit->parent.getIf<Fortran::lower::pft::FunctionLikeUnit>()) {
+ // Only canonical host globals share storage with sibling procedures.
+ // Private copies can resolve to the same ultimate symbol but have separate
+ // storage and are absent from the canonical global capture set.
+ if (&sym.owner() == &host->getScope() &&
+ host->getHostAssoc().isAssociatedGlobal(sym))
+ return true;
+ }
+ if (funit->getHostAssoc().empty())
return false;
if (funit->getHostAssoc().isAssociated(sym))
return true;
diff --git a/flang/test/Lower/MIF/coarray_alloc_many_declare.f90 b/flang/test/Lower/MIF/coarray_alloc_many_declare.f90
index b7d004321a7b5..c4ead3c66c694 100644
--- a/flang/test/Lower/MIF/coarray_alloc_many_declare.f90
+++ b/flang/test/Lower/MIF/coarray_alloc_many_declare.f90
@@ -29,7 +29,7 @@ end program p
!CHECK-LABEL: func.func private @_QFPinner() attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>}
!CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope
!CHECK-NEXT: %[[VAL_1:.*]] = fir.address_of(@_QFEa) : !fir.ref<!fir.box<!fir.heap<i32>, corank:1>>
-!CHECK-NEXT: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] uniq_name("_QFEa") fortran_attrs<allocatable> : (!fir.ref<!fir.box<!fir.heap<i32>, corank:1>>) -> (!fir.ref<!fir.box<!fir.heap<i32>, corank:1>>, !fir.ref<!fir.box<!fir.heap<i32>, corank:1>>)
+!CHECK-NEXT: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] uniq_name("_QFEa") fortran_attrs<allocatable, internal_assoc> : (!fir.ref<!fir.box<!fir.heap<i32>, corank:1>>) -> (!fir.ref<!fir.box<!fir.heap<i32>, corank:1>>, !fir.ref<!fir.box<!fir.heap<i32>, corank:1>>)
!CHECK-NEXT: %c1_i32 = arith.constant 1 : i32
!CHECK-NEXT: hlfir.assign %c1_i32 to %[[VAL_2:.*]]#0 realloc : i32, !fir.ref<!fir.box<!fir.heap<i32>, corank:1>>
diff --git a/flang/test/Lower/OpenMP/host-associated-globals-private.f90 b/flang/test/Lower/OpenMP/host-associated-globals-private.f90
new file mode 100644
index 0000000000000..0b6ff226a38d4
--- /dev/null
+++ b/flang/test/Lower/OpenMP/host-associated-globals-private.f90
@@ -0,0 +1,39 @@
+! REQUIRES: module-independent
+! RUN: %flang_fc1 -fopenmp -emit-hlfir %s -o - | FileCheck %s
+! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s
+
+! Canonical SAVE globals remain accessible through sibling calls. Each OpenMP
+! copy has separate storage and must not inherit internal_assoc from its source.
+! CHECK-LABEL: func.func private @_QFhPworker()
+! CHECK-DAG: hlfir.declare {{.*}}uniq_name("_QFhEx") fortran_attrs<internal_assoc>
+! CHECK-DAG: hlfir.declare {{.*}}uniq_name("_QFhEy") fortran_attrs<internal_assoc>
+! CHECK-DAG: hlfir.declare {{.*}}uniq_name("_QFhEz") fortran_attrs<internal_assoc>
+! CHECK: omp.parallel
+! CHECK-DAG: hlfir.declare %arg0 uniq_name("_QFhEx") :
+! CHECK-DAG: hlfir.declare %arg1 uniq_name("_QFhEy") :
+! CHECK-DAG: hlfir.declare %arg2 uniq_name("_QFhEz") :
+! CHECK-LABEL: func.func private @_QFhPbump()
+! CHECK-DAG: hlfir.declare {{.*}}uniq_name("_QFhEx") fortran_attrs<internal_assoc>
+! CHECK-DAG: hlfir.declare {{.*}}uniq_name("_QFhEy") fortran_attrs<internal_assoc>
+! CHECK-DAG: hlfir.declare {{.*}}uniq_name("_QFhEz") fortran_attrs<internal_assoc>
+subroutine h
+ integer, save :: x,y,z
+ x=7
+ y=8
+ z=9
+ call worker()
+contains
+ subroutine worker()
+!$omp parallel num_threads(1) firstprivate(x) private(y) reduction(+:z)
+ call bump()
+ y=x
+ z=z+y
+ print *,x,y,z
+!$omp end parallel
+ end subroutine
+ subroutine bump()
+ x=x+1
+ y=y+1
+ z=z+1
+ end subroutine
+end subroutine
diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90
index c632e12483af6..917c38b791266 100644
--- a/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90
+++ b/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90
@@ -14,13 +14,13 @@
!CHECK: }
!CHECK: func.func private @_QFPsub() attributes {fir.host_symbol = {{.*}}, llvm.linkage = #llvm.linkage<internal>} {
!CHECK: %[[A:.*]] = fir.alloca i32 <{bindc_name = "a", uniq_name = "_QFEa"}>
-!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] uniq_name("_QFEa") : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] uniq_name("_QFEa") fortran_attrs<internal_assoc> : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
-!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] uniq_name("_QFEa") : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] uniq_name("_QFEa") fortran_attrs<internal_assoc> : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: omp.parallel {
!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
-!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] uniq_name("_QFEa") : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] uniq_name("_QFEa") fortran_attrs<internal_assoc> : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref<i32>
!CHECK: omp.terminator
!CHECK: }
diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90
index 3219b61f436ee..0e411d80167f1 100644
--- a/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90
+++ b/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90
@@ -14,13 +14,13 @@
!CHECK: }
!CHECK: func.func private @_QFPsub() attributes {fir.host_symbol = {{.*}}, llvm.linkage = #llvm.linkage<internal>} {
!CHECK: %[[A:.*]] = fir.alloca i32 <{bindc_name = "a", uniq_name = "_QFEa"}>
-!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] uniq_name("_QFEa") : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] uniq_name("_QFEa") fortran_attrs<internal_assoc> : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
-!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] uniq_name("_QFEa") : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] uniq_name("_QFEa") fortran_attrs<internal_assoc> : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: omp.parallel {
!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
-!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] uniq_name("_QFEa") : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] uniq_name("_QFEa") fortran_attrs<internal_assoc> : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref<i32>
!CHECK: omp.terminator
!CHECK: }
diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association.f90
index f57ef2c422163..4e17486d096a4 100644
--- a/flang/test/Lower/OpenMP/threadprivate-host-association.f90
+++ b/flang/test/Lower/OpenMP/threadprivate-host-association.f90
@@ -13,12 +13,12 @@
!CHECK: }
!CHECK: func.func private @_QFPsub() attributes {fir.host_symbol = {{.*}}, llvm.linkage = #llvm.linkage<internal>} {
!CHECK: %[[A:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
-!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] uniq_name("_QFEa") : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] uniq_name("_QFEa") fortran_attrs<internal_assoc> : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_DECL]]#0 : !fir.ref<i32> -> !fir.ref<i32>
-!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] uniq_name("_QFEa") : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] uniq_name("_QFEa") fortran_attrs<internal_assoc> : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: omp.parallel {
!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_DECL]]#0 : !fir.ref<i32> -> !fir.ref<i32>
-!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] uniq_name("_QFEa") : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] uniq_name("_QFEa") fortran_attrs<internal_assoc> : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref<i32>
!CHECK: omp.terminator
!CHECK: }
diff --git a/flang/test/Lower/equivalence-with-host-assoc.f90 b/flang/test/Lower/equivalence-with-host-assoc.f90
index 41cc27589c211..192d31a9acc6c 100644
--- a/flang/test/Lower/equivalence-with-host-assoc.f90
+++ b/flang/test/Lower/equivalence-with-host-assoc.f90
@@ -15,11 +15,11 @@ end subroutine test1
! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<i32>
-! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] storage(%[[VAL_1]][0]) uniq_name("_QFtest1Ei1") : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
+! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] storage(%[[VAL_1]][0]) uniq_name("_QFtest1Ei1") fortran_attrs<internal_assoc> : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_6:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_6]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.ref<i8>) -> !fir.ptr<i32>
-! HLFIR: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] storage(%[[VAL_1]][0]) uniq_name("_QFtest1Ej1") : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
+! HLFIR: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] storage(%[[VAL_1]][0]) uniq_name("_QFtest1Ej1") fortran_attrs<internal_assoc> : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_10:.*]] = fir.load %[[VAL_9]]#0 : !fir.ptr<i32>
! HLFIR: hlfir.assign %[[VAL_10]] to %[[VAL_5]]#0 : i32, !fir.ptr<i32>
! HLFIR: return
@@ -45,11 +45,11 @@ end module test2
! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<f32>
-! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] storage(%[[VAL_1]][0]) uniq_name("_QMtest2FhostEf1") : (!fir.ptr<f32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<f32>, !fir.ptr<f32>)
+! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] storage(%[[VAL_1]][0]) uniq_name("_QMtest2FhostEf1") fortran_attrs<internal_assoc> : (!fir.ptr<f32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<f32>, !fir.ptr<f32>)
! HLFIR: %[[VAL_6:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_6]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.ref<i8>) -> !fir.ptr<f32>
-! HLFIR: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] storage(%[[VAL_1]][0]) uniq_name("_QMtest2FhostEf2") : (!fir.ptr<f32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<f32>, !fir.ptr<f32>)
+! HLFIR: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] storage(%[[VAL_1]][0]) uniq_name("_QMtest2FhostEf2") fortran_attrs<internal_assoc> : (!fir.ptr<f32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<f32>, !fir.ptr<f32>)
! HLFIR: %[[VAL_19:.*]] = fir.load %[[VAL_9]]#0 : !fir.ptr<f32>
! HLFIR: hlfir.assign %[[VAL_19]] to %[[VAL_5]]#0 : f32, !fir.ptr<f32>
! HLFIR: return
@@ -71,17 +71,17 @@ end subroutine test3
! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<i32>
-! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] storage(%[[VAL_1]][0]) uniq_name("_QFtest3Ei1") : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
+! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] storage(%[[VAL_1]][0]) uniq_name("_QFtest3Ei1") fortran_attrs<internal_assoc> : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_6:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<4xi8>>
! HLFIR: %[[VAL_7:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_8:.*]] = fir.coordinate_of %[[VAL_6]], %[[VAL_7]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.ref<i8>) -> !fir.ptr<i32>
-! HLFIR: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_9]] storage(%[[VAL_6]][0]) uniq_name("_QFtest3Ej1") : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
+! HLFIR: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_9]] storage(%[[VAL_6]][0]) uniq_name("_QFtest3Ej1") fortran_attrs<internal_assoc> : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_11:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<4xi8>>
! HLFIR: %[[VAL_12:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_13:.*]] = fir.coordinate_of %[[VAL_11]], %[[VAL_12]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<i8>) -> !fir.ptr<i32>
-! HLFIR: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] storage(%[[VAL_11]][0]) uniq_name("_QFtest3Ek1") : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
+! HLFIR: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] storage(%[[VAL_11]][0]) uniq_name("_QFtest3Ek1") fortran_attrs<internal_assoc> : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_16:.*]] = fir.load %[[VAL_10]]#0 : !fir.ptr<i32>
! HLFIR: %[[VAL_17:.*]] = fir.load %[[VAL_15]]#0 : !fir.ptr<i32>
! HLFIR: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i32
@@ -105,17 +105,17 @@ end subroutine test4
! HLFIR: %[[VAL_2:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i8>) -> !fir.ptr<i32>
-! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] storage(%[[VAL_1]][0]) uniq_name("_QFtest4Ei1") : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
+! HLFIR: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] storage(%[[VAL_1]][0]) uniq_name("_QFtest4Ei1") fortran_attrs<internal_assoc> : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_6:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<4xi8>>
! HLFIR: %[[VAL_7:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_8:.*]] = fir.coordinate_of %[[VAL_6]], %[[VAL_7]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.ref<i8>) -> !fir.ptr<i32>
-! HLFIR: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_9]] storage(%[[VAL_6]][0]) uniq_name("_QFtest4Ej1") : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
+! HLFIR: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_9]] storage(%[[VAL_6]][0]) uniq_name("_QFtest4Ej1") fortran_attrs<internal_assoc> : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_11:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<tuple<i32>>) -> !fir.ref<!fir.array<4xi8>>
! HLFIR: %[[VAL_12:.*]] = arith.constant 0 : index
! HLFIR: %[[VAL_13:.*]] = fir.coordinate_of %[[VAL_11]], %[[VAL_12]] : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
! HLFIR: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<i8>) -> !fir.ptr<i32>
-! HLFIR: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] storage(%[[VAL_11]][0]) uniq_name("_QFtest4Ek1") : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
+! HLFIR: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] storage(%[[VAL_11]][0]) uniq_name("_QFtest4Ek1") fortran_attrs<internal_assoc> : (!fir.ptr<i32>, !fir.ref<!fir.array<4xi8>>) -> (!fir.ptr<i32>, !fir.ptr<i32>)
! HLFIR: %[[VAL_16:.*]] = fir.load %[[VAL_10]]#0 : !fir.ptr<i32>
! HLFIR: %[[VAL_17:.*]] = fir.load %[[VAL_15]]#0 : !fir.ptr<i32>
! HLFIR: %[[VAL_18:.*]] = arith.addi %[[VAL_16]], %[[VAL_17]] : i32
diff --git a/flang/test/Lower/host-associated-globals-licm.f90 b/flang/test/Lower/host-associated-globals-licm.f90
new file mode 100644
index 0000000000000..f1b20b3f2b211
--- /dev/null
+++ b/flang/test/Lower/host-associated-globals-licm.f90
@@ -0,0 +1,96 @@
+! REQUIRES: module-independent
+! RUN: split-file %s %t
+! RUN: %flang_fc1 -fsave-main-program -emit-fir %t/main.f90 -o - | fir-opt --flang-...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/233433
More information about the flang-commits
mailing list