This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]