[flang-commits] [flang] da60b9e - [flang] Fixed managing copy-in/copy-out temps.
Slava Zakharin via flang-commits
flang-commits at lists.llvm.org
Tue May 23 09:37:35 PDT 2023
Author: Slava Zakharin
Date: 2023-05-23T09:35:17-07:00
New Revision: da60b9e7dc6b217ecd8f422a71ee3aa4a4022015
URL: https://github.com/llvm/llvm-project/commit/da60b9e7dc6b217ecd8f422a71ee3aa4a4022015
DIFF: https://github.com/llvm/llvm-project/commit/da60b9e7dc6b217ecd8f422a71ee3aa4a4022015.diff
LOG: [flang] Fixed managing copy-in/copy-out temps.
There are several observations regarding the copy-in/copy-out:
* Actual argument associated with INTENT(OUT) dummy argument that
requires finalization (7.5.6.3 p. 7) may be read by the finalization
function, so a copy-in is required.
* A temporary created for the copy-in/copy-out must be destroyed
without finalization after the call (or after the corresponding copy-out),
otherwise, memory leaks may occur.
* The copy-out assignment must not perform finalization for the LHS.
* The copy-out assignment from the temporary to the actual argument
may or may not need to initialize the LHS.
This change-set introduces new runtime methods: CopyOutAssign and
DestroyWithoutFinalization. They are called by the compiler generated
code to match the behavior described above.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D151135
Added:
Modified:
flang/include/flang/Lower/CallInterface.h
flang/include/flang/Optimizer/Builder/Runtime/Assign.h
flang/include/flang/Optimizer/Builder/Runtime/Derived.h
flang/include/flang/Runtime/assign.h
flang/include/flang/Runtime/derived-api.h
flang/lib/Lower/CallInterface.cpp
flang/lib/Lower/ConvertCall.cpp
flang/lib/Lower/ConvertExpr.cpp
flang/lib/Optimizer/Builder/Runtime/Assign.cpp
flang/lib/Optimizer/Builder/Runtime/Derived.cpp
flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
flang/runtime/assign.cpp
flang/runtime/derived-api.cpp
flang/test/HLFIR/copy-in-out-codegen.fir
flang/test/Lower/call-by-value-attr.f90
flang/test/Lower/call-copy-in-out.f90
flang/test/Lower/dummy-argument-assumed-shape-optional.f90
flang/test/Lower/dummy-argument-optional-2.f90
flang/test/Lower/optional-value-caller.f90
Removed:
################################################################################
diff --git a/flang/include/flang/Lower/CallInterface.h b/flang/include/flang/Lower/CallInterface.h
index fc338dbe1e8a9..8586a056f180e 100644
--- a/flang/include/flang/Lower/CallInterface.h
+++ b/flang/include/flang/Lower/CallInterface.h
@@ -167,6 +167,11 @@ class CallInterface {
bool mustBeMadeContiguous() const;
/// Does the dummy argument have the VALUE attribute?
bool hasValueAttribute() const;
+ /// Does the dummy argument have the ALLOCATABLE attribute?
+ bool hasAllocatableAttribute() const;
+ /// May the dummy argument require INTENT(OUT) finalization
+ /// on entry to the invoked procedure? Provides conservative answer.
+ bool mayRequireIntentoutFinalization() const;
/// How entity is passed by.
PassEntityBy passBy;
/// What is the entity (SymbolRef for callee/ActualArgument* for caller)
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Assign.h b/flang/include/flang/Optimizer/Builder/Runtime/Assign.h
index f33a76a6e8299..14d338b7093e8 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/Assign.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Assign.h
@@ -48,5 +48,26 @@ void genAssignExplicitLengthCharacter(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value destBox,
mlir::Value sourceBox);
+/// Generate runtime call to assign \p sourceBox to \p destBox.
+/// \p destBox must be a fir.ref<fir.box<T>> and \p sourceBox a fir.box<T>.
+/// \p destBox Fortran descriptor may be modified if destBox is an allocatable
+/// according to Fortran allocatable assignment rules, otherwise it is not
+/// modified.
+void genAssignTemporary(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value destBox, mlir::Value sourceBox);
+
+/// Generate runtime call to CopyOutAssign to assign \p sourceBox to
+/// \p destBox. This call implements the copy-out of a temporary
+/// (\p sourceBox) to the actual argument (\p destBox) passed to a procedure,
+/// after the procedure returns to the caller.
+/// If \p skipToInit is false, then \p destBox will be initialized before
+/// the assignment, otherwise, it is assumed to be already initialized.
+/// The runtime makes sure that there is no reallocation of the top-level
+/// entity represented by \p destBox. If reallocation is required
+/// for the components of \p destBox, then it is done without finalization.
+void genCopyOutAssign(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value destBox, mlir::Value sourceBox,
+ bool skipToInit);
+
} // namespace fir::runtime
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_ASSIGN_H
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Derived.h b/flang/include/flang/Optimizer/Builder/Runtime/Derived.h
index 8539d2781c33b..30998f8b0ea65 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/Derived.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Derived.h
@@ -31,6 +31,12 @@ void genDerivedTypeInitialize(fir::FirOpBuilder &builder, mlir::Location loc,
void genDerivedTypeDestroy(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value box);
+/// Generate call to derived type destruction runtime routine to
+/// destroy \p box without finalization
+void genDerivedTypeDestroyWithoutFinalization(fir::FirOpBuilder &builder,
+ mlir::Location loc,
+ mlir::Value box);
+
/// Generate call to `PointerNullifyDerived` runtime function to nullify
/// and set the correct dynamic type to a boxed derived type.
void genNullifyDerivedType(fir::FirOpBuilder &builder, mlir::Location loc,
diff --git a/flang/include/flang/Runtime/assign.h b/flang/include/flang/Runtime/assign.h
index 0b049b9d4b75d..779997dab6186 100644
--- a/flang/include/flang/Runtime/assign.h
+++ b/flang/include/flang/Runtime/assign.h
@@ -36,6 +36,8 @@ void RTNAME(Assign)(Descriptor &to, const Descriptor &from,
// reallocation.
void RTNAME(AssignTemporary)(Descriptor &to, const Descriptor &from,
const char *sourceFile = nullptr, int sourceLine = 0);
+void RTNAME(CopyOutAssign)(Descriptor &to, const Descriptor &from,
+ bool skipToInit, const char *sourceFile = nullptr, int sourceLine = 0);
// This variant is for assignments to explicit-length CHARACTER left-hand
// sides that might need to handle truncation or blank-fill, and
// must maintain the character length even if an allocatable array
diff --git a/flang/include/flang/Runtime/derived-api.h b/flang/include/flang/Runtime/derived-api.h
index 651ab406939e6..3bf631bc4d0c7 100644
--- a/flang/include/flang/Runtime/derived-api.h
+++ b/flang/include/flang/Runtime/derived-api.h
@@ -37,6 +37,11 @@ void RTNAME(Initialize)(
// storage.
void RTNAME(Destroy)(const Descriptor &);
+/// Deallocates any allocatable/automatic components.
+/// Does not deallocate the descriptor's storage.
+/// Does not perform any finalization.
+void RTNAME(DestroyWithoutFinalization)(const Descriptor &);
+
// Intrinsic or defined assignment, with scalar expansion but not type
// conversion.
void RTNAME(Assign)(const Descriptor &, const Descriptor &,
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index b7c4d920b37c5..833ad73d164a4 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -1229,6 +1229,57 @@ bool Fortran::lower::CallInterface<T>::PassedEntity::hasValueAttribute() const {
Fortran::evaluate::characteristics::DummyDataObject::Attr::Value);
}
+template <typename T>
+bool Fortran::lower::CallInterface<T>::PassedEntity::hasAllocatableAttribute()
+ const {
+ if (!characteristics)
+ return false;
+ const auto *dummy =
+ std::get_if<Fortran::evaluate::characteristics::DummyDataObject>(
+ &characteristics->u);
+ using Attrs = Fortran::evaluate::characteristics::DummyDataObject::Attr;
+ return dummy && dummy->attrs.test(Attrs::Allocatable);
+}
+
+template <typename T>
+bool Fortran::lower::CallInterface<
+ T>::PassedEntity::mayRequireIntentoutFinalization() const {
+ // Conservatively assume that the finalization is needed.
+ if (!characteristics)
+ return true;
+
+ // No INTENT(OUT) dummy arguments do not require finalization on entry.
+ if (!isIntentOut())
+ return false;
+
+ const auto *dummy =
+ std::get_if<Fortran::evaluate::characteristics::DummyDataObject>(
+ &characteristics->u);
+ if (!dummy)
+ return true;
+
+ // POINTER/ALLOCATABLE dummy arguments do not require finalization.
+ using Attrs = Fortran::evaluate::characteristics::DummyDataObject::Attr;
+ if (dummy->attrs.test(Attrs::Allocatable) ||
+ dummy->attrs.test(Attrs::Pointer))
+ return false;
+
+ // Polymorphic and unlimited polymorphic INTENT(OUT) dummy arguments
+ // may need finalization.
+ const Fortran::evaluate::DynamicType &type = dummy->type.type();
+ if (type.IsPolymorphic() || type.IsUnlimitedPolymorphic())
+ return true;
+
+ // INTENT(OUT) dummy arguments of derived types require finalization,
+ // if their type has finalization.
+ const Fortran::semantics::DerivedTypeSpec *derived =
+ Fortran::evaluate::GetDerivedTypeSpec(type);
+ if (!derived)
+ return false;
+
+ return Fortran::semantics::IsFinalizable(*derived);
+}
+
template <typename T>
void Fortran::lower::CallInterface<T>::determineInterface(
bool isImplicit,
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index 0c9d7af9678ec..d8160c6b7b198 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -925,6 +925,13 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
// Copy-in non contiguous variables.
assert(entity.getType().isa<fir::BaseBoxType>() &&
"expect non simply contiguous variables to be boxes");
+ // TODO: for non-finalizable monomorphic derived type actual
+ // arguments associated with INTENT(OUT) dummy arguments
+ // we may avoid doing the copy and only allocate the temporary.
+ // The codegen would do a "mold" allocation instead of "sourced"
+ // allocation for the temp in this case. We can communicate
+ // this to the codegen via some CopyInOp flag.
+ // This is a performance concern.
auto copyIn = builder.create<hlfir::CopyInOp>(
loc, entity, /*var_is_present=*/mlir::Value{});
entity = hlfir::Entity{copyIn.getCopiedIn()};
diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index 47d5ed4c02e54..b5423205ed065 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -2153,7 +2153,27 @@ class ScalarExprLowering {
auto doCopyIn = [&]() -> ExtValue {
ExtValue temp = genArrayTempFromMold(actualArg, tempName);
- if (!arg.mayBeReadByCall()) {
+ if (!arg.mayBeReadByCall() &&
+ // INTENT(OUT) dummy argument finalization, automatically
+ // done when the procedure is invoked, may imply reading
+ // the argument value in the finalization routine.
+ // So we need to make a copy, if finalization may occur.
+ // TODO: do we have to avoid the copying for an actual
+ // argument of type that does not require finalization?
+ !arg.mayRequireIntentoutFinalization() &&
+ // ALLOCATABLE dummy argument may require finalization.
+ // If it has to be automatically deallocated at the end
+ // of the procedure invocation (9.7.3.2 p. 2),
+ // then the finalization may happen if the actual argument
+ // is allocated (7.5.6.3 p. 2).
+ !arg.hasAllocatableAttribute()) {
+ // We have to initialize the temp if it may have components
+ // that need initialization. If there are no components
+ // requiring initialization, then the call is a no-op.
+ if (getElementTypeOf(temp).isa<fir::RecordType>()) {
+ mlir::Value tempBox = fir::getBase(builder.createBox(loc, temp));
+ fir::runtime::genDerivedTypeInitialize(builder, loc, tempBox);
+ }
return temp;
}
if (!isActualArgBox || inlineCopyInOutForBoxes) {
@@ -2161,12 +2181,16 @@ class ScalarExprLowering {
return temp;
}
- // Generate Assign() call to copy data from the actualArg
- // to a temporary.
+ // Generate AssignTemporary() call to copy data from the actualArg
+ // to a temporary. AssignTemporary() will initialize the temporary,
+ // if needed, before doing the assignment, which is required
+ // since the temporary's components (if any) are uninitialized
+ // at this point.
mlir::Value destBox = fir::getBase(builder.createBox(loc, temp));
mlir::Value boxRef = builder.createTemporary(loc, destBox.getType());
builder.create<fir::StoreOp>(loc, destBox, boxRef);
- fir::runtime::genAssign(builder, loc, boxRef, fir::getBase(actualArg));
+ fir::runtime::genAssignTemporary(builder, loc, boxRef,
+ fir::getBase(actualArg));
return temp;
};
@@ -2272,21 +2296,37 @@ class ScalarExprLowering {
genArrayCopy(copyOutPair.var, copyOutPair.temp);
return;
}
- // Generate Assign() call to copy data from the temporary
+ // Generate CopyOutAssign() call to copy data from the temporary
// to the actualArg. Note that in case the actual argument
- // is ALLOCATABLE/POINTER the Assign() implementation
+ // is ALLOCATABLE/POINTER the CopyOutAssign() implementation
// should not engage its reallocation, because the temporary
// is rank, shape and type compatible with it.
+ // Moreover, CopyOutAssign() guarantees that there will be no
+ // finalization for the LHS even if it is of a derived type
+ // with finalization.
mlir::Value srcBox =
fir::getBase(builder.createBox(loc, copyOutPair.temp));
mlir::Value destBox =
fir::getBase(builder.createBox(loc, copyOutPair.var));
mlir::Value destBoxRef = builder.createTemporary(loc, destBox.getType());
builder.create<fir::StoreOp>(loc, destBox, destBoxRef);
- fir::runtime::genAssign(builder, loc, destBoxRef, srcBox);
+ fir::runtime::genCopyOutAssign(builder, loc, destBoxRef, srcBox,
+ /*skipToInit=*/true);
};
if (!copyOutPair.restrictCopyAndFreeAtRuntime) {
doCopyOut();
+
+ if (fir::getElementTypeOf(copyOutPair.temp).isa<fir::RecordType>()) {
+ // Destroy components of the temporary (if any).
+ // If there are no components requiring destruction, then the call
+ // is a no-op.
+ mlir::Value tempBox =
+ fir::getBase(builder.createBox(loc, copyOutPair.temp));
+ fir::runtime::genDerivedTypeDestroyWithoutFinalization(builder, loc,
+ tempBox);
+ }
+
+ // Deallocate the top-level entity of the temporary.
builder.create<fir::FreeMemOp>(loc, fir::getBase(copyOutPair.temp));
return;
}
@@ -2294,6 +2334,17 @@ class ScalarExprLowering {
builder.genIfThen(loc, *copyOutPair.restrictCopyAndFreeAtRuntime)
.genThen([&]() {
doCopyOut();
+ if (fir::getElementTypeOf(copyOutPair.temp).isa<fir::RecordType>()) {
+ // Destroy components of the temporary (if any).
+ // If there are no components requiring destruction, then the call
+ // is a no-op.
+ mlir::Value tempBox =
+ fir::getBase(builder.createBox(loc, copyOutPair.temp));
+ fir::runtime::genDerivedTypeDestroyWithoutFinalization(builder, loc,
+ tempBox);
+ }
+
+ // Deallocate the top-level entity of the temporary.
builder.create<fir::FreeMemOp>(loc, fir::getBase(copyOutPair.temp));
})
.end();
diff --git a/flang/lib/Optimizer/Builder/Runtime/Assign.cpp b/flang/lib/Optimizer/Builder/Runtime/Assign.cpp
index db4de8ac9f377..ad0c2af85cdf3 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Assign.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Assign.cpp
@@ -54,3 +54,34 @@ void fir::runtime::genAssignExplicitLengthCharacter(fir::FirOpBuilder &builder,
sourceBox, sourceFile, sourceLine);
builder.create<fir::CallOp>(loc, func, args);
}
+
+void fir::runtime::genAssignTemporary(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Value destBox,
+ mlir::Value sourceBox) {
+ auto func =
+ fir::runtime::getRuntimeFunc<mkRTKey(AssignTemporary)>(loc, builder);
+ auto fTy = func.getFunctionType();
+ auto sourceFile = fir::factory::locationToFilename(builder, loc);
+ auto sourceLine =
+ fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
+ auto args = fir::runtime::createArguments(builder, loc, fTy, destBox,
+ sourceBox, sourceFile, sourceLine);
+ builder.create<fir::CallOp>(loc, func, args);
+}
+
+void fir::runtime::genCopyOutAssign(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Value destBox,
+ mlir::Value sourceBox, bool skipToInit) {
+ auto func =
+ fir::runtime::getRuntimeFunc<mkRTKey(CopyOutAssign)>(loc, builder);
+ auto fTy = func.getFunctionType();
+ auto sourceFile = fir::factory::locationToFilename(builder, loc);
+ auto sourceLine =
+ fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
+ auto i1Ty = builder.getIntegerType(1);
+ auto skipToInitVal = builder.createIntegerConstant(loc, i1Ty, skipToInit);
+ auto args =
+ fir::runtime::createArguments(builder, loc, fTy, destBox, sourceBox,
+ skipToInitVal, sourceFile, sourceLine);
+ builder.create<fir::CallOp>(loc, func, args);
+}
diff --git a/flang/lib/Optimizer/Builder/Runtime/Derived.cpp b/flang/lib/Optimizer/Builder/Runtime/Derived.cpp
index 796f35631bbee..e6cd9ff5a797d 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Derived.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Derived.cpp
@@ -37,6 +37,15 @@ void fir::runtime::genDerivedTypeDestroy(fir::FirOpBuilder &builder,
builder.create<fir::CallOp>(loc, func, args);
}
+void fir::runtime::genDerivedTypeDestroyWithoutFinalization(
+ fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value box) {
+ auto func = fir::runtime::getRuntimeFunc<mkRTKey(DestroyWithoutFinalization)>(
+ loc, builder);
+ auto fTy = func.getFunctionType();
+ auto args = fir::runtime::createArguments(builder, loc, fTy, box);
+ builder.create<fir::CallOp>(loc, func, args);
+}
+
void fir::runtime::genNullifyDerivedType(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value box,
fir::RecordType derivedType,
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
index ab1f7417531bd..20718aaa42da1 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
@@ -13,6 +13,7 @@
#include "flang/Optimizer/Builder/HLFIRTools.h"
#include "flang/Optimizer/Builder/MutableBox.h"
#include "flang/Optimizer/Builder/Runtime/Assign.h"
+#include "flang/Optimizer/Builder/Runtime/Derived.h"
#include "flang/Optimizer/Builder/Runtime/Inquiry.h"
#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
@@ -47,7 +48,7 @@ static mlir::Value genAllocatableTempFromSourceBox(mlir::Location loc,
mlir::Type fromBoxHeapType = fir::BoxType::get(fromHeapType);
mlir::Value fromMutableBox =
fir::factory::genNullBoxStorage(builder, loc, fromBoxHeapType);
- fir::runtime::genAssign(builder, loc, fromMutableBox, sourceBox);
+ fir::runtime::genAssignTemporary(builder, loc, fromMutableBox, sourceBox);
mlir::Value copy = builder.create<fir::LoadOp>(loc, fromMutableBox);
return copy;
}
@@ -248,20 +249,32 @@ class CopyOutOpConversion : public mlir::OpRewritePattern<hlfir::CopyOutOp> {
.genThen([&]() {
mlir::Value temp = copyOutOp.getTemp();
if (mlir::Value var = copyOutOp.getVar()) {
- auto mutableBox = builder.createTemporary(loc, var.getType());
- builder.create<fir::StoreOp>(loc, var, mutableBox);
- // Generate Assign() call to copy data from the temporary
- // to the variable. Note that in case the actual argument
- // is ALLOCATABLE/POINTER the Assign() implementation
+ auto mutableBoxTo = builder.createTemporary(loc, var.getType());
+ builder.create<fir::StoreOp>(loc, var, mutableBoxTo);
+ // Generate CopyOutAssign() call to copy data from the temporary
+ // to the actualArg. Note that in case the actual argument
+ // is ALLOCATABLE/POINTER the CopyOutAssign() implementation
// should not engage its reallocation, because the temporary
- // is rank, shape and type compatible with it (it was created
- // from the variable).
- fir::runtime::genAssign(builder, loc, mutableBox, temp);
+ // is rank, shape and type compatible with it.
+ // Moreover, CopyOutAssign() guarantees that there will be no
+ // finalization for the LHS even if it is of a derived type
+ // with finalization.
+ fir::runtime::genCopyOutAssign(builder, loc, mutableBoxTo, temp,
+ /*skipToInit=*/true);
}
+ // Destroy components of the temporary (if any).
+ fir::runtime::genDerivedTypeDestroyWithoutFinalization(builder, loc,
+ temp);
mlir::Type heapType =
fir::HeapType::get(fir::dyn_cast_ptrOrBoxEleTy(temp.getType()));
mlir::Value tempAddr =
builder.create<fir::BoxAddrOp>(loc, heapType, temp);
+
+ // Deallocate the top-level entity of the temporary.
+ //
+ // Note that this FreeMemOp is coupled with the runtime
+ // allocation engaged by the code generated by
+ // genAllocatableTempFromSourceBox().
builder.create<fir::FreeMemOp>(loc, tempAddr);
})
.end();
diff --git a/flang/runtime/assign.cpp b/flang/runtime/assign.cpp
index f75fe94bf3009..49e86c20b17cc 100644
--- a/flang/runtime/assign.cpp
+++ b/flang/runtime/assign.cpp
@@ -561,9 +561,32 @@ void RTNAME(AssignTemporary)(Descriptor &to, const Descriptor &from,
}
}
}
+
Assign(to, from, terminator, PolymorphicLHS);
}
+void RTNAME(CopyOutAssign)(Descriptor &to, const Descriptor &from,
+ bool skipToInit, const char *sourceFile, int sourceLine) {
+ Terminator terminator{sourceFile, sourceLine};
+ // Initialize the "to" if it is of derived type that needs initialization.
+ if (!skipToInit) {
+ if (const DescriptorAddendum * addendum{to.Addendum()}) {
+ if (const auto *derived{addendum->derivedType()}) {
+ if (!derived->noInitializationNeeded()) {
+ if (ReturnError(terminator, Initialize(to, *derived, terminator)) !=
+ StatOk) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ // Copyout from the temporary must not cause any finalizations
+ // for LHS.
+ Assign(to, from, terminator, NoAssignFlags);
+}
+
void RTNAME(AssignExplicitLengthCharacter)(Descriptor &to,
const Descriptor &from, const char *sourceFile, int sourceLine) {
Terminator terminator{sourceFile, sourceLine};
diff --git a/flang/runtime/derived-api.cpp b/flang/runtime/derived-api.cpp
index 9b3455d9f0293..8df49c5841a1c 100644
--- a/flang/runtime/derived-api.cpp
+++ b/flang/runtime/derived-api.cpp
@@ -156,5 +156,15 @@ bool RTNAME(ExtendsTypeOf)(const Descriptor &a, const Descriptor &mold) {
return false;
}
+void RTNAME(DestroyWithoutFinalization)(const Descriptor &descriptor) {
+ if (const DescriptorAddendum * addendum{descriptor.Addendum()}) {
+ if (const auto *derived{addendum->derivedType()}) {
+ if (!derived->noDestructionNeeded()) {
+ Destroy(descriptor, /*finalize=*/false, *derived);
+ }
+ }
+ }
+}
+
} // extern "C"
} // namespace Fortran::runtime
diff --git a/flang/test/HLFIR/copy-in-out-codegen.fir b/flang/test/HLFIR/copy-in-out-codegen.fir
index 71962d90f013a..462dc483a21f6 100644
--- a/flang/test/HLFIR/copy-in-out-codegen.fir
+++ b/flang/test/HLFIR/copy-in-out-codegen.fir
@@ -21,7 +21,7 @@ func.func @test_copy_in(%box: !fir.box<!fir.array<?xf64>>) {
// CHECK: fir.store %[[VAL_8]] to %[[VAL_1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
// CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) -> !fir.ref<!fir.box<none>>
// CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?xf64>>) -> !fir.box<none>
-// CHECK: %[[VAL_15:.*]] = fir.call @_FortranAAssign(%[[VAL_12]], %[[VAL_13]],
+// CHECK: %[[VAL_15:.*]] = fir.call @_FortranAAssignTemporary(%[[VAL_12]], %[[VAL_13]],
// CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
// CHECK: %[[VAL_17:.*]] = fir.rebox %[[VAL_16]] : (!fir.box<!fir.heap<!fir.array<?xf64>>>) -> !fir.box<!fir.array<?xf64>>
// CHECK: fir.result %[[VAL_17]] : !fir.box<!fir.array<?xf64>>
@@ -52,7 +52,7 @@ func.func @test_copy_in_optional(%box: !fir.box<!fir.array<?xf64>>, %is_present:
// CHECK: fir.store %[[VAL_10]] to %[[VAL_2]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
// CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) -> !fir.ref<!fir.box<none>>
// CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?xf64>>) -> !fir.box<none>
-// CHECK: %[[VAL_17:.*]] = fir.call @_FortranAAssign(%[[VAL_14]], %[[VAL_15]],
+// CHECK: %[[VAL_17:.*]] = fir.call @_FortranAAssignTemporary(%[[VAL_14]], %[[VAL_15]],
// CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_2]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
// CHECK: %[[VAL_19:.*]] = fir.rebox %[[VAL_18]] : (!fir.box<!fir.heap<!fir.array<?xf64>>>) -> !fir.box<!fir.array<?xf64>>
// CHECK: fir.result %[[VAL_19]] : !fir.box<!fir.array<?xf64>>
@@ -73,8 +73,10 @@ func.func @test_copy_out_no_copy_back(%temp: !fir.box<!fir.array<?xf64>>, %was_c
// CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf64>>,
// CHECK-SAME: %[[VAL_1:.*]]: i1) {
// CHECK-NEXT: fir.if %[[VAL_1]] {
-// CHECK-NEXT: %[[VAL_2:.*]] = fir.box_addr %[[VAL_0]] : (!fir.box<!fir.array<?xf64>>) -> !fir.heap<!fir.array<?xf64>>
-// CHECK-NEXT: fir.freemem %[[VAL_2]] : !fir.heap<!fir.array<?xf64>>
+// CHECK-NEXT: %[[VAL_2:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?xf64>>) -> !fir.box<none>
+// CHECK-NEXT: %[[VAL_3:.*]] = fir.call @_FortranADestroyWithoutFinalization(%[[VAL_2]]) : (!fir.box<none>) -> none
+// CHECK-NEXT: %[[VAL_4:.*]] = fir.box_addr %[[VAL_0]] : (!fir.box<!fir.array<?xf64>>) -> !fir.heap<!fir.array<?xf64>>
+// CHECK-NEXT: fir.freemem %[[VAL_4]] : !fir.heap<!fir.array<?xf64>>
// CHECK-NEXT: }
func.func @test_copy_out_copy_back(%box: !fir.box<!fir.array<?xf64>>, %temp: !fir.box<!fir.array<?xf64>>, %was_copied: i1) {
@@ -88,11 +90,14 @@ func.func @test_copy_out_copy_back(%box: !fir.box<!fir.array<?xf64>>, %temp: !fi
// CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.array<?xf64>>
// CHECK: fir.if %[[VAL_2]] {
// CHECK: fir.store %[[VAL_0]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.array<?xf64>>>
-// CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.box<!fir.array<?xf64>>>) -> !fir.ref<!fir.box<none>>
-// CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_1]] : (!fir.box<!fir.array<?xf64>>) -> !fir.box<none>
-// CHECK: %[[VAL_10:.*]] = fir.call @_FortranAAssign(%[[VAL_7]], %[[VAL_8]],
-// CHECK: %[[VAL_11:.*]] = fir.box_addr %[[VAL_1]] : (!fir.box<!fir.array<?xf64>>) -> !fir.heap<!fir.array<?xf64>>
-// CHECK: fir.freemem %[[VAL_11]] : !fir.heap<!fir.array<?xf64>>
+// CHECK: %[[VAL_7:.*]] = arith.constant true
+// CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.box<!fir.array<?xf64>>>) -> !fir.ref<!fir.box<none>>
+// CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_1]] : (!fir.box<!fir.array<?xf64>>) -> !fir.box<none>
+// CHECK: %[[VAL_11:.*]] = fir.call @_FortranACopyOutAssign(%[[VAL_8]], %[[VAL_9]], %[[VAL_7]],
+// CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_1]] : (!fir.box<!fir.array<?xf64>>) -> !fir.box<none>
+// CHECK: %[[VAL_13:.*]] = fir.call @_FortranADestroyWithoutFinalization(%[[VAL_12]]) : (!fir.box<none>) -> none
+// CHECK: %[[VAL_14:.*]] = fir.box_addr %[[VAL_1]] : (!fir.box<!fir.array<?xf64>>) -> !fir.heap<!fir.array<?xf64>>
+// CHECK: fir.freemem %[[VAL_14]] : !fir.heap<!fir.array<?xf64>>
// CHECK: }
func.func @test_copy_in_poly(%poly : !fir.class<!fir.array<?x!fir.type<test_copy_in_polyTt1{i:i32}>>>) {
@@ -118,7 +123,7 @@ func.func @test_copy_in_poly(%poly : !fir.class<!fir.array<?x!fir.type<test_copy
// CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<test_copy_in_polyTt1{i:i32}>>>>>) -> !fir.ref<!fir.box<none>>
// CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_0]] : (!fir.class<!fir.array<?x!fir.type<test_copy_in_polyTt1{i:i32}>>>) -> !fir.box<none>
// CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_9]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
-// CHECK: %[[VAL_15:.*]] = fir.call @_FortranAAssign(%[[VAL_12]], %[[VAL_13]], %[[VAL_14]], %[[VAL_11]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
+// CHECK: %[[VAL_15:.*]] = fir.call @_FortranAAssignTemporary(%[[VAL_12]], %[[VAL_13]], %[[VAL_14]], %[[VAL_11]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
// CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<test_copy_in_polyTt1{i:i32}>>>>>
// CHECK: %[[VAL_17:.*]] = fir.rebox %[[VAL_16]] : (!fir.box<!fir.heap<!fir.array<?x!fir.type<test_copy_in_polyTt1{i:i32}>>>>) -> !fir.class<!fir.array<?x!fir.type<test_copy_in_polyTt1{i:i32}>>>
// CHECK: fir.result %[[VAL_17]] : !fir.class<!fir.array<?x!fir.type<test_copy_in_polyTt1{i:i32}>>>
diff --git a/flang/test/Lower/call-by-value-attr.f90 b/flang/test/Lower/call-by-value-attr.f90
index 1e4ca4cd03c39..33060e0e9401f 100644
--- a/flang/test/Lower/call-by-value-attr.f90
+++ b/flang/test/Lower/call-by-value-attr.f90
@@ -78,7 +78,7 @@ end subroutine subra
!CHECK: fir.store %[[TEMP_BOX]] to %[[TEMP_BOX_LOC:.*]] : !fir.ref<!fir.box<!fir.array<11xi32>>>
!CHECK: %[[TEMP_BOX_ADDR:.*]] = fir.convert %[[TEMP_BOX_LOC]] : (!fir.ref<!fir.box<!fir.array<11xi32>>>) -> !fir.ref<!fir.box<none>>
!CHECK: %[[BOX_ADDR:.*]] = fir.convert %[[BOX]] : (!fir.box<!fir.array<11xi32>>) -> !fir.box<none>
- !CHECK: fir.call @_FortranAAssign(%[[TEMP_BOX_ADDR]], %[[BOX_ADDR]], %{{.*}}, %{{.*}}){{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
+ !CHECK: fir.call @_FortranAAssignTemporary(%[[TEMP_BOX_ADDR]], %[[BOX_ADDR]], %{{.*}}, %{{.*}}){{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
!CHECK: fir.result %[[ARRAY_COPY_2]] : !fir.heap<!fir.array<11xi32>>
!CHECK: %[[CONVERT_B:.*]] = fir.convert %[[ADDR]] : (!fir.heap<!fir.array<11xi32>>) -> !fir.ref<!fir.array<10xi32>>
!CHECK: fir.call @_QPsubra(%[[CONVERT_B]])
diff --git a/flang/test/Lower/call-copy-in-out.f90 b/flang/test/Lower/call-copy-in-out.f90
index d6e21c73e3b7c..bcc2f81cf6bee 100644
--- a/flang/test/Lower/call-copy-in-out.f90
+++ b/flang/test/Lower/call-copy-in-out.f90
@@ -23,7 +23,7 @@ subroutine test_assumed_shape_to_array(x)
! CHECK-DAG: fir.store %[[temp_box]] to %[[temp_box_loc:.*]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
! CHECK-DAG: %[[temp_box_addr:.*]] = fir.convert %[[temp_box_loc]] : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.ref<!fir.box<none>>
! CHECK-DAG: %[[arg_box:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
-! CHECK-DAG: fir.call @_FortranAAssign(%[[temp_box_addr]], %[[arg_box]], %{{.*}}, %{{.*}}){{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
+! CHECK-DAG: fir.call @_FortranAAssignTemporary(%[[temp_box_addr]], %[[arg_box]], %{{.*}}, %{{.*}}){{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
! CHECK: fir.result %[[temp]] : !fir.heap<!fir.array<?xf32>>
! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
@@ -34,9 +34,10 @@ subroutine test_assumed_shape_to_array(x)
! CHECK-DAG: %[[shape:.*]] = fir.shape %[[dim]]#1 : (index) -> !fir.shape<1>
! CHECK-DAG: %[[temp_box:.*]] = fir.embox %[[addr]](%[[shape]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
! CHECK-DAG: fir.store %[[x]] to %[[arg_box_loc:.*]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
+! CHECK-DAG: %[[skipToInit:.*]] = arith.constant true
! CHECK-DAG: %[[arg_box_addr:.*]] = fir.convert %[[arg_box_loc]] : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.ref<!fir.box<none>>
! CHECK-DAG: %[[temp_box_cast:.*]] = fir.convert %[[temp_box]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
-! CHECK-DAG: fir.call @_FortranAAssign(%[[arg_box_addr]], %[[temp_box_cast]], %{{.*}}, %{{.*}}){{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
+! CHECK-DAG: fir.call @_FortranACopyOutAssign(%[[arg_box_addr]], %[[temp_box_cast]], %[[skipToInit]], %{{.*}}, %{{.*}}){{.*}}: (!fir.ref<!fir.box<none>>, !fir.box<none>, i1, !fir.ref<i8>, i32) -> none
! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xf32>>
call bar(x)
@@ -57,7 +58,7 @@ subroutine eval_expr_only_once(x)
! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>
! CHECK-NOT: fir.call @_QPonly_once()
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranAAssignTemporary
! CHECK-NOT: fir.call @_QPonly_once()
! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
@@ -65,7 +66,7 @@ subroutine eval_expr_only_once(x)
call bar(x(1:200:only_once()))
! CHECK-NOT: fir.call @_QPonly_once()
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK-NOT: fir.call @_QPonly_once()
! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xf32>>
@@ -77,10 +78,10 @@ subroutine eval_expr_only_once(x)
subroutine test_contiguous(x)
real, contiguous :: x(:)
! CHECK: %[[addr:.*]] = fir.box_addr %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
-! CHECK-NOT: fir.call @_FortranAAssign
+! CHECK-NOT: fir.call @_FortranAAssignTemporary
! CHECK: fir.call @_QPbar(%[[addr]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
call bar(x)
-! CHECK-NOT: fir.call @_FortranAAssign
+! CHECK-NOT: fir.call @_FortranACopyOutAssign
! CHECK: return
end subroutine
@@ -95,7 +96,7 @@ subroutine test_parenthesis(x)
! CHECK: %[[cast:.*]] = fir.convert %[[temp]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
! CHECK: fir.call @_QPbar(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
call bar((x))
-! CHECK-NOT: fir.call @_FortranAAssign
+! CHECK-NOT: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[temp]] : !fir.heap<!fir.array<?xf32>>
! CHECK: return
end subroutine
@@ -116,14 +117,14 @@ subroutine bar_intent_out(x)
! CHECK: } else {
! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1
-! CHECK-NOT: fir.call @_FortranAAssign
+! CHECK-NOT: fir.call @_FortranAAssignTemporary
! CHECK: %[[not_contiguous:.*]] = arith.cmpi eq, %[[is_contiguous]], %false{{.*}} : i1
! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
! CHECK: fir.call @_QPbar_intent_out(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
call bar_intent_out(x)
! CHECK: fir.if %[[not_contiguous]]
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xf32>>
! CHECK: return
end subroutine
@@ -148,13 +149,13 @@ subroutine bar_intent_in(x)
! CHECK: %[[temp_box:.*]] = fir.embox %[[temp]](%[[temp_shape]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
! CHECK: fir.store %[[temp_box]] to %[[temp_box_loc:.*]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
! CHECK: %[[temp_box_addr:.*]] = fir.convert %[[temp_box_loc]] : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: fir.call @_FortranAAssign(%[[temp_box_addr]],
+! CHECK: fir.call @_FortranAAssignTemporary(%[[temp_box_addr]],
! CHECK: %[[not_contiguous:.*]] = arith.cmpi eq, %[[is_contiguous]], %false{{.*}} : i1
! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
! CHECK: fir.call @_QPbar_intent_in(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
call bar_intent_in(x)
! CHECK: fir.if %[[not_contiguous]]
-! CHECK-NOT: fir.call @_FortranAAssign
+! CHECK-NOT: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xf32>>
! CHECK: return
end subroutine
@@ -181,7 +182,7 @@ subroutine bar_intent_inout(x)
! CHECK: fir.call @_QPbar_intent_inout(%[[cast]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
call bar_intent_inout(x)
! CHECK: fir.if %[[not_contiguous]]
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xf32>>
! CHECK: return
end subroutine
@@ -190,48 +191,43 @@ subroutine bar_intent_inout(x)
! CHECK-LABEL: func @_QPtest_char(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.char<1,10>>>{{.*}}) {
subroutine test_char(x)
- ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.array<?x!fir.char<1,10>>>
- ! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.array<?x!fir.char<1,10>>>
- ! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index
- ! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<none>
- ! CHECK: %[[VAL_5:.*]] = fir.call @_FortranAIsContiguous(%[[VAL_4]]) fastmath<contract> : (!fir.box<none>) -> i1
- ! CHECK: %[[VAL_6:.*]] = fir.if %[[VAL_5]] -> (!fir.heap<!fir.array<?x!fir.char<1,10>>>) {
- ! CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.heap<!fir.array<?x!fir.char<1,10>>>
- ! CHECK: fir.result %[[VAL_7]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
- ! CHECK: } else {
- ! CHECK: %[[VAL_8:.*]] = arith.constant 0 : index
- ! CHECK: %[[VAL_9:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_8]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>, index) -> (index, index, index)
- ! CHECK: %[[VAL_10:.*]] = fir.allocmem !fir.array<?x!fir.char<1,10>>, %[[VAL_9]]#1 {uniq_name = ".copyinout"}
- ! CHECK: %[[VAL_11:.*]] = fir.shape %[[VAL_9]]#1 : (index) -> !fir.shape<1>
- ! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_10]](%[[VAL_11]]) : (!fir.heap<!fir.array<?x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.box<!fir.array<?x!fir.char<1,10>>>
- ! CHECK: fir.store %[[VAL_12]] to %[[VAL_2]] : !fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>
- ! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,{{.*}}>>
- ! CHECK: %[[VAL_14:.*]] = arith.constant {{.*}} : i32
- ! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>) -> !fir.ref<!fir.box<none>>
- ! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<none>
- ! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_13]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
- ! CHECK: %[[VAL_18:.*]] = fir.call @_FortranAAssign(%[[VAL_15]], %[[VAL_16]], %[[VAL_17]], %[[VAL_14]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
- ! CHECK: fir.result %[[VAL_10]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
- ! CHECK: }
- ! CHECK: %[[VAL_19:.*]] = arith.constant 0 : index
- ! CHECK: %[[VAL_20:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_19]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>, index) -> (index, index, index)
- ! CHECK: %[[VAL_21:.*]] = arith.constant false
- ! CHECK: %[[VAL_22:.*]] = arith.cmpi eq, %[[VAL_5]], %[[VAL_21]] : i1
- ! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_24:.*]] : (!fir.heap<!fir.array<?x!fir.char<1,10>>>) -> !fir.ref<!fir.char<1,?>>
- ! CHECK: %[[VAL_25:.*]] = fir.emboxchar %[[VAL_23]], %[[VAL_3]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
- ! CHECK: fir.call @_QPbar_char(%[[VAL_25]]) fastmath<contract> : (!fir.boxchar<1>) -> ()
- ! CHECK: fir.if %[[VAL_22]] {
- ! CHECK: %[[VAL_26:.*]] = fir.shape %[[VAL_20]]#1 : (index) -> !fir.shape<1>
- ! CHECK: %[[VAL_27:.*]] = fir.embox %[[VAL_24]](%[[VAL_26]]) : (!fir.heap<!fir.array<?x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.box<!fir.array<?x!fir.char<1,10>>>
- ! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>
- ! CHECK: %[[VAL_28:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,{{.*}}>>
- ! CHECK: %[[VAL_29:.*]] = arith.constant {{.*}} : i32
- ! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_1]] : (!fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>) -> !fir.ref<!fir.box<none>>
- ! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_27]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<none>
- ! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_28]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
- ! CHECK: %[[VAL_33:.*]] = fir.call @_FortranAAssign(%[[VAL_30]], %[[VAL_31]], %[[VAL_32]], %[[VAL_29]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
- ! CHECK: fir.freemem %[[VAL_24]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
- ! CHECK: }
+! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.array<?x!fir.char<1,10>>>
+! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.array<?x!fir.char<1,10>>>
+! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<none>
+! CHECK: %[[VAL_5:.*]] = fir.call @_FortranAIsContiguous(%[[VAL_4]]) fastmath<contract> : (!fir.box<none>) -> i1
+! CHECK: %[[VAL_6:.*]] = fir.if %[[VAL_5]] -> (!fir.heap<!fir.array<?x!fir.char<1,10>>>) {
+! CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.heap<!fir.array<?x!fir.char<1,10>>>
+! CHECK: fir.result %[[VAL_7]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
+! CHECK: } else {
+! CHECK: %[[VAL_8:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_9:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_8]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>, index) -> (index, index, index)
+! CHECK: %[[VAL_10:.*]] = fir.allocmem !fir.array<?x!fir.char<1,10>>, %[[VAL_9]]#1 {uniq_name = ".copyinout"}
+! CHECK: %[[VAL_11:.*]] = fir.shape %[[VAL_9]]#1 : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_10]](%[[VAL_11]]) : (!fir.heap<!fir.array<?x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.box<!fir.array<?x!fir.char<1,10>>>
+! CHECK: fir.store %[[VAL_12]] to %[[VAL_2]] : !fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>
+! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<none>
+! CHECK: %[[VAL_18:.*]] = fir.call @_FortranAAssignTemporary(%[[VAL_15]], %[[VAL_16]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
+! CHECK: fir.result %[[VAL_10]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
+! CHECK: }
+! CHECK: %[[VAL_19:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_20:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_19]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>, index) -> (index, index, index)
+! CHECK: %[[VAL_21:.*]] = arith.constant false
+! CHECK: %[[VAL_22:.*]] = arith.cmpi eq, %[[VAL_5]], %[[VAL_21]] : i1
+! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_24:.*]] : (!fir.heap<!fir.array<?x!fir.char<1,10>>>) -> !fir.ref<!fir.char<1,?>>
+! CHECK: %[[VAL_25:.*]] = fir.emboxchar %[[VAL_23]], %[[VAL_3]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
+! CHECK: fir.call @_QPbar_char(%[[VAL_25]]) fastmath<contract> : (!fir.boxchar<1>) -> ()
+! CHECK: fir.if %[[VAL_22]] {
+! CHECK: %[[VAL_26:.*]] = fir.shape %[[VAL_20]]#1 : (index) -> !fir.shape<1>
+! CHECK: %[[VAL_27:.*]] = fir.embox %[[VAL_24]](%[[VAL_26]]) : (!fir.heap<!fir.array<?x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.box<!fir.array<?x!fir.char<1,10>>>
+! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>
+! CHECK: %[[VAL_30:.*]] = arith.constant true
+! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_1]] : (!fir.ref<!fir.box<!fir.array<?x!fir.char<1,10>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_27]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<none>
+! CHECK: %[[VAL_34:.*]] = fir.call @_FortranACopyOutAssign(%[[VAL_31]], %[[VAL_32]], %[[VAL_30]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, i1, !fir.ref<i8>, i32) -> none
+! CHECK: fir.freemem %[[VAL_24]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
+! CHECK: }
character(10) :: x(:)
call bar_char(x)
diff --git a/flang/test/Lower/dummy-argument-assumed-shape-optional.f90 b/flang/test/Lower/dummy-argument-assumed-shape-optional.f90
index 01f774f1713f1..6a5a830fb67a5 100644
--- a/flang/test/Lower/dummy-argument-assumed-shape-optional.f90
+++ b/flang/test/Lower/dummy-argument-assumed-shape-optional.f90
@@ -40,7 +40,7 @@ subroutine test_assumed_shape_to_contiguous(x)
! CHECK: %[[VAL_25:.*]] = fir.embox %[[VAL_3]](%[[VAL_24]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
! CHECK: fir.call @_QPtakes_contiguous(%[[VAL_25]]) {{.*}}: (!fir.box<!fir.array<?xf32>>) -> ()
! CHECK: fir.if %[[VAL_23]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_3]] : !fir.heap<!fir.array<?xf32>>
! CHECK: }
! CHECK: return
@@ -85,7 +85,7 @@ subroutine test_assumed_shape_opt_to_contiguous(x)
! CHECK: %[[VAL_25:.*]] = fir.embox %[[VAL_3]](%[[VAL_24]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
! CHECK: fir.call @_QPtakes_contiguous(%[[VAL_25]]) {{.*}}: (!fir.box<!fir.array<?xf32>>) -> ()
! CHECK: fir.if %[[VAL_23]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_3]] : !fir.heap<!fir.array<?xf32>>
! CHECK: }
! CHECK: return
@@ -131,7 +131,7 @@ subroutine test_assumed_shape_to_contiguous_opt(x)
! CHECK: %[[VAL_25:.*]] = fir.embox %[[VAL_3]](%[[VAL_24]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
! CHECK: fir.call @_QPtakes_contiguous_optional(%[[VAL_25]]) {{.*}}: (!fir.box<!fir.array<?xf32>>) -> ()
! CHECK: fir.if %[[VAL_23]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_3]] : !fir.heap<!fir.array<?xf32>>
! CHECK: }
! CHECK: return
@@ -191,7 +191,7 @@ subroutine test_assumed_shape_opt_to_contiguous_opt(x)
! CHECK: %[[VAL_38:.*]] = arith.select %[[VAL_1]], %[[VAL_35]], %[[VAL_37]] : !fir.box<!fir.array<?xf32>>
! CHECK: fir.call @_QPtakes_contiguous_optional(%[[VAL_38]]) {{.*}}: (!fir.box<!fir.array<?xf32>>) -> ()
! CHECK: fir.if %[[VAL_33]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_9]] : !fir.heap<!fir.array<?xf32>>
! CHECK: }
! CHECK: return
@@ -254,7 +254,7 @@ subroutine test_pointer_to_contiguous_opt(x)
! CHECK: %[[VAL_41:.*]] = arith.select %[[VAL_5]], %[[VAL_38]], %[[VAL_40]] : !fir.box<!fir.array<?xf32>>
! CHECK: fir.call @_QPtakes_contiguous_optional(%[[VAL_41]]) {{.*}}: (!fir.box<!fir.array<?xf32>>) -> ()
! CHECK: fir.if %[[VAL_36]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_11]] : !fir.heap<!fir.array<?xf32>>
! CHECK: }
! CHECK: return
@@ -323,7 +323,7 @@ subroutine test_pointer_opt_to_contiguous_opt(x)
! CHECK: %[[VAL_41:.*]] = arith.select %[[VAL_5]], %[[VAL_38]], %[[VAL_40]] : !fir.box<!fir.array<?xf32>>
! CHECK: fir.call @_QPtakes_contiguous_optional(%[[VAL_41]]) {{.*}}: (!fir.box<!fir.array<?xf32>>) -> ()
! CHECK: fir.if %[[VAL_36]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_11]] : !fir.heap<!fir.array<?xf32>>
! CHECK: }
! CHECK: return
diff --git a/flang/test/Lower/dummy-argument-optional-2.f90 b/flang/test/Lower/dummy-argument-optional-2.f90
index ab43fd9167797..82b7e612c924e 100644
--- a/flang/test/Lower/dummy-argument-optional-2.f90
+++ b/flang/test/Lower/dummy-argument-optional-2.f90
@@ -111,7 +111,7 @@ subroutine pass_pointer_array(i)
! CHECK: %[[VAL_10:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_11:.*]]:3 = fir.box_dims %[[box]], %[[VAL_10]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
! CHECK: %[[VAL_12:.*]] = fir.allocmem !fir.array<?xf32>, %[[VAL_11]]#1 {uniq_name = ".copyinout"}
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranAAssignTemporary
! CHECK: fir.result %[[VAL_12]] : !fir.heap<!fir.array<?xf32>>
! CHECK: } else {
! CHECK: %[[VAL_26:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
@@ -122,7 +122,7 @@ subroutine pass_pointer_array(i)
! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_9]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
! CHECK: fir.call @_QPtakes_opt_explicit_shape(%[[VAL_29]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
! CHECK: fir.if %[[and]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_9]] : !fir.heap<!fir.array<?xf32>>
! CHECK: }
end subroutine
@@ -145,7 +145,7 @@ subroutine pass_pointer_array_char(c)
! CHECK: %[[VAL_11:.*]]:3 = fir.box_dims %[[VAL_6]], %[[VAL_10]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>, index) -> (index, index, index)
! CHECK: %[[VAL_12:.*]] = fir.box_elesize %[[VAL_6]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>) -> index
! CHECK: %[[VAL_13:.*]] = fir.allocmem !fir.array<?x!fir.char<1,?>>(%[[VAL_12]] : index), %[[VAL_11]]#1 {uniq_name = ".copyinout"}
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranAAssignTemporary
! CHECK: fir.result %[[VAL_13]] : !fir.heap<!fir.array<?x!fir.char<1,?>>>
! CHECK: } else {
! CHECK: %[[VAL_46:.*]] = fir.zero_bits !fir.heap<!fir.array<?x!fir.char<1,?>>>
@@ -158,7 +158,7 @@ subroutine pass_pointer_array_char(c)
! CHECK: %[[VAL_52:.*]] = fir.emboxchar %[[VAL_50]], %[[VAL_47]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
! CHECK: fir.call @_QPtakes_opt_explicit_shape_char(%[[VAL_52]]) {{.*}}: (!fir.boxchar<1>) -> ()
! CHECK: fir.if %[[and]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_9]] : !fir.heap<!fir.array<?x!fir.char<1,?>>>
! CHECK: }
! CHECK: return
@@ -182,7 +182,7 @@ subroutine forward_pointer_array()
! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%{{.*}}) {{.*}}: (!fir.box<none>) -> i1
! CHECK: %[[VAL_7:.*]] = fir.if %[[VAL_6]] -> (!fir.heap<!fir.array<?xf32>>) {
! CHECK: %[[VAL_10:.*]] = fir.allocmem !fir.array<?xf32>
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranAAssignTemporary
! CHECK: fir.result %[[VAL_10]] : !fir.heap<!fir.array<?xf32>>
! CHECK: } else {
! CHECK: %[[VAL_11:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
@@ -193,7 +193,7 @@ subroutine forward_pointer_array()
! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_7]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
! CHECK: fir.call @_QPtakes_opt_explicit_shape(%[[VAL_14]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
! CHECK: fir.if %[[and]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_7]] : !fir.heap<!fir.array<?xf32>>
! CHECK: }
end subroutine
@@ -221,7 +221,7 @@ subroutine pass_opt_assumed_shape(x)
! CHECK: %[[VAL_8:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_9:.*]]:3 = fir.box_dims %[[VAL_6]], %[[VAL_8]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
! CHECK: %[[VAL_10:.*]] = fir.allocmem !fir.array<?xf32>, %[[VAL_9]]#1 {uniq_name = ".copyinout"}
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranAAssignTemporary
! CHECK: fir.result %[[VAL_10]] : !fir.heap<!fir.array<?xf32>>
! CHECK: } else {
! CHECK: %[[VAL_23:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
@@ -232,7 +232,7 @@ subroutine pass_opt_assumed_shape(x)
! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_27:.*]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
! CHECK: fir.call @_QPtakes_opt_explicit_shape(%[[VAL_26]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
! CHECK: fir.if %[[and]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_27]] : !fir.heap<!fir.array<?xf32>>
! CHECK: }
end subroutine
@@ -258,7 +258,7 @@ subroutine pass_opt_assumed_shape_char(c)
! CHECK: } else {
! CHECK: %[[box_elesize:.*]] = fir.box_elesize %[[VAL_7]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> index
! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?x!fir.char<1,?>>(%[[box_elesize]] : index), %{{.*}}#1 {uniq_name = ".copyinout"}
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranAAssignTemporary
! CHECK: fir.result %[[VAL_12]] : !fir.heap<!fir.array<?x!fir.char<1,?>>>
! CHECK: } else {
! CHECK: %[[VAL_44:.*]] = fir.zero_bits !fir.heap<!fir.array<?x!fir.char<1,?>>>
@@ -271,7 +271,7 @@ subroutine pass_opt_assumed_shape_char(c)
! CHECK: %[[VAL_50:.*]] = fir.emboxchar %[[VAL_48]], %[[VAL_45]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
! CHECK: fir.call @_QPtakes_opt_explicit_shape_char(%[[VAL_50]]) {{.*}}: (!fir.boxchar<1>) -> ()
! CHECK: fir.if %[[and]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_49]] : !fir.heap<!fir.array<?x!fir.char<1,?>>>
! CHECK: }
end subroutine
@@ -394,7 +394,7 @@ subroutine pass_opt_assumed_shape_to_intentin(x)
! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
! CHECK: %[[VAL_7:.*]] = fir.if %[[VAL_1]] -> (!fir.heap<!fir.array<?xf32>>) {
! CHECK: %[[VAL_10:.*]] = fir.allocmem !fir.array<?xf32>
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranAAssignTemporary
! CHECK: fir.result %[[VAL_10]] : !fir.heap<!fir.array<?xf32>>
! CHECK: } else {
! CHECK: %[[VAL_23:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
@@ -405,7 +405,7 @@ subroutine pass_opt_assumed_shape_to_intentin(x)
! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_7]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
! CHECK: fir.call @_QPtakes_opt_explicit_shape_intentin(%[[VAL_24]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
! CHECK: fir.if %[[and]] {
-! CHECK-NOT: fir.call @_FortranAAssign
+! CHECK-NOT: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_7]] : !fir.heap<!fir.array<?xf32>>
! CHECK: }
end subroutine
@@ -425,7 +425,7 @@ subroutine pass_opt_assumed_shape_to_intentout(x)
! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) {{.*}}: (!fir.box<none>) -> i1
! CHECK: %[[VAL_7:.*]] = fir.if %[[VAL_1]] -> (!fir.heap<!fir.array<?xf32>>) {
! CHECK: %[[VAL_10:.*]] = fir.allocmem !fir.array<?xf32>
-! CHECK-NOT: fir.call @_FortranAAssign
+! CHECK-NOT: fir.call @_FortranAAssignTemporary
! CHECK: fir.result %[[VAL_10]] : !fir.heap<!fir.array<?xf32>>
! CHECK: } else {
! CHECK: %[[VAL_11:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
@@ -436,7 +436,7 @@ subroutine pass_opt_assumed_shape_to_intentout(x)
! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_7]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
! CHECK: fir.call @_QPtakes_opt_explicit_shape_intentout(%[[VAL_14]]) {{.*}}: (!fir.ref<!fir.array<100xf32>>) -> ()
! CHECK: fir.if %[[and]] {
-! CHECK: fir.call @_FortranAAssign
+! CHECK: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_7]] : !fir.heap<!fir.array<?xf32>>
! CHECK: }
end subroutine
diff --git a/flang/test/Lower/optional-value-caller.f90 b/flang/test/Lower/optional-value-caller.f90
index b4df3415b7825..6c68e0dce5ed5 100644
--- a/flang/test/Lower/optional-value-caller.f90
+++ b/flang/test/Lower/optional-value-caller.f90
@@ -298,7 +298,7 @@ subroutine test_dyn_array_from_assumed(i, n)
! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_8]] : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
! CHECK: fir.call @_QPdyn_array(%[[VAL_25]], %[[VAL_1]]) {{.*}}: (!fir.ref<!fir.array<?xi32>>, !fir.ref<i64>) -> ()
! CHECK: fir.if %[[and]] {
-! CHECK-NOT: fir.call @_FortranAAssign
+! CHECK-NOT: fir.call @_FortranACopyOutAssign
! CHECK: fir.freemem %[[VAL_8]] : !fir.heap<!fir.array<?xi32>>
! CHECK: }
end subroutine
@@ -333,7 +333,7 @@ subroutine test_array_ptr(i)
! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_1]] : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<none>>
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>) -> !fir.box<none>
! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_18]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
-! CHECK: %[[VAL_23:.*]] = fir.call @_FortranAAssign(%[[VAL_20]], %[[VAL_21]], %[[VAL_22]], %[[VAL_19]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
+! CHECK: %[[VAL_23:.*]] = fir.call @_FortranAAssignTemporary(%[[VAL_20]], %[[VAL_21]], %[[VAL_22]], %[[VAL_19]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
! CHECK: fir.result %[[VAL_15]] : !fir.heap<!fir.array<?xi32>>
! CHECK: }
! CHECK: fir.result %[[VAL_24:.*]] : !fir.heap<!fir.array<?xi32>>
@@ -439,7 +439,7 @@ subroutine test_char_array(c)
! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_1]] : (!fir.ref<!fir.box<!fir.array<?x!fir.char<1,?>>>>) -> !fir.ref<!fir.box<none>>
! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> !fir.box<none>
! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_21]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
-! CHECK: %[[VAL_26:.*]] = fir.call @_FortranAAssign(%[[VAL_23]], %[[VAL_24]], %[[VAL_25]], %[[VAL_22]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
+! CHECK: %[[VAL_26:.*]] = fir.call @_FortranAAssignTemporary(%[[VAL_23]], %[[VAL_24]], %[[VAL_25]], %[[VAL_22]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none
! CHECK: fir.result %[[VAL_18]] : !fir.heap<!fir.array<?x!fir.char<1,?>>>
! CHECK: }
! CHECK: fir.result %[[VAL_27:.*]] : !fir.heap<!fir.array<?x!fir.char<1,?>>>
More information about the flang-commits
mailing list