diff options
author | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2020-05-09 22:44:39 +0200 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2020-05-09 22:44:39 +0200 |
commit | 527ed00b715bf4a945284722b7e766a4f763049f (patch) | |
tree | d0aa44f1dfd8f91695a2eeb9bbd65a4ae69444b5 /gcc/ada/gcc-interface | |
parent | aff220748ca669d4338c5ac6f0b210a29f90bbab (diff) | |
download | gcc-527ed00b715bf4a945284722b7e766a4f763049f.zip gcc-527ed00b715bf4a945284722b7e766a4f763049f.tar.gz gcc-527ed00b715bf4a945284722b7e766a4f763049f.tar.bz2 |
Do not make a local copy of large aggregate
This prevents gigi from making a local copy of large aggregates.
* gcc-interface/trans.c (lvalue_required_p) <N_Selected_Component>:
Merge with N_Slice.
<N_Allocator>: Move to...
(lvalue_for_aggregate_p): ...here. New function.
(Identifier_to_gnu): For an identifier with aggregate type, also
call lvalue_for_aggregate_p if lvalue_required_p returned false
before substituting the identifier with the constant.
Diffstat (limited to 'gcc/ada/gcc-interface')
-rw-r--r-- | gcc/ada/gcc-interface/trans.c | 86 |
1 files changed, 73 insertions, 13 deletions
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 44b156a..a2f06d7 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -871,8 +871,9 @@ lvalue_required_p (Node_Id gnat_node, tree gnu_type, bool constant, /* ... fall through ... */ + case N_Selected_Component: case N_Slice: - /* Only the array expression can require an lvalue. */ + /* Only the prefix expression can require an lvalue. */ if (Prefix (gnat_parent) != gnat_node) return 0; @@ -880,11 +881,6 @@ lvalue_required_p (Node_Id gnat_node, tree gnu_type, bool constant, get_unpadded_type (Etype (gnat_parent)), constant, address_of_constant); - case N_Selected_Component: - return lvalue_required_p (gnat_parent, - get_unpadded_type (Etype (gnat_parent)), - constant, address_of_constant); - case N_Object_Renaming_Declaration: /* We need to preserve addresses through a renaming. */ return 1; @@ -925,12 +921,6 @@ lvalue_required_p (Node_Id gnat_node, tree gnu_type, bool constant, get_unpadded_type (Etype (gnat_parent)), constant, address_of_constant); - case N_Allocator: - /* We should only reach here through the N_Qualified_Expression case. - Force an lvalue for composite types since a block-copy to the newly - allocated area of memory is made. */ - return Is_Composite_Type (Underlying_Type (Etype (gnat_node))); - case N_Explicit_Dereference: /* We look through dereferences for address of constant because we need to handle the special cases listed above. */ @@ -948,6 +938,74 @@ lvalue_required_p (Node_Id gnat_node, tree gnu_type, bool constant, gcc_unreachable (); } +/* Return true if an lvalue should be used for GNAT_NODE. GNU_TYPE is the type + that will be used for GNAT_NODE in the translated GNU tree and is assumed to + be an aggregate type. + + The function climbs up the GNAT tree starting from the node and returns true + upon encountering a node that makes it doable to decide. lvalue_required_p + should have been previously invoked on the arguments and returned false. */ + +static bool +lvalue_for_aggregate_p (Node_Id gnat_node, tree gnu_type) +{ + Node_Id gnat_parent = Parent (gnat_node); + + switch (Nkind (gnat_parent)) + { + case N_Parameter_Association: + case N_Function_Call: + case N_Procedure_Call_Statement: + /* Even if the parameter is by copy, prefer an lvalue. */ + return true; + + case N_Indexed_Component: + case N_Selected_Component: + /* If an elementary component is used, take it from the constant. */ + if (!Is_Composite_Type (Underlying_Type (Etype (gnat_parent)))) + return false; + + /* ... fall through ... */ + + case N_Slice: + return lvalue_for_aggregate_p (gnat_parent, + get_unpadded_type (Etype (gnat_parent))); + + case N_Object_Declaration: + /* For an aggregate object declaration, return the constant at top level + in order to avoid generating elaboration code. */ + if (global_bindings_p ()) + return false; + + /* ... fall through ... */ + + case N_Assignment_Statement: + /* For an aggregate assignment, decide based on the size. */ + { + const HOST_WIDE_INT size = int_size_in_bytes (gnu_type); + return size < 0 || size >= param_large_stack_frame / 4; + } + + case N_Unchecked_Type_Conversion: + case N_Type_Conversion: + case N_Qualified_Expression: + return lvalue_for_aggregate_p (gnat_parent, + get_unpadded_type (Etype (gnat_parent))); + + case N_Allocator: + /* We should only reach here through the N_Qualified_Expression case. + Force an lvalue for aggregate types since a block-copy to the newly + allocated area of memory is made. */ + return true; + + default: + return false; + } + + gcc_unreachable (); +} + + /* Return true if T is a constant DECL node that can be safely replaced by its initializer. */ @@ -1232,7 +1290,9 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p) if ((!constant_only || address_of_constant) && require_lvalue < 0) require_lvalue = lvalue_required_p (gnat_node, gnu_result_type, true, - address_of_constant); + address_of_constant) + || (AGGREGATE_TYPE_P (gnu_result_type) + && lvalue_for_aggregate_p (gnat_node, gnu_result_type)); /* Finally retrieve the initializer if this is deemed valid. */ if ((constant_only && !address_of_constant) || !require_lvalue) |