This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Create RECORD_NODE for COMMON blocks contain no EQUIVALENCE objects
- From: Canqun Yang <canqun at nudt dot edu dot cn>
- To: fortran at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Thu, 24 Mar 2005 22:39:10 +0800 (HKT)
- Subject: Re: Create RECORD_NODE for COMMON blocks contain no EQUIVALENCE objects
- Reply-to: Canqun Yang <canqun at nudt dot edu dot cn>
Hi, all
If the common block contains no equivalence objects,
then make a RECORD_TYPE node, otherwise UNION_TYPE.
This will let the alias analyzer work well when there
is no address overlapping for common variables in the
current common block.
This patch may improve performance for Fortran
programs which contain COMMON blocks. For example, the
SPEC CFP2000 benchmark 171.swim just spend 20 seconds
to execute in train mode, but 29 seconds without this
patch.
Tested on IA-64.
2005-03-24 Canqun Yang <canqun@nudt.edu.cn>
* trans-common.c (saw_equiv): New static
variable.
(create_common): Build RECORD_NODE for common
blocks contain no
equivalence objects.
(add_equivalences): Set saw_equiv when needed.
(translate_common): Initialize saw_equiv.
(create_common, build_field,
build_equiv_decl, build_common_decl):
change 'union_node' to 'node_type'.
Canqun Yang
Creative Compiler Research Group.
National University of Defense Technology, China.
*** trans-common.c.save Thu Mar 24 21:30:24 2005
--- trans-common.c Thu Mar 24 21:45:29 2005
*************** typedef struct segment_info
*** 119,124 ****
--- 119,127 ----
static segment_info * current_segment;
static gfc_namespace *gfc_common_ns = NULL;
+ /* Whether the current common block contains equivalence object or not. */
+ static bool saw_equiv;
+
#define BLANK_COMMON_NAME "__BLNK__"
/* Make a segment_info based on a symbol. */
*************** gfc_sym_mangled_common_id (const char *
*** 215,221 ****
object. */
static void
! build_field (segment_info *h, tree union_type, record_layout_info rli)
{
tree field;
tree name;
--- 218,224 ----
object. */
static void
! build_field (segment_info *h, tree node_type, record_layout_info rli)
{
tree field;
tree name;
*************** build_field (segment_info *h, tree union
*** 233,239 ****
if (desired_align > known_align)
DECL_PACKED (field) = 1;
! DECL_FIELD_CONTEXT (field) = union_type;
DECL_FIELD_OFFSET (field) = size_int (offset);
DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
SET_DECL_OFFSET_ALIGN (field, known_align);
--- 236,242 ----
if (desired_align > known_align)
DECL_PACKED (field) = 1;
! DECL_FIELD_CONTEXT (field) = node_type;
DECL_FIELD_OFFSET (field) = size_int (offset);
DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
SET_DECL_OFFSET_ALIGN (field, known_align);
*************** build_field (segment_info *h, tree union
*** 270,276 ****
/* Get storage for local equivalence. */
static tree
! build_equiv_decl (tree union_type, bool is_init)
{
tree decl;
char name[15];
--- 273,279 ----
/* Get storage for local equivalence. */
static tree
! build_equiv_decl (tree node_type, bool is_init)
{
tree decl;
char name[15];
*************** build_equiv_decl (tree union_type, bool
*** 278,290 ****
if (is_init)
{
! decl = gfc_create_var (union_type, "equiv");
TREE_STATIC (decl) = 1;
return decl;
}
snprintf (name, sizeof (name), "equiv.%d", serial++);
! decl = build_decl (VAR_DECL, get_identifier (name), union_type);
DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 1;
--- 281,293 ----
if (is_init)
{
! decl = gfc_create_var (node_type, "equiv");
TREE_STATIC (decl) = 1;
return decl;
}
snprintf (name, sizeof (name), "equiv.%d", serial++);
! decl = build_decl (VAR_DECL, get_identifier (name), node_type);
DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 1;
*************** build_equiv_decl (tree union_type, bool
*** 307,313 ****
/* Get storage for common block. */
static tree
! build_common_decl (gfc_common_head *com, tree union_type, bool is_init)
{
gfc_symbol *common_sym;
tree decl;
--- 310,316 ----
/* Get storage for common block. */
static tree
! build_common_decl (gfc_common_head *com, tree node_type, bool is_init)
{
gfc_symbol *common_sym;
tree decl;
*************** build_common_decl (gfc_common_head *com,
*** 322,328 ****
/* Update the size of this common block as needed. */
if (decl != NULL_TREE)
{
! tree size = TYPE_SIZE_UNIT (union_type);
if (tree_int_cst_lt (DECL_SIZE_UNIT (decl), size))
{
/* Named common blocks of the same name shall be of the same size
--- 325,331 ----
/* Update the size of this common block as needed. */
if (decl != NULL_TREE)
{
! tree size = TYPE_SIZE_UNIT (node_type);
if (tree_int_cst_lt (DECL_SIZE_UNIT (decl), size))
{
/* Named common blocks of the same name shall be of the same size
*************** build_common_decl (gfc_common_head *com,
*** 344,350 ****
/* If there is no backend_decl for the common block, build it. */
if (decl == NULL_TREE)
{
! decl = build_decl (VAR_DECL, get_identifier (com->name), union_type);
SET_DECL_ASSEMBLER_NAME (decl, gfc_sym_mangled_common_id (com->name));
TREE_PUBLIC (decl) = 1;
TREE_STATIC (decl) = 1;
--- 347,353 ----
/* If there is no backend_decl for the common block, build it. */
if (decl == NULL_TREE)
{
! decl = build_decl (VAR_DECL, get_identifier (com->name), node_type);
SET_DECL_ASSEMBLER_NAME (decl, gfc_sym_mangled_common_id (com->name));
TREE_PUBLIC (decl) = 1;
TREE_STATIC (decl) = 1;
*************** static void
*** 382,401 ****
create_common (gfc_common_head *com, segment_info * head)
{
segment_info *s, *next_s;
! tree union_type;
tree *field_link;
record_layout_info rli;
tree decl;
bool is_init = false;
! /* Declare the variables inside the common block. */
! union_type = make_node (UNION_TYPE);
! rli = start_record_layout (union_type);
! field_link = &TYPE_FIELDS (union_type);
for (s = head; s; s = s->next)
{
! build_field (s, union_type, rli);
/* Link the field into the type. */
*field_link = s->field;
--- 385,412 ----
create_common (gfc_common_head *com, segment_info * head)
{
segment_info *s, *next_s;
! tree node_type;
tree *field_link;
record_layout_info rli;
tree decl;
bool is_init = false;
! /* Declare the variables inside the common block.
! If the current common block contains any equivalence object, then
! make a UNION_TYPE node, otherwise RECORD_TYPE. This will let the
! alias analyzer work well when there is no address overlapping for
! common variables in the current common block. */
! if (saw_equiv)
! node_type = make_node (UNION_TYPE);
! else
! node_type = make_node (RECORD_TYPE);
!
! rli = start_record_layout (node_type);
! field_link = &TYPE_FIELDS (node_type);
for (s = head; s; s = s->next)
{
! build_field (s, node_type, rli);
/* Link the field into the type. */
*field_link = s->field;
*************** create_common (gfc_common_head *com, seg
*** 408,416 ****
finish_record_layout (rli, true);
if (com)
! decl = build_common_decl (com, union_type, is_init);
else
! decl = build_equiv_decl (union_type, is_init);
if (is_init)
{
--- 419,427 ----
finish_record_layout (rli, true);
if (com)
! decl = build_common_decl (com, node_type, is_init);
else
! decl = build_equiv_decl (node_type, is_init);
if (is_init)
{
*************** create_common (gfc_common_head *com, seg
*** 439,445 ****
}
}
gcc_assert (list);
! ctor = build1 (CONSTRUCTOR, union_type, nreverse(list));
TREE_CONSTANT (ctor) = 1;
TREE_INVARIANT (ctor) = 1;
TREE_STATIC (ctor) = 1;
--- 450,456 ----
}
}
gcc_assert (list);
! ctor = build1 (CONSTRUCTOR, node_type, nreverse(list));
TREE_CONSTANT (ctor) = 1;
TREE_INVARIANT (ctor) = 1;
TREE_STATIC (ctor) = 1;
*************** add_equivalences (void)
*** 718,723 ****
--- 729,736 ----
{
f->sym->equiv_built = 1;
more = find_equivalence (f);
+ if (more)
+ saw_equiv = true;
}
}
}
*************** translate_common (gfc_common_head *commo
*** 792,797 ****
--- 805,811 ----
common_segment = NULL;
current_offset = 0;
max_align = 1;
+ saw_equiv = false;
/* Add symbols to the segment. */
for (sym = var_list; sym; sym = sym->common_next)