mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-01-12 00:05:41 +08:00
ada: Fix suboptimal copy of discriminated record to local variable
This happens for a discriminated record type with default discriminants, for which GNAT allocates mutable objects with the maximum size, while trying not to copy padding bits unnecessarily. When the padded size is small enough to be copied efficiently, it should nevertheless be profitable to copy them in order to avoid a call to memcpy with a dynamic size. gcc/ada/ChangeLog: * gcc-interface/trans.cc (gnat_to_gnu): For the LHS of an assignment or an actual parameter of a call, do not remove the padding even for a type of self-referential size when the padded size is small enough to be copied efficiently.
This commit is contained in:
committed by
Marc Poulhiès
parent
4e1468b9ff
commit
571f250c66
@@ -8903,17 +8903,21 @@ gnat_to_gnu (Node_Id gnat_node)
|
||||
&& !(TREE_CODE (gnu_result_type) == RECORD_TYPE
|
||||
&& TYPE_JUSTIFIED_MODULAR_P (gnu_result_type))))
|
||||
{
|
||||
/* Remove padding only if the inner object is of self-referential
|
||||
size: in that case it must be an object of unconstrained type
|
||||
with a default discriminant and we want to avoid copying too
|
||||
much data. But do not remove it if it is already too small. */
|
||||
if (type_is_padding_self_referential (TREE_TYPE (gnu_result))
|
||||
tree t = TREE_TYPE (gnu_result);
|
||||
|
||||
/* Remove the padding only if the inner object is of self-referential
|
||||
size: in that case, it must be an object of an unconstrained type
|
||||
with default discriminants and we want to avoid copying too much
|
||||
data. But we would nevertheless rather copy up to MOVE_MAX_PIECES
|
||||
bytes than invoke memcpy for such a small amount of data. In any
|
||||
case, do not remove the padding if it is already too small. */
|
||||
if (type_is_padding_self_referential (t)
|
||||
&& (TREE_CODE (TYPE_SIZE_UNIT (t)) != INTEGER_CST
|
||||
|| compare_tree_int (TYPE_SIZE_UNIT (t), MOVE_MAX_PIECES) > 0)
|
||||
&& !(TREE_CODE (gnu_result) == COMPONENT_REF
|
||||
&& DECL_BIT_FIELD (TREE_OPERAND (gnu_result, 1))
|
||||
&& DECL_SIZE (TREE_OPERAND (gnu_result, 1))
|
||||
!= TYPE_SIZE (TREE_TYPE (gnu_result))))
|
||||
gnu_result = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_result))),
|
||||
gnu_result);
|
||||
&& DECL_SIZE (TREE_OPERAND (gnu_result, 1)) != TYPE_SIZE (t)))
|
||||
gnu_result = convert (TREE_TYPE (TYPE_FIELDS (t)), gnu_result);
|
||||
}
|
||||
|
||||
else if (TREE_CODE (gnu_result) == LABEL_DECL
|
||||
|
||||
Reference in New Issue
Block a user