@@ -791,26 +791,35 @@ struct ElementalOpConversion
791791 // Assign the element value to the temp element for this iteration.
792792 auto tempElement =
793793 hlfir::getElementAt (loc, builder, temp, loopNest.oneBasedIndices );
794- // FIXME: if the elemental result is a function result temporary
795- // of a derived type, we have to make sure that we are either
796- // deallocate any allocatable/automatic components after the assignment
797- // or that we do not do the deep copy with the AssignOp. The latter
798- // seems to be preferrable, because the deep copy is more expensive.
799- // The shallow copy may be done with a load/store of the RecordType scalar.
800- builder.create <hlfir::AssignOp>(loc, elementValue, tempElement,
801- /* realloc=*/ false ,
802- /* keep_lhs_length_if_realloc=*/ false ,
803- /* temporary_lhs=*/ true );
804- // hlfir.yield_element implicitly marks the end-of-life its operand if
805- // it is an expression created in the hlfir.elemental (since it is its
806- // last use and an hlfir.destroy could not be created afterwards)
807- // Now that this node has been removed and the expression has been used in
808- // the assign, insert an hlfir.destroy to mark the expression end-of-life.
809- // If the expression creation allocated a buffer on the heap inside the
810- // loop, this will ensure the buffer properly deallocated.
811- if (elementValue.getType ().isa <hlfir::ExprType>() &&
812- wasCreatedInCurrentBlock (elementValue, builder))
813- builder.create <hlfir::DestroyOp>(loc, elementValue);
794+ // If the elemental result is a temporary of a derived type,
795+ // we can avoid the deep copy implied by the AssignOp and just
796+ // do the shallow copy with load/store. This helps avoiding the overhead
797+ // of deallocating allocatable components of the temporary (if any)
798+ // on each iteration of the elemental operation.
799+ auto asExpr = elementValue.getDefiningOp <hlfir::AsExprOp>();
800+ auto elemType = hlfir::getFortranElementType (elementValue.getType ());
801+ if (asExpr && asExpr.isMove () && mlir::isa<fir::RecordType>(elemType) &&
802+ hlfir::mayHaveAllocatableComponent (elemType) &&
803+ wasCreatedInCurrentBlock (elementValue, builder)) {
804+ auto load = builder.create <fir::LoadOp>(loc, asExpr.getVar ());
805+ builder.create <fir::StoreOp>(loc, load, tempElement);
806+ } else {
807+ builder.create <hlfir::AssignOp>(loc, elementValue, tempElement,
808+ /* realloc=*/ false ,
809+ /* keep_lhs_length_if_realloc=*/ false ,
810+ /* temporary_lhs=*/ true );
811+
812+ // hlfir.yield_element implicitly marks the end-of-life its operand if
813+ // it is an expression created in the hlfir.elemental (since it is its
814+ // last use and an hlfir.destroy could not be created afterwards)
815+ // Now that this node has been removed and the expression has been used in
816+ // the assign, insert an hlfir.destroy to mark the expression end-of-life.
817+ // If the expression creation allocated a buffer on the heap inside the
818+ // loop, this will ensure the buffer properly deallocated.
819+ if (elementValue.getType ().isa <hlfir::ExprType>() &&
820+ wasCreatedInCurrentBlock (elementValue, builder))
821+ builder.create <hlfir::DestroyOp>(loc, elementValue);
822+ }
814823 builder.restoreInsertionPoint (insPt);
815824
816825 mlir::Value bufferizedExpr =
0 commit comments