[flang-commits] [flang] [flang][hlfir] ensure hlfir.declare result box attributes are consistent (PR #143137)
via flang-commits
flang-commits at lists.llvm.org
Fri Jun 6 06:19:41 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: None (jeanPerier)
<details>
<summary>Changes</summary>
Prevent hlfir.declare output to be fir.box/class values with the heap/pointer attribute to ensure the runtime descriptor attributes are in line with the Fortran attributes for the entities being declared (only fir.ref<box/class> can be ALLOCATABLE/POINTERS).
This fixes a bug that was caught by valgrind on https://github.com/fujitsu/compiler-test-suite/blob/0d02267bb98b6bfdf46d1f6bbd92e9781c24356c/Fortran/0419/0419_0045.f90 where an associated entity inside a SELECT TYPE was being unexpectedly reallocated inside assign runtime because the selector was allocatable and this attribute was not properly removed when creating the descriptor for the associated entity (that do not inherit the ALLOCATABLE/POINTER attribute according to Fortran 2023 section 11.1.3.3).
Note that I could have gone for a fir.rebox before the hlfir.declare, but I think it is safer is this is enforced by hlfir.declare verifier and hlfir codegen (that already generates a fir.rebox).
---
Patch is 73.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143137.diff
17 Files Affected:
- (modified) flang/include/flang/Optimizer/Dialect/FIRType.h (+3)
- (modified) flang/lib/Optimizer/Dialect/FIRType.cpp (+11-4)
- (modified) flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp (+38-17)
- (modified) flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp (+1-1)
- (modified) flang/test/HLFIR/as_expr-codegen-polymorphic.fir (+10-10)
- (modified) flang/test/HLFIR/associate-codegen.fir (+8-8)
- (modified) flang/test/HLFIR/bufferize-poly-expr.fir (+23-23)
- (added) flang/test/HLFIR/declare-alloc-target.fir (+21)
- (modified) flang/test/HLFIR/elemental-codegen.fir (+17-17)
- (modified) flang/test/HLFIR/reshape-lowering.fir (+8-8)
- (modified) flang/test/Lower/HLFIR/assumed-rank-entry.f90 (+1-1)
- (modified) flang/test/Lower/HLFIR/function-return-as-expr.f90 (+4-4)
- (modified) flang/test/Lower/HLFIR/poly_expr_for_nonpoly_dummy.f90 (+6-6)
- (modified) flang/test/Lower/HLFIR/polymorphic-expressions.f90 (+6-7)
- (modified) flang/test/Lower/HLFIR/select-type-selector.f90 (+2-2)
- (modified) flang/test/Lower/HLFIR/vector-subscript-as-value.f90 (+3-4)
- (modified) flang/test/Lower/volatile-allocatable.f90 (+5-5)
``````````diff
diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index ab6254da19e06..ecab12de55d61 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -59,6 +59,9 @@ class BaseBoxType : public mlir::Type {
/// Is this a box for a pointer?
bool isPointer() const;
+ /// Does this box for a pointer or allocatable?
+ bool isPointerOrAllocatable() const;
+
/// Is this a box describing volatile memory?
bool isVolatile() const;
diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index e65faf3a7396f..93f8c0d7d0e5a 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -1482,10 +1482,12 @@ fir::BaseBoxType fir::BaseBoxType::getBoxTypeWithNewAttr(
break;
}
return llvm::TypeSwitch<fir::BaseBoxType, fir::BaseBoxType>(*this)
- .Case<fir::BoxType>(
- [baseType](auto) { return fir::BoxType::get(baseType); })
- .Case<fir::ClassType>(
- [baseType](auto) { return fir::ClassType::get(baseType); });
+ .Case<fir::BoxType>([baseType](auto b) {
+ return fir::BoxType::get(baseType, b.isVolatile());
+ })
+ .Case<fir::ClassType>([baseType](auto b) {
+ return fir::ClassType::get(baseType, b.isVolatile());
+ });
}
bool fir::BaseBoxType::isAssumedRank() const {
@@ -1499,7 +1501,12 @@ bool fir::BaseBoxType::isPointer() const {
return llvm::isa<fir::PointerType>(getEleTy());
}
+bool fir::BaseBoxType::isPointerOrAllocatable() const {
+ return llvm::isa<fir::PointerType, fir::HeapType>(getEleTy());
+}
+
bool BaseBoxType::isVolatile() const { return fir::isa_volatile_type(*this); }
+
//===----------------------------------------------------------------------===//
// FIROpsDialect
//===----------------------------------------------------------------------===//
diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index baa2e2180eaf6..df6ce12215d26 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -180,16 +180,26 @@ void hlfir::AssignOp::getEffects(
// DeclareOp
//===----------------------------------------------------------------------===//
-/// Given a FIR memory type, and information about non default lower bounds, get
-/// the related HLFIR variable type.
-mlir::Type hlfir::DeclareOp::getHLFIRVariableType(mlir::Type inputType,
- bool hasExplicitLowerBounds) {
+static std::pair<mlir::Type, mlir::Type>
+getDeclareOutputTypes(mlir::Type inputType, bool hasExplicitLowerBounds) {
+ // Drop pointer/allocatable attribute of descriptor values. Only descriptor
+ // addresses are ALLOCATABLE/POINTER. The HLFIR box result of an hlfir.declare
+ // without those attributes should not have these attributes set.
+ if (auto baseBoxType = mlir::dyn_cast<fir::BaseBoxType>(inputType))
+ if (baseBoxType.isPointerOrAllocatable()) {
+ mlir::Type boxWithoutAttributes =
+ baseBoxType.getBoxTypeWithNewAttr(fir::BaseBoxType::Attribute::None);
+ return {boxWithoutAttributes, boxWithoutAttributes};
+ }
mlir::Type type = fir::unwrapRefType(inputType);
if (mlir::isa<fir::BaseBoxType>(type))
- return inputType;
+ return {inputType, inputType};
if (auto charType = mlir::dyn_cast<fir::CharacterType>(type))
- if (charType.hasDynamicLen())
- return fir::BoxCharType::get(charType.getContext(), charType.getFKind());
+ if (charType.hasDynamicLen()) {
+ mlir::Type hlfirType =
+ fir::BoxCharType::get(charType.getContext(), charType.getFKind());
+ return {hlfirType, inputType};
+ }
auto seqType = mlir::dyn_cast<fir::SequenceType>(type);
bool hasDynamicExtents =
@@ -197,9 +207,19 @@ mlir::Type hlfir::DeclareOp::getHLFIRVariableType(mlir::Type inputType,
mlir::Type eleType = seqType ? seqType.getEleTy() : type;
bool hasDynamicLengthParams = fir::characterWithDynamicLen(eleType) ||
fir::isRecordWithTypeParameters(eleType);
- if (hasExplicitLowerBounds || hasDynamicExtents || hasDynamicLengthParams)
- return fir::BoxType::get(type, fir::isa_volatile_type(inputType));
- return inputType;
+ if (hasExplicitLowerBounds || hasDynamicExtents || hasDynamicLengthParams) {
+ mlir::Type boxType =
+ fir::BoxType::get(type, fir::isa_volatile_type(inputType));
+ return {boxType, inputType};
+ }
+ return {inputType, inputType};
+}
+
+/// Given a FIR memory type, and information about non default lower bounds, get
+/// the related HLFIR variable type.
+mlir::Type hlfir::DeclareOp::getHLFIRVariableType(mlir::Type inputType,
+ bool hasExplicitLowerBounds) {
+ return getDeclareOutputTypes(inputType, hasExplicitLowerBounds).first;
}
static bool hasExplicitLowerBounds(mlir::Value shape) {
@@ -256,17 +276,18 @@ void hlfir::DeclareOp::build(mlir::OpBuilder &builder,
std::tie(inputType, memref) = updateDeclaredInputTypeWithVolatility(
inputType, memref, builder, flags);
}
- mlir::Type hlfirVariableType =
- getHLFIRVariableType(inputType, hasExplicitLbs);
- build(builder, result, {hlfirVariableType, inputType}, memref, shape,
+ auto [hlfirVariableType, firVarType] =
+ getDeclareOutputTypes(inputType, hasExplicitLbs);
+ build(builder, result, {hlfirVariableType, firVarType}, memref, shape,
typeparams, dummy_scope, nameAttr, fortran_attrs, data_attr);
}
llvm::LogicalResult hlfir::DeclareOp::verify() {
- if (getMemref().getType() != getResult(1).getType())
- return emitOpError("second result type must match input memref type");
- mlir::Type hlfirVariableType = getHLFIRVariableType(
+ auto [hlfirVariableType, firVarType] = getDeclareOutputTypes(
getMemref().getType(), hasExplicitLowerBounds(getShape()));
+ if (firVarType != getResult(1).getType())
+ return emitOpError("second result type must match input memref type, "
+ "unless it is a box with heap or pointer attribute");
if (hlfirVariableType != getResult(0).getType())
return emitOpError("first result type is inconsistent with variable "
"properties: expected ")
@@ -1608,7 +1629,7 @@ void hlfir::AssociateOp::build(
mlir::Type firVarType;
auto sourceExprType = mlir::dyn_cast<hlfir::ExprType>(source.getType());
if (sourceExprType && sourceExprType.isPolymorphic())
- firVarType = fir::ClassType::get(fir::HeapType::get(dataType));
+ firVarType = fir::ClassType::get(dataType);
else
firVarType = fir::ReferenceType::get(dataType);
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
index 8f206b5a1ade7..f7efaa736a279 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
@@ -356,7 +356,7 @@ class DeclareOpConversion : public mlir::OpRewritePattern<hlfir::DeclareOp> {
// is used for accessing the bounds etc. Using the HLFIR box,
// that holds the same base_addr at this point, makes
// the representation a little bit more clear.
- if (hlfirBase.getType() == firBase.getType())
+ if (hlfirBase.getType() == declareOp.getOriginalBase().getType())
firBase = hlfirBase;
} else {
// Need to conditionally rebox/embox the optional: the input fir.box
diff --git a/flang/test/HLFIR/as_expr-codegen-polymorphic.fir b/flang/test/HLFIR/as_expr-codegen-polymorphic.fir
index f22ef2fa5aede..31301697ad225 100644
--- a/flang/test/HLFIR/as_expr-codegen-polymorphic.fir
+++ b/flang/test/HLFIR/as_expr-codegen-polymorphic.fir
@@ -9,13 +9,13 @@ func.func @as_expr_class(%arg0 : !fir.class<!t>, %arg1: !fir.ref<!t>) {
return
}
// CHECK-LABEL: func.func @as_expr_class(
-// CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = ".tmp"} : (!fir.class<!fir.heap<!fir.type<t{i:i32}>>>) -> (!fir.class<!fir.heap<!fir.type<t{i:i32}>>>, !fir.class<!fir.heap<!fir.type<t{i:i32}>>>)
+// CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = ".tmp"} : (!fir.class<!fir.heap<!fir.type<t{i:i32}>>>) -> (!fir.class<!fir.type<t{i:i32}>>, !fir.class<!fir.type<t{i:i32}>>)
// CHECK: %[[VAL_5:.*]] = arith.constant true
// ... copy ...
-// CHECK: %[[VAL_12:.*]] = fir.undefined tuple<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>, i1>
-// CHECK: %[[VAL_13:.*]] = fir.insert_value %[[VAL_12]], %[[VAL_5]], [1 : index] : (tuple<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>, i1>, i1) -> tuple<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>, i1>
-// CHECK: %[[VAL_14:.*]] = fir.insert_value %[[VAL_13]], %[[VAL_6]]#0, [0 : index] : (tuple<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>, i1>, !fir.class<!fir.heap<!fir.type<t{i:i32}>>>) -> tuple<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>, i1>
-// CHECK: hlfir.assign %[[VAL_6]]#0 to %{{.*}} : !fir.class<!fir.heap<!fir.type<t{i:i32}>>>, !fir.ref<!fir.type<t{i:i32}>>
+// CHECK: %[[VAL_12:.*]] = fir.undefined tuple<!fir.class<!fir.type<t{i:i32}>>, i1>
+// CHECK: %[[VAL_13:.*]] = fir.insert_value %[[VAL_12]], %[[VAL_5]], [1 : index] : (tuple<!fir.class<!fir.type<t{i:i32}>>, i1>, i1) -> tuple<!fir.class<!fir.type<t{i:i32}>>, i1>
+// CHECK: %[[VAL_14:.*]] = fir.insert_value %[[VAL_13]], %[[VAL_6]]#0, [0 : index] : (tuple<!fir.class<!fir.type<t{i:i32}>>, i1>, !fir.class<!fir.type<t{i:i32}>>) -> tuple<!fir.class<!fir.type<t{i:i32}>>, i1>
+// CHECK: hlfir.assign %[[VAL_6]]#0 to %{{.*}} : !fir.class<!fir.type<t{i:i32}>>, !fir.ref<!fir.type<t{i:i32}>>
func.func @as_expr_class_2(%arg0 : !fir.class<!fir.array<?x!t>>) {
@@ -25,11 +25,11 @@ func.func @as_expr_class_2(%arg0 : !fir.class<!fir.array<?x!t>>) {
return
}
// CHECK-LABEL: func.func @as_expr_class_2(
-// CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = ".tmp"} : (!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>) -> (!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, !fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>)
+// CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = ".tmp"} : (!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>) -> (!fir.class<!fir.array<?x!fir.type<t{i:i32}>>>, !fir.class<!fir.array<?x!fir.type<t{i:i32}>>>)
// CHECK: %[[VAL_9:.*]] = arith.constant true
// ... copy ...
-// CHECK: %[[VAL_16:.*]] = fir.undefined tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, i1>
-// CHECK: %[[VAL_17:.*]] = fir.insert_value %[[VAL_16]], %[[VAL_9]], [1 : index] : (tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, i1>, i1) -> tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, i1>
-// CHECK: %[[VAL_18:.*]] = fir.insert_value %[[VAL_17]], %[[VAL_10]]#0, [0 : index] : (tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, i1>, !fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>) -> tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, i1>
+// CHECK: %[[VAL_16:.*]] = fir.undefined tuple<!fir.class<!fir.array<?x!fir.type<t{i:i32}>>>, i1>
+// CHECK: %[[VAL_17:.*]] = fir.insert_value %[[VAL_16]], %[[VAL_9]], [1 : index] : (tuple<!fir.class<!fir.array<?x!fir.type<t{i:i32}>>>, i1>, i1) -> tuple<!fir.class<!fir.array<?x!fir.type<t{i:i32}>>>, i1>
+// CHECK: %[[VAL_18:.*]] = fir.insert_value %[[VAL_17]], %[[VAL_10]]#0, [0 : index] : (tuple<!fir.class<!fir.array<?x!fir.type<t{i:i32}>>>, i1>, !fir.class<!fir.array<?x!fir.type<t{i:i32}>>>) -> tuple<!fir.class<!fir.array<?x!fir.type<t{i:i32}>>>, i1>
// CHECK: %[[VAL_19:.*]] = arith.constant 1 : index
-// CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_10]]#0 (%[[VAL_19]]) : (!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, index) -> !fir.class<!fir.type<t{i:i32}>>
+// CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_10]]#0 (%[[VAL_19]]) : (!fir.class<!fir.array<?x!fir.type<t{i:i32}>>>, index) -> !fir.class<!fir.type<t{i:i32}>>
diff --git a/flang/test/HLFIR/associate-codegen.fir b/flang/test/HLFIR/associate-codegen.fir
index fef7526011205..5d0d67854365e 100644
--- a/flang/test/HLFIR/associate-codegen.fir
+++ b/flang/test/HLFIR/associate-codegen.fir
@@ -174,22 +174,22 @@ func.func @test_result_convert(%x : !fir.heap<!fir.array<10xi32>>) {
func.func @test_0dim_box(%x : !fir.ref<!fir.box<!fir.heap<i32>>>) {
%0 = fir.load %x : !fir.ref<!fir.box<!fir.heap<i32>>>
- %1:2 = hlfir.declare %0 {uniq_name = ".tmp.intrinsic_result"} : (!fir.box<!fir.heap<i32>>) -> (!fir.box<!fir.heap<i32>>, !fir.box<!fir.heap<i32>>)
+ %1:2 = hlfir.declare %0 {uniq_name = ".tmp.intrinsic_result"} : (!fir.box<!fir.heap<i32>>) -> (!fir.box<i32>, !fir.box<i32>)
%true = arith.constant true
- %2 = hlfir.as_expr %1#0 move %true : (!fir.box<!fir.heap<i32>>, i1) -> !hlfir.expr<i32>
+ %2 = hlfir.as_expr %1#0 move %true : (!fir.box<i32>, i1) -> !hlfir.expr<i32>
%3:3 = hlfir.associate %2 {adapt.valuebyref} : (!hlfir.expr<i32>) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
return
}
// CHECK-LABEL: func.func @test_0dim_box(
// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>>) {
// CHECK: %[[VAL_1:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<i32>>>
-// CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.box<!fir.heap<i32>>) -> (!fir.box<!fir.heap<i32>>, !fir.box<!fir.heap<i32>>)
+// CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.box<!fir.heap<i32>>) -> (!fir.box<i32>, !fir.box<i32>)
// CHECK: %[[VAL_3:.*]] = arith.constant true
-// CHECK: %[[VAL_4:.*]] = fir.undefined tuple<!fir.box<!fir.heap<i32>>, i1>
-// CHECK: %[[VAL_5:.*]] = fir.insert_value %[[VAL_4]], %[[VAL_3]], [1 : index] : (tuple<!fir.box<!fir.heap<i32>>, i1>, i1) -> tuple<!fir.box<!fir.heap<i32>>, i1>
-// CHECK: %[[VAL_6:.*]] = fir.insert_value %[[VAL_5]], %[[VAL_2]]#0, [0 : index] : (tuple<!fir.box<!fir.heap<i32>>, i1>, !fir.box<!fir.heap<i32>>) -> tuple<!fir.box<!fir.heap<i32>>, i1>
-// CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_2]]#0 : (!fir.box<!fir.heap<i32>>) -> !fir.ref<i32>
-// CHECK: %[[VAL_8:.*]] = fir.box_addr %[[VAL_2]]#1 : (!fir.box<!fir.heap<i32>>) -> !fir.ref<i32>
+// CHECK: %[[VAL_4:.*]] = fir.undefined tuple<!fir.box<i32>, i1>
+// CHECK: %[[VAL_5:.*]] = fir.insert_value %[[VAL_4]], %[[VAL_3]], [1 : index] : (tuple<!fir.box<i32>, i1>, i1) -> tuple<!fir.box<i32>, i1>
+// CHECK: %[[VAL_6:.*]] = fir.insert_value %[[VAL_5]], %[[VAL_2]]#0, [0 : index] : (tuple<!fir.box<i32>, i1>, !fir.box<i32>) -> tuple<!fir.box<i32>, i1>
+// CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_2]]#0 : (!fir.box<i32>) -> !fir.ref<i32>
+// CHECK: %[[VAL_8:.*]] = fir.box_addr %[[VAL_2]]#1 : (!fir.box<i32>) -> !fir.ref<i32>
// CHECK: return
// CHECK: }
diff --git a/flang/test/HLFIR/bufferize-poly-expr.fir b/flang/test/HLFIR/bufferize-poly-expr.fir
index 1c63805e52425..54cdfa38f81a2 100644
--- a/flang/test/HLFIR/bufferize-poly-expr.fir
+++ b/flang/test/HLFIR/bufferize-poly-expr.fir
@@ -4,8 +4,8 @@ func.func @test_poly_expr_without_associate() {
%5 = fir.alloca !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>> {bindc_name = "r", uniq_name = "_QFtestEr"}
%8:2 = hlfir.declare %5 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtestEr"} : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>) -> (!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>, !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>)
%26 = fir.undefined !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>
- %27:2 = hlfir.declare %26 {uniq_name = ".tmp.intrinsic_result"} : (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>)
- %28 = hlfir.as_expr %27#0 : (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> !hlfir.expr<!fir.type<_QFtestTt{c:i32}>?>
+ %27:2 = hlfir.declare %26 {uniq_name = ".tmp.intrinsic_result"} : (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> (!fir.class<!fir.type<_QFtestTt{c:i32}>>, !fir.class<!fir.type<_QFtestTt{c:i32}>>)
+ %28 = hlfir.as_expr %27#0 : (!fir.class<!fir.type<_QFtestTt{c:i32}>>) -> !hlfir.expr<!fir.type<_QFtestTt{c:i32}>?>
hlfir.assign %28 to %8#0 realloc : !hlfir.expr<!fir.type<_QFtestTt{c:i32}>?>, !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>
hlfir.destroy %28 : !hlfir.expr<!fir.type<_QFtestTt{c:i32}>?>
return
@@ -15,9 +15,9 @@ func.func @test_poly_expr_without_associate() {
// CHECK: %[[VAL_1:.*]] = fir.alloca !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>> {bindc_name = "r", uniq_name = "_QFtestEr"}
// CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtestEr"} : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>) -> (!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>, !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>)
// CHECK: %[[VAL_3:.*]] = fir.undefined !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>
-// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>)
+// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> (!fir.class<!fir.type<_QFtestTt{c:i32}>>, !fir.class<!fir.type<_QFtestTt{c:i32}>>)
// CHECK: %[[VAL_5:.*]] = fir.zero_bits !fir.heap<!fir.type<_QFtestTt{c:i32}>>
-// CHECK: %[[VAL_6:.*]] = fir.embox %[[VAL_5]] source_box %[[VAL_4]]#0 : (!fir.heap<!fir.type<_QFtestTt{c:i32}>>, !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>
+// CHECK: %[[VAL_6:.*]] = fir.embox %[[VAL_5]] source_box %[[VAL_4]]#0 : (!fir.heap<!fir.type<_QFtestTt{c:i32}>>, !fir.class<!fir.type<_QFtestTt{c:i32}>>) -> !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>
// CHECK: fir.store %[[VAL_6]] to %[[VAL_0]] : !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>
// CHECK: %[[VAL_7:.*]] = fir.zero_bits !fir.ref<none>
// CHECK: %[[VAL_11:.*]] = arith.constant false
@@ -26,15 +26,15 @@ func.func @test_poly_expr_without_associate() {
// CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_7]] : (!fir.ref<none>) -> !fir.ref<i64>
// CHECK: %[[VAL_16:.*]] = fir.call @_FortranAAllocatableAllocate(%[[VAL_13]], %[[VAL_14]], %[[VAL_11]], %[[VAL_12:.*]], {{.*}}
// CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>
-// CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = ".tmp"} : (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>)
+// CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = ".tmp"} : (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> (!fir.class<!fir.type<_QFtestTt{c:i32}>>, !fir.class<!fir.type<_QFtestTt{c:i32}>>)
// CHECK: %[[VAL_19:.*]] = arith.constant true
-// CHECK: hlfir.assign %[[VAL_4]]#0 to %[[VAL_18]]#0 temporary_lhs : !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>
-// CHECK: %[[VAL_20:.*]] = fir.undefined tuple<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, i1>
-// CHECK: %[[VAL_21:.*]] = fir.insert_value %[[VAL_20]], %[[VAL_19]], [1 : index] : (tuple<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, i1>, i1) -> tuple<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, i1>
-// CHECK: %[[VAL_22:.*]] = fir.insert_value ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/143137
More information about the flang-commits
mailing list