[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