This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][LTO][i386] Speed up type-merging, dump TYPE_STRUCTURAL_EQUALITY_P (for lto)
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 6 Jun 2010 00:04:56 +0200 (CEST)
- Subject: [PATCH][LTO][i386] Speed up type-merging, dump TYPE_STRUCTURAL_EQUALITY_P (for lto)
This uses TYPE_CANONICAL to cache type-merging results avoiding
repeated hashtable lookups and speeding up the merging process
considerably. Basically LTO re-computes TYPE_CANONICAL from
scratch, retaining only the canonical type during the substitution
process. Canonical types slightly differ from what the frontends
think (but we use it in the middle-end, so we better had a middle-end
idea about TYPE_CANONICAL ...).
This patch re-breaks PR35771 for LTO, but only because the fix
for it was bogus (and the fixup to i386.c still is - maybe - depending
on what the ABI mandates).
In the end I'd like to have all types a canonical type for
all languages - TYPE_STRUCTURAL_EQUALITY_P uses in the middle-end
have to go. I'm not yet 100% sure how to hook things up, but
either re-doing TYPE_CANONICAL computation or completely avoiding
it (and instead do the gimple TBAA type thing for all languages,
see http://gcc.gnu.org/ml/gcc-patches/2010-05/msg02424.html).
In the very far end we'd of course have gimplified types and decls
would have a pointer to the debug representation of their type.
But that's even farther off.
Anyway - bootstrapped and tested on x86_64-unknown-linux-gnu,
with and w/o WHOPR.
Any comments? Any takers for a real fix for PR35771?
Thanks,
Richard.
2010-06-05 Richard Guenther <rguenther@suse.de>
* lto-streamer-in.c (lto_input_ts_type_tree_pointers):
Do not stream but initialize TYPE_CANONICAL to NULL.
(lto_output_ts_type_tree_pointers): Do not stream TYPE_CANONICAL.
* gimple.c (gimple_types_compatible_p): Disregard
TYPE_STRUCTURAL_EQUALITY_P.
(gimple_register_type): Use TYPE_CANONICAL as cache.
* lto-streamer.c (lto_record_common_node): Zero TYPE_CANONICAL
before registering common types.
* config/i386/i386.c (ix86_function_arg_boundary): Do not
use TYPE_CANONICAL, instead use TYPE_MAIN_VARIANT.
Index: gcc/lto-streamer-in.c
===================================================================
*** gcc/lto-streamer-in.c (revision 160311)
--- gcc/lto-streamer-in.c (working copy)
*************** lto_input_ts_type_tree_pointers (struct
*** 2192,2198 ****
if (RECORD_OR_UNION_TYPE_P (expr))
TYPE_BINFO (expr) = lto_input_tree (ib, data_in);
TYPE_CONTEXT (expr) = lto_input_tree (ib, data_in);
! TYPE_CANONICAL (expr) = lto_input_tree (ib, data_in);
TYPE_STUB_DECL (expr) = lto_input_tree (ib, data_in);
}
--- 2192,2199 ----
if (RECORD_OR_UNION_TYPE_P (expr))
TYPE_BINFO (expr) = lto_input_tree (ib, data_in);
TYPE_CONTEXT (expr) = lto_input_tree (ib, data_in);
! /* TYPE_CANONICAL gets re-computed during type merging. */
! TYPE_CANONICAL (expr) = NULL_TREE;
TYPE_STUB_DECL (expr) = lto_input_tree (ib, data_in);
}
Index: gcc/lto-streamer-out.c
===================================================================
*** gcc/lto-streamer-out.c (revision 160311)
--- gcc/lto-streamer-out.c (working copy)
*************** lto_output_ts_type_tree_pointers (struct
*** 986,992 ****
if (RECORD_OR_UNION_TYPE_P (expr))
lto_output_tree_or_ref (ob, TYPE_BINFO (expr), ref_p);
lto_output_tree_or_ref (ob, TYPE_CONTEXT (expr), ref_p);
! lto_output_tree_or_ref (ob, TYPE_CANONICAL (expr), ref_p);
lto_output_tree_or_ref (ob, TYPE_STUB_DECL (expr), ref_p);
}
--- 986,993 ----
if (RECORD_OR_UNION_TYPE_P (expr))
lto_output_tree_or_ref (ob, TYPE_BINFO (expr), ref_p);
lto_output_tree_or_ref (ob, TYPE_CONTEXT (expr), ref_p);
! /* TYPE_CANONICAL is re-computed during type merging, so no need
! to stream it here. */
lto_output_tree_or_ref (ob, TYPE_STUB_DECL (expr), ref_p);
}
Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c (revision 160311)
--- gcc/gimple.c (working copy)
*************** gimple_types_compatible_p (tree t1, tree
*** 3592,3603 ****
{
tree f1, f2;
- /* If one type requires structural equality checks and the
- other doesn't, do not merge the types. */
- if (TYPE_STRUCTURAL_EQUALITY_P (t1)
- != TYPE_STRUCTURAL_EQUALITY_P (t2))
- goto different_types;
-
/* The struct tags shall compare equal. */
if (!compare_type_names_p (TYPE_MAIN_VARIANT (t1),
TYPE_MAIN_VARIANT (t2), false))
--- 3592,3597 ----
*************** gimple_register_type (tree t)
*** 3954,3959 ****
--- 3948,3958 ----
gcc_assert (TYPE_P (t));
+ /* In TYPE_CANONICAL we cache the result of gimple_register_type.
+ It is initially set to NULL during LTO streaming. */
+ if (TYPE_CANONICAL (t))
+ return TYPE_CANONICAL (t);
+
/* Always register the main variant first. This is important so we
pick up the non-typedef variants as canonical, otherwise we'll end
up taking typedef ids for structure tags during comparison. */
*************** gimple_register_type (tree t)
*** 4017,4026 ****
TYPE_NEXT_REF_TO (t) = NULL_TREE;
}
t = new_type;
}
else
! *slot = (void *) t;
return t;
}
--- 4016,4029 ----
TYPE_NEXT_REF_TO (t) = NULL_TREE;
}
+ TYPE_CANONICAL (t) = new_type;
t = new_type;
}
else
! {
! TYPE_CANONICAL (t) = t;
! *slot = (void *) t;
! }
return t;
}
Index: gcc/lto-streamer.c
===================================================================
*** gcc/lto-streamer.c (revision 160311)
--- gcc/lto-streamer.c (working copy)
*************** lto_record_common_node (tree *nodep, VEC
*** 674,680 ****
return;
if (TYPE_P (node))
! *nodep = node = gimple_register_type (node);
/* Return if node is already seen. */
if (pointer_set_insert (seen_nodes, node))
--- 674,685 ----
return;
if (TYPE_P (node))
! {
! /* Type merging will get confused by the canonical types as they
! are set by the middle-end. */
! TYPE_CANONICAL (node) = NULL_TREE;
! *nodep = node = gimple_register_type (node);
! }
/* Return if node is already seen. */
if (pointer_set_insert (seen_nodes, node))
Index: gcc/config/i386/i386.c
===================================================================
*** gcc/config/i386/i386.c (revision 160311)
--- gcc/config/i386/i386.c (working copy)
*************** ix86_function_arg_boundary (enum machine
*** 6393,6402 ****
int align;
if (type)
{
! /* Since canonical type is used for call, we convert it to
! canonical type if needed. */
! if (!TYPE_STRUCTURAL_EQUALITY_P (type))
! type = TYPE_CANONICAL (type);
align = TYPE_ALIGN (type);
}
else
--- 6393,6401 ----
int align;
if (type)
{
! /* Since the main variant type is used for call, we convert it to
! the main variant type. */
! type = TYPE_MAIN_VARIANT (type);
align = TYPE_ALIGN (type);
}
else