[flang-commits] [flang] [flang] emit declare for function result before call (PR #177615)
via flang-commits
flang-commits at lists.llvm.org
Mon Jan 26 08:08:57 PST 2026
https://github.com/jeanPerier updated https://github.com/llvm/llvm-project/pull/177615
>From 600bfea32f440f0e58c8ab6190a22673e04c5ee9 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Fri, 23 Jan 2026 06:43:21 -0800
Subject: [PATCH 1/3] [flang] emit declare for function result before call
---
flang/include/flang/Lower/ConvertCall.h | 3 +-
flang/lib/Lower/ConvertCall.cpp | 56 ++++++++++++-------
flang/lib/Lower/ConvertExpr.cpp | 13 ++---
flang/test/Lower/HLFIR/calls-f77.f90 | 2 +-
.../test/Lower/HLFIR/elemental-array-ops.f90 | 2 +-
flang/test/Lower/HLFIR/where.f90 | 4 +-
.../test/Lower/Intrinsics/storage_size-2.f90 | 4 +-
.../omp-declare-reduction-derivedtype.f90 | 2 +-
.../array-elemental-calls-char-dynamic.f90 | 10 ++--
.../test/Lower/array-elemental-calls-char.f90 | 2 +-
10 files changed, 57 insertions(+), 41 deletions(-)
diff --git a/flang/include/flang/Lower/ConvertCall.h b/flang/include/flang/Lower/ConvertCall.h
index f1cd4f938320b..6de0b3cbd11f5 100644
--- a/flang/include/flang/Lower/ConvertCall.h
+++ b/flang/include/flang/Lower/ConvertCall.h
@@ -21,6 +21,7 @@
#include "flang/Lower/CallInterface.h"
#include "flang/Optimizer/Builder/HLFIRTools.h"
#include <optional>
+#include <tuple>
namespace Fortran::lower {
@@ -37,7 +38,7 @@ using LoweredResult =
/// It is only used for HLFIR.
/// The returned boolean indicates if finalization has been emitted in
/// \p stmtCtx for the result.
-std::pair<LoweredResult, bool> genCallOpAndResult(
+std::tuple<LoweredResult, bool, mlir::Operation *> genCallOpAndResult(
mlir::Location loc, Fortran::lower::AbstractConverter &converter,
Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
Fortran::lower::CallerInterface &caller, mlir::FunctionType callSiteType,
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index 7bdd84903c1d3..8a0160e9a2fa3 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -342,7 +342,7 @@ getTypeWithIgnoreTkrC(mlir::FunctionType funcType,
return std::nullopt;
}
-std::pair<Fortran::lower::LoweredResult, bool>
+std::tuple<Fortran::lower::LoweredResult, bool, mlir::Operation *>
Fortran::lower::genCallOpAndResult(
mlir::Location loc, Fortran::lower::AbstractConverter &converter,
Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
@@ -351,6 +351,7 @@ Fortran::lower::genCallOpAndResult(
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
using PassBy = Fortran::lower::CallerInterface::PassEntityBy;
bool mustPopSymMap = false;
+ mlir::Operation *callOp = nullptr;
llvm::SmallVector<mlir::Value> resultLengths;
if (isElemental)
@@ -713,10 +714,10 @@ Fortran::lower::genCallOpAndResult(
}
}
- cuf::KernelLaunchOp::create(builder, loc, funcType.getResults(),
- funcSymbolAttr, grid_x, grid_y, grid_z, block_x,
- block_y, block_z, bytes, stream, operands,
- /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr);
+ callOp = cuf::KernelLaunchOp::create(
+ builder, loc, funcType.getResults(), funcSymbolAttr, grid_x, grid_y,
+ grid_z, block_x, block_y, block_z, bytes, stream, operands,
+ /*arg_attrs=*/nullptr, /*res_attrs=*/nullptr);
callNumResults = 0;
} else if (caller.requireDispatchCall()) {
// Procedure call requiring a dynamic dispatch. Call is created with
@@ -748,6 +749,7 @@ Fortran::lower::genCallOpAndResult(
passActual, operands, builder.getI32IntegerAttr(*passArg),
/*arg_attrs=*/nullptr,
/*res_attrs=*/nullptr, procAttrs);
+ callOp = dispatch;
} else {
// NOPASS
const Fortran::evaluate::Component *component =
@@ -764,6 +766,7 @@ Fortran::lower::genCallOpAndResult(
builder, loc, funcType.getResults(), builder.getStringAttr(procName),
passObject, operands, nullptr, /*arg_attrs=*/nullptr,
/*res_attrs=*/nullptr, procAttrs);
+ callOp = dispatch;
}
callNumResults = dispatch.getNumResults();
if (callNumResults != 0)
@@ -785,6 +788,7 @@ Fortran::lower::genCallOpAndResult(
builder, loc, funcType.getResults(), funcSymbolAttr, operands,
/*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, procAttrs, inlineAttr,
/*accessGroups=*/mlir::ArrayAttr{});
+ callOp = call;
callNumResults = call.getNumResults();
if (callNumResults != 0)
@@ -821,7 +825,7 @@ Fortran::lower::genCallOpAndResult(
/*finalize=*/mustFinalizeResult);
});
return {LoweredResult{hlfir::EntityWithAttributes{expr}},
- mustFinalizeResult};
+ mustFinalizeResult, callOp};
}
if (allocatedResult) {
@@ -880,13 +884,13 @@ Fortran::lower::genCallOpAndResult(
}
}
}
- return {LoweredResult{*allocatedResult}, resultIsFinalized};
+ return {LoweredResult{*allocatedResult}, resultIsFinalized, callOp};
}
// subroutine call
if (!resultType)
return {LoweredResult{fir::ExtendedValue{mlir::Value{}}},
- /*resultIsFinalized=*/false};
+ /*resultIsFinalized=*/false, callOp};
// For now, Fortran return values are implemented with a single MLIR
// function return value.
@@ -902,11 +906,11 @@ Fortran::lower::genCallOpAndResult(
loc, builder.getCharacterLengthType(), charTy.getLen());
return {
LoweredResult{fir::ExtendedValue{fir::CharBoxValue{callResult, len}}},
- /*resultIsFinalized=*/false};
+ /*resultIsFinalized=*/false, callOp};
}
return {LoweredResult{fir::ExtendedValue{callResult}},
- /*resultIsFinalized=*/false};
+ /*resultIsFinalized=*/false, callOp};
}
static hlfir::EntityWithAttributes genStmtFunctionRef(
@@ -1050,8 +1054,8 @@ using ExvAndCleanup =
// Helper to transform a fir::ExtendedValue to an hlfir::EntityWithAttributes.
static hlfir::EntityWithAttributes
extendedValueToHlfirEntity(mlir::Location loc, fir::FirOpBuilder &builder,
- const fir::ExtendedValue &exv,
- llvm::StringRef name) {
+ const fir::ExtendedValue &exv, llvm::StringRef name,
+ mlir::Operation *insertBefore = nullptr) {
mlir::Value firBase = fir::getBase(exv);
mlir::Type firBaseTy = firBase.getType();
if (fir::isa_trivial(firBaseTy))
@@ -1073,6 +1077,17 @@ extendedValueToHlfirEntity(mlir::Location loc, fir::FirOpBuilder &builder,
builder, loc, storage, /*mustFree=*/builder.createBool(loc, false));
return hlfir::EntityWithAttributes{asExpr.getResult()};
}
+ // TODO: better scoping model in FIR.
+ // The declare for result storage allocated on the callee side must be
+ // currently be emitted before the call so that MLIR level inlining does not
+ // break aliasing by introducing a fir.dummy_scope between the alloca and
+ // fir.declare that leads the alias analysis to think that the result
+ // allocation is a local inside the callee scope that cannot alias with the
+ // usage of that temporary inside the callee because they are made through a
+ // declare with the TARGET attribute.
+ mlir::OpBuilder::InsertionGuard guard(builder);
+ if (insertBefore)
+ builder.setInsertionPoint(insertBefore);
return hlfir::genDeclare(loc, builder, exv, name,
fir::FortranVariableFlagsAttr{});
}
@@ -1909,10 +1924,11 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
// Prepare lowered arguments according to the interface
// and map the lowered values to the dummy
// arguments.
- auto [loweredResult, resultIsFinalized] = Fortran::lower::genCallOpAndResult(
- loc, callContext.converter, callContext.symMap, callContext.stmtCtx,
- caller, callSiteType, callContext.resultType,
- callContext.isElementalProcWithArrayArgs());
+ auto [loweredResult, resultIsFinalized, callOp] =
+ Fortran::lower::genCallOpAndResult(
+ loc, callContext.converter, callContext.symMap, callContext.stmtCtx,
+ caller, callSiteType, callContext.resultType,
+ callContext.isElementalProcWithArrayArgs());
// Clean-up associations and copy-in.
// The association clean-ups are postponed to the end of the statement
@@ -1948,8 +1964,8 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
return extendedValueToHlfirEntity(loc, builder, result, tempResultName);
if (!resultIsFinalized) {
- hlfir::Entity resultEntity =
- extendedValueToHlfirEntity(loc, builder, result, tempResultName);
+ hlfir::Entity resultEntity = extendedValueToHlfirEntity(
+ loc, builder, result, tempResultName, /*insertBefore=*/callOp);
resultEntity = loadTrivialScalar(loc, builder, resultEntity);
if (resultEntity.isVariable()) {
// If the result has no finalization, it can be moved into an expression.
@@ -1981,7 +1997,9 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
/*mayBePolymorphic=*/true,
/*preserveLowerBounds=*/false)
: result;
- return extendedValueToHlfirEntity(loc, builder, loadedResult, tempResultName);
+ return extendedValueToHlfirEntity(
+ loc, builder, loadedResult, tempResultName,
+ /*insertBefore=*/!allocatable ? callOp : nullptr);
}
/// Create an optional dummy argument value from an entity that may be
diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index b2910a0fc58e0..a7e0239d335fd 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -2907,10 +2907,8 @@ class ScalarExprLowering {
}
}
- auto loweredResult =
- Fortran::lower::genCallOpAndResult(loc, converter, symMap, stmtCtx,
- caller, callSiteType, resultType)
- .first;
+ auto loweredResult = std::get<0>(Fortran::lower::genCallOpAndResult(
+ loc, converter, symMap, stmtCtx, caller, callSiteType, resultType));
auto &result = std::get<ExtValue>(loweredResult);
// Sync pointers and allocatables that may have been modified during the
@@ -4946,10 +4944,9 @@ class ArrayExprLowering {
caller.placeInput(argIface, arg);
}
Fortran::lower::LoweredResult res =
- Fortran::lower::genCallOpAndResult(loc, converter, symMap,
- getElementCtx(), caller,
- callSiteType, retTy)
- .first;
+ std::get<0>(Fortran::lower::genCallOpAndResult(
+ loc, converter, symMap, getElementCtx(), caller, callSiteType,
+ retTy));
return std::get<ExtValue>(res);
};
}
diff --git a/flang/test/Lower/HLFIR/calls-f77.f90 b/flang/test/Lower/HLFIR/calls-f77.f90
index 97d2307beeb06..3e3ac33bdf719 100644
--- a/flang/test/Lower/HLFIR/calls-f77.f90
+++ b/flang/test/Lower/HLFIR/calls-f77.f90
@@ -164,8 +164,8 @@ subroutine return_char(n)
! CHECK: %[[VAL_10:.*]] = arith.cmpi sgt, %[[VAL_8]], %[[VAL_9]] : index
! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_10]], %[[VAL_8]], %[[VAL_9]] : index
! CHECK: %[[VAL_13:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_11]] : index) {bindc_name = ".result"}
-! CHECK: %[[VAL_14:.*]] = fir.call @_QPc2foo(%[[VAL_13]], %[[VAL_11]]) fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_13]] typeparams %[[VAL_11]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK: %[[VAL_14:.*]] = fir.call @_QPc2foo(%[[VAL_13]], %[[VAL_11]]) fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
! -----------------------------------------------------------------------------
! Test calls with alternate returns
diff --git a/flang/test/Lower/HLFIR/elemental-array-ops.f90 b/flang/test/Lower/HLFIR/elemental-array-ops.f90
index 3a923b3c70ec5..9007e26b05a64 100644
--- a/flang/test/Lower/HLFIR/elemental-array-ops.f90
+++ b/flang/test/Lower/HLFIR/elemental-array-ops.f90
@@ -177,8 +177,8 @@ end subroutine char_return
! CHECK: ^bb0(%[[VAL_18:.*]]: index):
! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_12]]#0 (%[[VAL_18]]) typeparams %[[VAL_11]] : (!fir.box<!fir.array<?x!fir.char<1,3>>>, index, index) -> !fir.ref<!fir.char<1,3>>
! CHECK: %[[VAL_20:.*]] = fir.emboxchar %[[VAL_19]], %[[VAL_11]] : (!fir.ref<!fir.char<1,3>>, index) -> !fir.boxchar<1>
-! CHECK: %[[VAL_27:.*]] = fir.call @_QPcallee(%[[VAL_2]], %[[VAL_16]], %[[VAL_20]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,3>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[VAL_16]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>)
+! CHECK: %[[VAL_27:.*]] = fir.call @_QPcallee(%[[VAL_2]], %[[VAL_16]], %[[VAL_20]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,3>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[MustFree:.*]] = arith.constant false
! CHECK: %[[ResultTemp:.*]] = hlfir.as_expr %[[VAL_28]]#0 move %[[MustFree]] : (!fir.ref<!fir.char<1,3>>, i1) -> !hlfir.expr<!fir.char<1,3>>
! CHECK: hlfir.yield_element %[[ResultTemp]] : !hlfir.expr<!fir.char<1,3>>
diff --git a/flang/test/Lower/HLFIR/where.f90 b/flang/test/Lower/HLFIR/where.f90
index bd4cc64de9509..80f1c38510f05 100644
--- a/flang/test/Lower/HLFIR/where.f90
+++ b/flang/test/Lower/HLFIR/where.f90
@@ -76,9 +76,9 @@ subroutine where_cleanup()
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>> {bindc_name = ".result"}
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare {{.*}}Ex
! CHECK: hlfir.where {
+! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>)
! CHECK: %[[VAL_6:.*]] = fir.call @_QPreturn_temporary_mask() fastmath<contract> : () -> !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>
! CHECK: fir.save_result %[[VAL_6]] to %[[VAL_1]] : !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
-! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>)
! CHECK: %[[deref:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[MustFree:.*]] = arith.constant false
! CHECK: %[[ResTemp:.*]] = hlfir.as_expr %[[deref]] move %[[MustFree]] : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, i1) -> !hlfir.expr<?x!fir.logical<4>>
@@ -87,9 +87,9 @@ subroutine where_cleanup()
! CHECK: }
! CHECK: } do {
! CHECK: hlfir.region_assign {
+! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
! CHECK: %[[VAL_14:.*]] = fir.call @_QPreturn_temporary_array() fastmath<contract> : () -> !fir.box<!fir.heap<!fir.array<?xf32>>>
! CHECK: fir.save_result %[[VAL_14]] to %[[VAL_0]] : !fir.box<!fir.heap<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
-! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
! CHECK: %[[deref:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
! CHECK: %[[MustFree:.*]] = arith.constant false
! CHECK: %[[ResTemp:.*]] = hlfir.as_expr %[[deref]] move %[[MustFree]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, i1) -> !hlfir.expr<?xf32>
diff --git a/flang/test/Lower/Intrinsics/storage_size-2.f90 b/flang/test/Lower/Intrinsics/storage_size-2.f90
index 208070e04e6e6..41ea51961bca4 100644
--- a/flang/test/Lower/Intrinsics/storage_size-2.f90
+++ b/flang/test/Lower/Intrinsics/storage_size-2.f90
@@ -11,8 +11,8 @@ function return_char(l)
end interface
integer n
print*, storage_size(return_char(n))
-! CHECK: %[[val_16:.*]] = fir.call @_QPreturn_char(%[[res_addr:[^,]*]], %[[res_len:[^,]*]], {{.*}})
-! CHECK: %[[res:.*]]:2 = hlfir.declare %[[res_addr]] typeparams %[[res_len]]
+! CHECK: %[[res:.*]]:2 = hlfir.declare %[[res_addr:[^,]*]] typeparams %[[res_len:[^ ]*]]
+! CHECK: %[[val_16:.*]] = fir.call @_QPreturn_char(%[[res_addr]], %[[res_len]], {{.*}})
! CHECK: %[[false:.*]] = arith.constant false
! CHECK: %[[expr:.*]] = hlfir.as_expr %[[res]]#0 move %[[false]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: %[[assoc:.*]]:3 = hlfir.associate %[[expr]] typeparams %[[res_len]] {adapt.valuebyref} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1)
diff --git a/flang/test/Lower/OpenMP/omp-declare-reduction-derivedtype.f90 b/flang/test/Lower/OpenMP/omp-declare-reduction-derivedtype.f90
index 36bb131e677a3..f38018d2067cc 100644
--- a/flang/test/Lower/OpenMP/omp-declare-reduction-derivedtype.f90
+++ b/flang/test/Lower/OpenMP/omp-declare-reduction-derivedtype.f90
@@ -61,9 +61,9 @@ end module maxtype_mod
!CHECK: %[[OMP_IN_DECL:.*]]:2 = hlfir.declare %[[OMP_IN]] {uniq_name = "omp_in"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>)
!CHECK: fir.store %[[LHS_ARG]] to %[[OMP_OUT]] : !fir.ref<[[MAXTYPE]]>
!CHECK: %[[OMP_OUT_DECL:.*]]:2 = hlfir.declare %[[OMP_OUT]] {uniq_name = "omp_out"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>)
+!CHECK: %[[TMPRESULT:.*]]:2 = hlfir.declare %[[RESULT]] {uniq_name = ".tmp.func_result"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>)
!CHECK: %[[COMBINE_RESULT:.*]] = fir.call @_QMmaxtype_modPmycombine(%[[OMP_OUT_DECL]]#0, %[[OMP_IN_DECL]]#0) fastmath<contract> : (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) -> [[MAXTYPE]]
!CHECK: fir.save_result %[[COMBINE_RESULT]] to %[[RESULT]] : [[MAXTYPE]], !fir.ref<[[MAXTYPE]]>
-!CHECK: %[[TMPRESULT:.*]]:2 = hlfir.declare %[[RESULT]] {uniq_name = ".tmp.func_result"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>)
!CHECK: %false = arith.constant false
!CHECK: %[[EXPRRESULT:.*]] = hlfir.as_expr %[[TMPRESULT]]#0 move %false : (!fir.ref<[[MAXTYPE]]>, i1) -> !hlfir.expr<[[MAXTYPE]]>
!CHECK: %[[ASSOCIATE:.*]]:3 = hlfir.associate %[[EXPRRESULT]] {adapt.valuebyref} : (!hlfir.expr<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>, i1)
diff --git a/flang/test/Lower/array-elemental-calls-char-dynamic.f90 b/flang/test/Lower/array-elemental-calls-char-dynamic.f90
index 24b798904d82d..34baea2e9f3b2 100644
--- a/flang/test/Lower/array-elemental-calls-char-dynamic.f90
+++ b/flang/test/Lower/array-elemental-calls-char-dynamic.f90
@@ -39,8 +39,8 @@ elemental function bug_145151_1(c_dummy)
! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] : !fir.ref<i64>
! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_1]]#0 (%[[VAL_18]]) typeparams %[[VAL_3]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>, i64, index) -> !fir.boxchar<1>
! CHECK: %[[VAL_20:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_14]] : index) {bindc_name = ".result"}
-! CHECK: %[[VAL_21:.*]] = fir.call @_QPbug_145151_1(%[[VAL_20]], %[[VAL_14]], %[[VAL_19]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_20]] typeparams %[[VAL_14]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK: %[[VAL_21:.*]] = fir.call @_QPbug_145151_1(%[[VAL_20]], %[[VAL_14]], %[[VAL_19]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_23:.*]] = arith.constant false
! CHECK: %[[VAL_24:.*]] = hlfir.as_expr %[[VAL_22]]#0 move %[[VAL_23]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.yield_element %[[VAL_24]] : !hlfir.expr<!fir.char<1,?>>
@@ -97,8 +97,8 @@ elemental function bug_145151_2(x)
! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_2]]#0 (%[[VAL_14]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]] : !fir.ref<f32>
! CHECK: %[[VAL_17:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_12]] : index) {bindc_name = ".result"}
-! CHECK: %[[VAL_18:.*]] = fir.call @_QPbug_145151_2(%[[VAL_17]], %[[VAL_12]], %[[VAL_16]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, f32) -> !fir.boxchar<1>
! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_17]] typeparams %[[VAL_12]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK: %[[VAL_18:.*]] = fir.call @_QPbug_145151_2(%[[VAL_17]], %[[VAL_12]], %[[VAL_16]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, f32) -> !fir.boxchar<1>
! CHECK: %[[VAL_20:.*]] = arith.constant false
! CHECK: %[[VAL_21:.*]] = hlfir.as_expr %[[VAL_19]]#0 move %[[VAL_20]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.yield_element %[[VAL_21]] : !hlfir.expr<!fir.char<1,?>>
@@ -165,8 +165,8 @@ elemental function f_opt(x, opt)
! CHECK: fir.result %[[VAL_27]] : !fir.ref<f32>
! CHECK: }
! CHECK: %[[VAL_28:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_21]] : index) {bindc_name = ".result"}
-! CHECK: %[[VAL_29:.*]] = fir.call @_QPf_opt(%[[VAL_28]], %[[VAL_21]], %[[VAL_24]], %[[VAL_25]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.ref<f32>, !fir.ref<f32>) -> !fir.boxchar<1>
! CHECK: %[[VAL_30:.*]]:2 = hlfir.declare %[[VAL_28]] typeparams %[[VAL_21]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK: %[[VAL_29:.*]] = fir.call @_QPf_opt(%[[VAL_28]], %[[VAL_21]], %[[VAL_24]], %[[VAL_25]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.ref<f32>, !fir.ref<f32>) -> !fir.boxchar<1>
! CHECK: %[[VAL_31:.*]] = arith.constant false
! CHECK: %[[VAL_32:.*]] = hlfir.as_expr %[[VAL_30]]#0 move %[[VAL_31]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.yield_element %[[VAL_32]] : !hlfir.expr<!fir.char<1,?>>
@@ -231,8 +231,8 @@ elemental function f_poly(p1, p2)
! CHECK: %[[VAL_32:.*]] = hlfir.designate %[[VAL_1]]#0 (%[[VAL_31]]) : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, index) -> !fir.class<!fir.type<_QFtest_polymorphicTt>>
! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_2]]#0 (%[[VAL_31]]) : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, index) -> !fir.class<!fir.type<_QFtest_polymorphicTt>>
! CHECK: %[[VAL_34:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_29]] : index) {bindc_name = ".result"}
-! CHECK: %[[VAL_35:.*]] = fir.call @_QPf_poly(%[[VAL_34]], %[[VAL_29]], %[[VAL_32]], %[[VAL_33]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.class<!fir.type<_QFtest_polymorphicTt>>, !fir.class<!fir.type<_QFtest_polymorphicTt>>) -> !fir.boxchar<1>
! CHECK: %[[VAL_36:.*]]:2 = hlfir.declare %[[VAL_34]] typeparams %[[VAL_29]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK: %[[VAL_35:.*]] = fir.call @_QPf_poly(%[[VAL_34]], %[[VAL_29]], %[[VAL_32]], %[[VAL_33]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.class<!fir.type<_QFtest_polymorphicTt>>, !fir.class<!fir.type<_QFtest_polymorphicTt>>) -> !fir.boxchar<1>
! CHECK: %[[VAL_37:.*]] = arith.constant false
! CHECK: %[[VAL_38:.*]] = hlfir.as_expr %[[VAL_36]]#0 move %[[VAL_37]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.yield_element %[[VAL_38]] : !hlfir.expr<!fir.char<1,?>>
@@ -278,8 +278,8 @@ elemental function f_value(c_dummy)
! CHECK: %[[VAL_18:.*]] = hlfir.as_expr %[[VAL_17]] : (!fir.boxchar<1>) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: %[[VAL_19:.*]]:3 = hlfir.associate %[[VAL_18]] typeparams %[[VAL_16]] {adapt.valuebyref} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1)
! CHECK: %[[VAL_20:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_13]] : index) {bindc_name = ".result"}
-! CHECK: %[[VAL_21:.*]] = fir.call @_QPf_value(%[[VAL_20]], %[[VAL_13]], %[[VAL_19]]#0) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_20]] typeparams %[[VAL_13]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK: %[[VAL_21:.*]] = fir.call @_QPf_value(%[[VAL_20]], %[[VAL_13]], %[[VAL_19]]#0) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_23:.*]] = arith.constant false
! CHECK: %[[VAL_24:.*]] = hlfir.as_expr %[[VAL_22]]#0 move %[[VAL_23]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.end_associate %[[VAL_19]]#1, %[[VAL_19]]#2 : !fir.ref<!fir.char<1,?>>, i1
diff --git a/flang/test/Lower/array-elemental-calls-char.f90 b/flang/test/Lower/array-elemental-calls-char.f90
index f99bce4cfec81..b1c220991c6fe 100644
--- a/flang/test/Lower/array-elemental-calls-char.f90
+++ b/flang/test/Lower/array-elemental-calls-char.f90
@@ -253,8 +253,8 @@ subroutine foo6(c)
! CHECK: ^bb0(%[[VAL_17:.*]]: index):
! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_6]]#0 (%[[VAL_17]]) typeparams %[[VAL_2]]#1 : (!fir.box<!fir.array<10x!fir.char<1,?>>>, index, index) -> !fir.boxchar<1>
! CHECK: %[[VAL_28:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_15]] : index) {bindc_name = ".result"}
-! CHECK: %[[VAL_29:.*]] = fir.call @_QMchar_elemPelem_return_char(%[[VAL_28]], %[[VAL_15]], %[[VAL_18]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_30:.*]]:2 = hlfir.declare %[[VAL_28]] typeparams %[[VAL_15]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK: %[[VAL_29:.*]] = fir.call @_QMchar_elemPelem_return_char(%[[VAL_28]], %[[VAL_15]], %[[VAL_18]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_31:.*]] = arith.constant false
! CHECK: %[[VAL_32:.*]] = hlfir.as_expr %[[VAL_30]]#0 move %[[VAL_31]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.yield_element %[[VAL_32]] : !hlfir.expr<!fir.char<1,?>>
>From 413f7a4214a97003e143b639f500af29b1f4cf2f Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Mon, 26 Jan 2026 08:06:19 -0800
Subject: [PATCH 2/3] update fir.save_result to also use declare result
---
flang/lib/Lower/ConvertCall.cpp | 11 +++++++++--
flang/test/Lower/HLFIR/where.f90 | 4 ++--
.../OpenMP/omp-declare-reduction-derivedtype.f90 | 2 +-
flang/test/Lower/io-statement-clean-ups.f90 | 9 ++++++---
.../DoConcurrent/locally_destroyed_temp.f90 | 3 ++-
5 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index 8a0160e9a2fa3..486a933625573 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -1088,8 +1088,15 @@ extendedValueToHlfirEntity(mlir::Location loc, fir::FirOpBuilder &builder,
mlir::OpBuilder::InsertionGuard guard(builder);
if (insertBefore)
builder.setInsertionPoint(insertBefore);
- return hlfir::genDeclare(loc, builder, exv, name,
- fir::FortranVariableFlagsAttr{});
+ hlfir::EntityWithAttributes declare = hlfir::genDeclare(
+ loc, builder, exv, name, fir::FortranVariableFlagsAttr{});
+ // Replace the fir.save_result "to" by the declare results instead of
+ // directly using the alloca.
+ if (insertBefore && insertBefore->getNumResults() == 1)
+ for (auto resUser : insertBefore->getResult(0).getUsers())
+ if (auto save_result = llvm::dyn_cast<fir::SaveResultOp>(resUser))
+ save_result.getMemrefMutable().assign(declare.getFirBase());
+ return declare;
}
namespace {
/// Structure to hold the clean-up related to a dummy argument preparation
diff --git a/flang/test/Lower/HLFIR/where.f90 b/flang/test/Lower/HLFIR/where.f90
index 80f1c38510f05..dea344214928a 100644
--- a/flang/test/Lower/HLFIR/where.f90
+++ b/flang/test/Lower/HLFIR/where.f90
@@ -78,7 +78,7 @@ subroutine where_cleanup()
! CHECK: hlfir.where {
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>)
! CHECK: %[[VAL_6:.*]] = fir.call @_QPreturn_temporary_mask() fastmath<contract> : () -> !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>
-! CHECK: fir.save_result %[[VAL_6]] to %[[VAL_1]] : !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
+! CHECK: fir.save_result %[[VAL_6]] to %[[VAL_7]]#0 : !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[deref:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[MustFree:.*]] = arith.constant false
! CHECK: %[[ResTemp:.*]] = hlfir.as_expr %[[deref]] move %[[MustFree]] : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, i1) -> !hlfir.expr<?x!fir.logical<4>>
@@ -89,7 +89,7 @@ subroutine where_cleanup()
! CHECK: hlfir.region_assign {
! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
! CHECK: %[[VAL_14:.*]] = fir.call @_QPreturn_temporary_array() fastmath<contract> : () -> !fir.box<!fir.heap<!fir.array<?xf32>>>
-! CHECK: fir.save_result %[[VAL_14]] to %[[VAL_0]] : !fir.box<!fir.heap<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: fir.save_result %[[VAL_14]] to %[[VAL_15]]#0 : !fir.box<!fir.heap<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
! CHECK: %[[deref:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
! CHECK: %[[MustFree:.*]] = arith.constant false
! CHECK: %[[ResTemp:.*]] = hlfir.as_expr %[[deref]] move %[[MustFree]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, i1) -> !hlfir.expr<?xf32>
diff --git a/flang/test/Lower/OpenMP/omp-declare-reduction-derivedtype.f90 b/flang/test/Lower/OpenMP/omp-declare-reduction-derivedtype.f90
index f38018d2067cc..ff70acbb10e32 100644
--- a/flang/test/Lower/OpenMP/omp-declare-reduction-derivedtype.f90
+++ b/flang/test/Lower/OpenMP/omp-declare-reduction-derivedtype.f90
@@ -63,7 +63,7 @@ end module maxtype_mod
!CHECK: %[[OMP_OUT_DECL:.*]]:2 = hlfir.declare %[[OMP_OUT]] {uniq_name = "omp_out"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>)
!CHECK: %[[TMPRESULT:.*]]:2 = hlfir.declare %[[RESULT]] {uniq_name = ".tmp.func_result"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>)
!CHECK: %[[COMBINE_RESULT:.*]] = fir.call @_QMmaxtype_modPmycombine(%[[OMP_OUT_DECL]]#0, %[[OMP_IN_DECL]]#0) fastmath<contract> : (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) -> [[MAXTYPE]]
-!CHECK: fir.save_result %[[COMBINE_RESULT]] to %[[RESULT]] : [[MAXTYPE]], !fir.ref<[[MAXTYPE]]>
+!CHECK: fir.save_result %[[COMBINE_RESULT]] to %[[TMPRESULT]]#0 : [[MAXTYPE]], !fir.ref<[[MAXTYPE]]>
!CHECK: %false = arith.constant false
!CHECK: %[[EXPRRESULT:.*]] = hlfir.as_expr %[[TMPRESULT]]#0 move %false : (!fir.ref<[[MAXTYPE]]>, i1) -> !hlfir.expr<[[MAXTYPE]]>
!CHECK: %[[ASSOCIATE:.*]]:3 = hlfir.associate %[[EXPRRESULT]] {adapt.valuebyref} : (!hlfir.expr<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>, i1)
diff --git a/flang/test/Lower/io-statement-clean-ups.f90 b/flang/test/Lower/io-statement-clean-ups.f90
index a8d7950cee8b7..7e590e7236322 100644
--- a/flang/test/Lower/io-statement-clean-ups.f90
+++ b/flang/test/Lower/io-statement-clean-ups.f90
@@ -17,22 +17,25 @@ function gen_temp_character()
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>>
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>>
! CHECK: fir.call @_FortranAioBeginOpenUnit
+! CHECK: %[[DECLARE3:.*]] = fir.declare %[[VAL_3]]
! CHECK: %[[VAL_15:.*]] = fir.call @_QPgen_temp_character() {{.*}}: () -> !fir.box<!fir.heap<!fir.char<1,?>>>
-! CHECK: fir.save_result %[[VAL_15]] to %[[VAL_3]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
+! CHECK: fir.save_result %[[VAL_15]] to %[[DECLARE3]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: %[[VAL_21:.*]] = fir.call @_FortranAioSetEncoding
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: %[[VAL_23:.*]] = fir.box_addr %[[VAL_22]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>>
! CHECK: fir.freemem %[[VAL_23]] : !fir.heap<!fir.char<1,?>>
! CHECK: fir.if %[[VAL_21]] {
+! CHECK: %[[DECLARE2:.*]] = fir.declare %[[VAL_2]]
! CHECK: %[[VAL_27:.*]] = fir.call @_QPgen_temp_character() {{.*}}: () -> !fir.box<!fir.heap<!fir.char<1,?>>>
-! CHECK: fir.save_result %[[VAL_27]] to %[[VAL_2]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
+! CHECK: fir.save_result %[[VAL_27]] to %[[DECLARE2]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: %[[VAL_33:.*]] = fir.call @_FortranAioSetFile
! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_2]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: %[[VAL_35:.*]] = fir.box_addr %[[VAL_34]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>>
! CHECK: fir.freemem %[[VAL_35]] : !fir.heap<!fir.char<1,?>>
! CHECK: fir.if %[[VAL_33]] {
+! CHECK: %[[DECLARE1:.*]] = fir.declare %[[VAL_1]]
! CHECK: %[[VAL_39:.*]] = fir.call @_QPgen_temp_character() {{.*}}: () -> !fir.box<!fir.heap<!fir.char<1,?>>>
-! CHECK: fir.save_result %[[VAL_39]] to %[[VAL_1]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
+! CHECK: fir.save_result %[[VAL_39]] to %[[DECLARE1]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: fir.call @_FortranAioSetPad
! CHECK: %[[VAL_46:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: %[[VAL_47:.*]] = fir.box_addr %[[VAL_46]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>>
diff --git a/flang/test/Transforms/DoConcurrent/locally_destroyed_temp.f90 b/flang/test/Transforms/DoConcurrent/locally_destroyed_temp.f90
index 6a29b57a90d00..6c7981713ccc5 100644
--- a/flang/test/Transforms/DoConcurrent/locally_destroyed_temp.f90
+++ b/flang/test/Transforms/DoConcurrent/locally_destroyed_temp.f90
@@ -56,8 +56,9 @@ end program main
! DEVICE: omp.distribute {
! COMMON: omp.wsloop {
! COMMON: omp.loop_nest {{.*}} {
+! COMMON: %[[DECLARE:.*]]:2 = hlfir.declare %[[LOCAL_TEMP]]
! COMMON: %[[TEMP_VAL:.*]] = fir.call @_QMstruct_modPconstruct_from_components
-! COMMON: fir.save_result %[[TEMP_VAL]] to %[[LOCAL_TEMP]]
+! COMMON: fir.save_result %[[TEMP_VAL]] to %[[DECLARE]]#0
! COMMON: %[[EMBOXED_LOCAL:.*]] = fir.embox %[[LOCAL_TEMP]]
! COMMON: %[[CONVERTED_LOCAL:.*]] = fir.convert %[[EMBOXED_LOCAL]]
! COMMON: fir.call @_FortranADestroy(%[[CONVERTED_LOCAL]])
>From 54485a70334e57e441f21e03c388dad453b3c8c3 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Mon, 26 Jan 2026 08:08:32 -0800
Subject: [PATCH 3/3] comment typo
---
flang/lib/Lower/ConvertCall.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index 486a933625573..179626624822d 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -1078,7 +1078,7 @@ extendedValueToHlfirEntity(mlir::Location loc, fir::FirOpBuilder &builder,
return hlfir::EntityWithAttributes{asExpr.getResult()};
}
// TODO: better scoping model in FIR.
- // The declare for result storage allocated on the callee side must be
+ // The declare for result storage allocated on the callee side must
// currently be emitted before the call so that MLIR level inlining does not
// break aliasing by introducing a fir.dummy_scope between the alloca and
// fir.declare that leads the alias analysis to think that the result
More information about the flang-commits
mailing list