This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Ada] Improve allocation of constants with discriminated types
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 2 Apr 2008 12:08:24 +0200
- Subject: [Ada] Improve allocation of constants with discriminated types
As demonstrated by the following testcase, the allocation of constants with
discriminated types in Gigi is suboptimal. For
type T (Big : Boolean := False) is record
case Big is
when True =>
Content : Integer;
when False =>
null;
end case;
end record;
D : constant T := (True, 0);
Var : T := D;
Con : constant T := D;
D is allocated statically with exact size, Var is allocated statically with
maximum size, but Con is allocated dynamically (with exact size).
We can do better by propagating the size of D thanks to its constantness.
Tested on i586-suse-linux, applied on the mainline
2008-04-02 Eric Botcazou <ebotcazou@adacore.com>
* decl.c (gnat_to_gnu_entity) <object>: For a constant object whose
type has self-referential size, get the size from the initializing
expression directly if it is also a constant whose nominal type
has self-referential size.
2008-04-02 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/specs/discr_record_constant.ads: New test.
--
Eric Botcazou
Index: decl.c
===================================================================
--- decl.c (revision 133768)
+++ decl.c (working copy)
@@ -607,15 +607,34 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
initializing expression, in which case we can get the size from
that. Note that the resulting size may still be a variable, so
this may end up with an indirect allocation. */
-
if (No (Renamed_Object (gnat_entity))
&& CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type)))
{
if (gnu_expr && kind == E_Constant)
- gnu_size
- = SUBSTITUTE_PLACEHOLDER_IN_EXPR
- (TYPE_SIZE (TREE_TYPE (gnu_expr)), gnu_expr);
-
+ {
+ tree size = TYPE_SIZE (TREE_TYPE (gnu_expr));
+ if (CONTAINS_PLACEHOLDER_P (size))
+ {
+ /* If the initializing expression is itself a constant,
+ despite having a nominal type with self-referential
+ size, we can get the size directly from it. */
+ if (TREE_CODE (gnu_expr) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (gnu_expr, 0)))
+ == RECORD_TYPE
+ && TYPE_IS_PADDING_P
+ (TREE_TYPE (TREE_OPERAND (gnu_expr, 0)))
+ && TREE_CODE (TREE_OPERAND (gnu_expr, 0)) == VAR_DECL
+ && (TREE_READONLY (TREE_OPERAND (gnu_expr, 0))
+ || DECL_READONLY_ONCE_ELAB
+ (TREE_OPERAND (gnu_expr, 0))))
+ gnu_size = DECL_SIZE (TREE_OPERAND (gnu_expr, 0));
+ else
+ gnu_size
+ = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, gnu_expr);
+ }
+ else
+ gnu_size = size;
+ }
/* We may have no GNU_EXPR because No_Initialization is
set even though there's an Expression. */
else if (kind == E_Constant
-- { dg-do compile }
pragma Restrictions (No_Implicit_Heap_Allocations);
package Discr_Record_Constant is
type T (Big : Boolean := False) is record
case Big is
when True =>
Content : Integer;
when False =>
null;
end case;
end record;
D : constant T := (True, 0);
Var : T := D; -- OK, maximum size
Con : constant T := D; -- Violation of restriction
Ter : constant T := Con; -- Violation of restriction
end Discr_Record_Constant;