[flang-commits] [flang] [flang] Use alias analysis in lowering record assignments (PR #180628)
via flang-commits
flang-commits at lists.llvm.org
Mon Feb 9 13:46:06 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Matt (MattPD)
<details>
<summary>Changes</summary>
Without alias analysis Flang assumes no aliasing in lowering record assignments which can result in miscompilation of programs using `SEQUENCE` types and `EQUIVALENCE`.
Use alias analysis to guard the fast path in `genRecordAssignment`; otherwise fall back to element-wise expansion.
Update FIR FileCheck expectations
Add `FIRAnalysis` to "flang/unittests/Optimizer/CMakeLists.txt" to fix the Windows x64 build failure (linker error).
Add `SEQUENCE` handling and update tests accordingly.
Fixes #<!-- -->175246 (and includes the fix to "flang/lib/Optimizer/Builder/CMakeLists.txt" in PR #<!-- -->176483).
---
Patch is 129.73 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/180628.diff
11 Files Affected:
- (modified) flang/include/flang/Optimizer/Dialect/FIRTypes.td (+4)
- (modified) flang/lib/Lower/ConvertType.cpp (+6)
- (modified) flang/lib/Optimizer/Builder/CMakeLists.txt (+1)
- (modified) flang/lib/Optimizer/Builder/FIRBuilder.cpp (+9-1)
- (modified) flang/lib/Optimizer/Dialect/FIRType.cpp (+18-1)
- (modified) flang/test/Lower/HLFIR/cray-pointers.f90 (+9-9)
- (modified) flang/test/Lower/HLFIR/proc-pointer-comp-pass.f90 (+21-21)
- (modified) flang/test/Lower/default-initialization.f90 (+27-27)
- (added) flang/test/Lower/derived-type-sequence-alias-assign.f90 (+56)
- (modified) flang/test/Lower/polymorphic.f90 (+202-202)
- (modified) flang/unittests/Optimizer/CMakeLists.txt (+1)
``````````diff
diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
index f2bb6f34313ed..7c7fe706d29d4 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
@@ -357,6 +357,10 @@ def fir_RecordType : FIR_Type<"Record", "type"> {
bool isPacked() const;
void pack(bool);
+ // The presence of SEQUENCE attribute.
+ bool isSequence() const;
+ void setSequence(bool);
+
detail::RecordTypeStorage const *uniqueKey() const;
}];
}
diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp
index 0fde61465fb85..0d343968374f0 100644
--- a/flang/lib/Lower/ConvertType.cpp
+++ b/flang/lib/Lower/ConvertType.cpp
@@ -387,6 +387,12 @@ struct TypeBuilderImpl {
return ty;
auto rec = fir::RecordType::get(context, converter.mangleName(tySpec));
+ // Mark SEQUENCE derived types.
+ if (const auto *details =
+ typeSymbol.detailsIf<Fortran::semantics::DerivedTypeDetails>())
+ if (details->sequence())
+ rec.setSequence(true);
+
// Maintain the stack of types for recursive references and to speed-up
// the derived type constructions that can be expensive for derived type
// with dozens of components/parents (modern Fortran).
diff --git a/flang/lib/Optimizer/Builder/CMakeLists.txt b/flang/lib/Optimizer/Builder/CMakeLists.txt
index 37c9c2d703c76..d966c52b29c33 100644
--- a/flang/lib/Optimizer/Builder/CMakeLists.txt
+++ b/flang/lib/Optimizer/Builder/CMakeLists.txt
@@ -47,6 +47,7 @@ add_flang_library(FIRBuilder
LINK_LIBS
CUFAttrs
CUFDialect
+ FIRAnalysis
FIRDialect
FIRDialectSupport
FIRSupport
diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index fcceb3a5b32c7..6a9c84ffbd909 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Analysis/AliasAnalysis.h"
#include "flang/Optimizer/Builder/BoxValue.h"
#include "flang/Optimizer/Builder/Character.h"
#include "flang/Optimizer/Builder/Complex.h"
@@ -1566,8 +1567,15 @@ void fir::factory::genRecordAssignment(fir::FirOpBuilder &builder,
mlir::isa<fir::BaseBoxType>(fir::getBase(rhs).getType());
auto recTy = mlir::dyn_cast<fir::RecordType>(baseTy);
assert(recTy && "must be a record type");
+
+ // Use alias analysis to guard the fast path.
+ fir::AliasAnalysis aa;
+ // Aliased SEQUENCE types must take the conservative (slow) path.
+ bool disjoint = isTemporaryLHS || !recTy.isSequence() ||
+ (aa.alias(fir::getBase(lhs), fir::getBase(rhs)) ==
+ mlir::AliasResult::NoAlias);
if ((needFinalization && mayHaveFinalizer(recTy, builder)) ||
- hasBoxOperands || !recordTypeCanBeMemCopied(recTy)) {
+ hasBoxOperands || !recordTypeCanBeMemCopied(recTy) || !disjoint) {
auto to = fir::getBase(builder.createBox(loc, lhs));
auto from = fir::getBase(builder.createBox(loc, rhs));
// The runtime entry point may modify the LHS descriptor if it is
diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index d84846843db81..ccdc8e45feede 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -183,18 +183,21 @@ struct RecordTypeStorage : public mlir::TypeStorage {
bool isPacked() const { return packed; }
void pack(bool p) { packed = p; }
+ bool isSequence() const { return sequence; }
+ void setSequence(bool s) { sequence = s; }
protected:
std::string name;
bool finalized;
bool packed;
+ bool sequence;
std::vector<RecordType::TypePair> lens;
std::vector<RecordType::TypePair> types;
private:
RecordTypeStorage() = delete;
explicit RecordTypeStorage(llvm::StringRef name)
- : name{name}, finalized{false}, packed{false} {}
+ : name{name}, finalized{false}, packed{false}, sequence{false} {}
};
} // namespace detail
@@ -1013,6 +1016,14 @@ mlir::Type fir::RecordType::parse(mlir::AsmParser &parser) {
if (parser.parseLess() || parser.parseKeyword(&name))
return {};
RecordType result = RecordType::get(parser.getContext(), name);
+ // Optional SEQUENCE attribute: ", sequence"
+ if (!parser.parseOptionalComma()) {
+ if (parser.parseKeyword("sequence")) {
+ parser.emitError(parser.getNameLoc(), "expected 'sequence' keyword");
+ return {};
+ }
+ result.setSequence(true);
+ }
RecordType::TypeVector lenParamList;
if (!parser.parseOptionalLParen()) {
@@ -1068,6 +1079,8 @@ mlir::Type fir::RecordType::parse(mlir::AsmParser &parser) {
void fir::RecordType::print(mlir::AsmPrinter &printer) const {
printer << "<" << getName();
+ if (isSequence())
+ printer << ",sequence";
if (!recordTypeVisited.count(uniqueKey())) {
recordTypeVisited.insert(uniqueKey());
if (getLenParamList().size()) {
@@ -1122,6 +1135,10 @@ void fir::RecordType::pack(bool p) { getImpl()->pack(p); }
bool fir::RecordType::isPacked() const { return getImpl()->isPacked(); }
+bool fir::RecordType::isSequence() const { return getImpl()->isSequence(); }
+
+void fir::RecordType::setSequence(bool s) { getImpl()->setSequence(s); }
+
detail::RecordTypeStorage const *fir::RecordType::uniqueKey() const {
return getImpl();
}
diff --git a/flang/test/Lower/HLFIR/cray-pointers.f90 b/flang/test/Lower/HLFIR/cray-pointers.f90
index 9c67b960951df..30f326765ba5b 100644
--- a/flang/test/Lower/HLFIR/cray-pointers.f90
+++ b/flang/test/Lower/HLFIR/cray-pointers.f90
@@ -120,25 +120,25 @@ subroutine test5()
res = v(7)%i
end subroutine test5
! CHECK-LABEL: func.func @_QPtest5() {
-! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>
+! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>
! CHECK: %[[VAL_1:.*]] = fir.alloca i64 {bindc_name = "cp", uniq_name = "_QFtest5Ecp"}
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<cray_pointer>, uniq_name = "_QFtest5Ecp"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>)
! CHECK: %[[VAL_5:.*]] = arith.constant 3 : index
! CHECK: %[[VAL_6:.*]] = arith.constant 9 : index
! CHECK: %[[VAL_8:.*]] = fir.shape_shift %[[VAL_5]], %[[VAL_6]] : (index, index) -> !fir.shapeshift<1>
-! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer, cray_pointee>, uniq_name = "_QFtest5Ev"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>)
-! CHECK: %[[VAL_14:.*]] = fir.zero_bits !fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>
-! CHECK: %[[VAL_15:.*]] = fir.embox %[[VAL_14]](%[[VAL_8]]) : (!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>, !fir.shapeshift<1>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>
-! CHECK: fir.store %[[VAL_15]] to %[[VAL_13]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>
+! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer, cray_pointee>, uniq_name = "_QFtest5Ev"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>)
+! CHECK: %[[VAL_14:.*]] = fir.zero_bits !fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>
+! CHECK: %[[VAL_15:.*]] = fir.embox %[[VAL_14]](%[[VAL_8]]) : (!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>, !fir.shapeshift<1>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>
+! CHECK: fir.store %[[VAL_15]] to %[[VAL_13]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>
! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_2]]#0 : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i64>>
! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref<!fir.ptr<i64>>
-! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_13]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_13]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>) -> !fir.ref<!fir.box<none>>
! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_17]] : (!fir.ptr<i64>) -> !fir.llvm_ptr<i8>
! CHECK: fir.call @_FortranAPointerAssociateScalar(%[[VAL_18]], %[[VAL_19]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.llvm_ptr<i8>) -> ()
-! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_13]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>>
+! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_13]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>>
! CHECK: %[[VAL_22:.*]] = arith.constant 7 : index
-! CHECK: %[[VAL_23:.*]] = hlfir.designate %[[VAL_21]] (%[[VAL_22]]) : (!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{r:f32,i:i32}>>>>, index) -> !fir.ref<!fir.type<_QFtest5Tt{r:f32,i:i32}>>
-! CHECK: %[[VAL_24:.*]] = hlfir.designate %[[VAL_23]]{"i"} : (!fir.ref<!fir.type<_QFtest5Tt{r:f32,i:i32}>>) -> !fir.ref<i32>
+! CHECK: %[[VAL_23:.*]] = hlfir.designate %[[VAL_21]] (%[[VAL_22]]) : (!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>>>, index) -> !fir.ref<!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>
+! CHECK: %[[VAL_24:.*]] = hlfir.designate %[[VAL_23]]{"i"} : (!fir.ref<!fir.type<_QFtest5Tt{{(,sequence)?}}{r:f32,i:i32}>>) -> !fir.ref<i32>
! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_24]] : !fir.ref<i32>
subroutine test6(n)
diff --git a/flang/test/Lower/HLFIR/proc-pointer-comp-pass.f90 b/flang/test/Lower/HLFIR/proc-pointer-comp-pass.f90
index 6a25fd1fe6a11..76b13c720cd10 100644
--- a/flang/test/Lower/HLFIR/proc-pointer-comp-pass.f90
+++ b/flang/test/Lower/HLFIR/proc-pointer-comp-pass.f90
@@ -46,10 +46,10 @@ subroutine test1(x)
end subroutine
! CHECK-LABEL: func.func @_QPtest1(
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] {{.*}}Ex
-! CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> ()>>
-! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]] : !fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> ()>>
-! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> ()>) -> ((!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> ())
-! CHECK: fir.call %[[VAL_4]](%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> ()
+! CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}>>) -> ()>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}>>) -> ()>}>>) -> ()>>
+! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]] : !fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}>>) -> ()>}>>) -> ()>>
+! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}>>) -> ()>}>>) -> ()>) -> ((!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}>>) -> ()>}>>) -> ())
+! CHECK: fir.call %[[VAL_4]](%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}>>) -> ()>}>>) -> ()
subroutine test2(x)
use m, only : t2
@@ -58,13 +58,13 @@ subroutine test2(x)
end subroutine
! CHECK-LABEL: func.func @_QPtest2(
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] {{.*}}Ex
-! CHECK: %[[VAL_2:.*]] = fir.embox %[[VAL_1]]#0 : (!fir.ref<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>) -> !fir.box<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>
-! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.box<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>) -> !fir.class<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>
-! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.class<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>) -> !fir.ref<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>
-! CHECK: %[[VAL_5:.*]] = hlfir.designate %[[VAL_4]]{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>) -> !fir.ref<!fir.boxproc<(!fir.class<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>) -> ()>>
-! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]] : !fir.ref<!fir.boxproc<(!fir.class<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>) -> ()>>
-! CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_6]] : (!fir.boxproc<(!fir.class<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>) -> ()>) -> ((!fir.class<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>) -> ())
-! CHECK: fir.call %[[VAL_7]](%[[VAL_3]]) fastmath<contract> : (!fir.class<!fir.type<_QMmTt2{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt2>>) -> ()>}>>) -> ()
+! CHECK: %[[VAL_2:.*]] = fir.embox %[[VAL_1]]#0 : (!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>) -> !fir.box<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>
+! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.box<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>) -> !fir.class<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>
+! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>) -> !fir.ref<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>
+! CHECK: %[[VAL_5:.*]] = hlfir.designate %[[VAL_4]]{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>) -> !fir.ref<!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>) -> ()>>
+! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]] : !fir.ref<!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>) -> ()>>
+! CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_6]] : (!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>) -> ()>) -> ((!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>) -> ())
+! CHECK: fir.call %[[VAL_7]](%[[VAL_3]]) fastmath<contract> : (!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.class<!fir.type<_QMmTt{{(,sequence)?}}2>>) -> ()>}>>) -> ()
subroutine test3(x)
use m, only : t, takes_hello
@@ -73,8 +73,8 @@ subroutine test3(x)
end subroutine
! CHECK-LABEL: func.func @_QPtest3(
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] {{.*}}Ex
-! CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> ()>>
-! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> ()>>) -> !fir.ref<!fir.boxproc<() -> ()>>
+! CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}>>) -> ()>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}>>) -> ()>}>>) -> ()>>
+! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}>>) -> ()>}>>) -> ()>>) -> !fir.ref<!fir.boxproc<() -> ()>>
! CHECK: fir.call @_QPtakes_hello(%[[VAL_3]]) fastmath<contract> : (!fir.ref<!fir.boxproc<() -> ()>>) -> ()
subroutine test4(x, y)
@@ -85,10 +85,10 @@ subroutine test4(x, y)
! CHECK-LABEL: func.func @_QPtest4(
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] {{.*}}Ex
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1:[a-z0-9]*]] {{.*}}Ey
-! CHECK: %[[VAL_4:.*]] = hlfir.designate %[[VAL_2]]#0{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> ()>>
-! CHECK: %[[VAL_5:.*]] = hlfir.designate %[[VAL_3]]#0{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> ()>>
-! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]] : !fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> ()>>
-! CHECK: fir.store %[[VAL_6]] to %[[VAL_4]] : !fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt>>) -> ()>}>>) -> ()>>
+! CHECK: %[[VAL_4:.*]] = hlfir.designate %[[VAL_2]]#0{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}>>) -> ()>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,sequence)?}}{i:i32,p:!fir.boxproc<(!fir.ref<!fir.type<_QMmTt{{(,seq...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/180628
More information about the flang-commits
mailing list