[LTO] Localize SSA variables

Jan Hubicka jh@suse.cz
Sun Jun 11 12:41:00 GMT 2006


Hi,
as discussed briefly with Diego and Kenneth on IRC, I would like to
break out the basic changes needed to make IPA on SSA happen from the
IPA branch and send them for consideration for merging to LTO branch.

In general I believe that we do want to perform IPA optimization on SSA
(not necesarily have the on-disc representation in SSA however) and that
the change is better to be done earlier, since it affects datastructure
decisions quite closely (ie all datastructures needs to be designed in a
way allowing multiple functions in SSA form, that is dificult for
example with current variable annotations and memory consumption of
basic SSA form is also more of a concern), so I think it is profitable
to merge the changes. However it can be done now or later on depending
on the overall plan to work on LTO.  I am mostly sending the patch for
consideration and comments.

If merging early seems good idea, I would like to proceed by incremental
patches pretty much as in a way I would like to send them in stage1 of
4.3.  There are number of details to discuss with people interestedin
SSA/gimple datastructures si hopefully this will also increase chances
to merge all relevant parts from IPA branch to mainline soon.

Overall mege plan would be to first localize the variables in current
step, in next step add the infrastructure allowing to turn multiple
functions into SSA (and don't do inlining), third part would be the
inliner itself.

I did some testing on IPA branch for GCC summit paper and to my surprise
the memory costs for turning everything into SSA early is pretty low and
is mostly made neutral by ability to optimize early and improve
effectivity of inlining.  There are few regressions caused by inliner
not being able to properly update SSA form after inlining functions that
after being inlined throw local exceptions.  I have rather intrusive fix
for this that I would like to avoid, so I would like to discuss this
details later during merging progress.  Otherwise things seems to be
quite stable.

Weak side of this patch is the fact that it localizes some variables
that can be shared across bodies with little rewriting of the underlying
datastructures (such as freelist and so).  Those are probably best
addressed by incremental patches I can send as followup, but of course
can do it in the patch as well or wait for some bigger reorganization of
SSA we will need to do in foreseeable future anyway.
Other weak side is that is uses the macros to access cfun->ssa fields
that are frequent in GCC sources to avoid merge headaches.  I used same
scheme for CFG branch and promised to clean it up later and still plan
to do so.  There is partial patch for this in the queue, but probably
late stage1 or mid stage2 is best to avoid branch syncronization issues.

Does this seem to make sense?

2006-06-09  Jan Hubicka  <jh@suse.cz>
	* tree-into-ssa.c: (in_ssa_p): Localize to SSA structure.
	(rewrite_into_ssa): Access dirrectly cfun->x_in_ssa-p
	* tree-ssa-alias.c (aliases_computed_p, call_clobbered_vars,
	addressable_vars, global_var): Localize to SSA structure.
	(init_alias_info, setup_pointers_and_addressables,
	maybe_create_global_var): Update uses of localized vars.
	* function.h (struct function): Add SSA field.
	* tree-flow-inline.h (mark_stmt_modified, is_call_clobbered,
	mark_call_clobbered, clear_call_cobbered, mark_non_addressable):
	Update for localized vars.
	* tree-dfa.c (referenced_vars, referenced_vars_dup_list, default_defs):
	Localize.
	(default_def): Break out major functionality to ....
	(default_def_fn)
	(set_default_def): Update for localized vars.
	* tree-cfgcleanup (modified_noreturn_calls): Localize.
	(cleanup_control_flow): Update use.
	* tree-ssa.c (verify_call_clobbering): Update for localized vars.
	(init_tree_ssa, delete_tree_ssa): Likewise.
	* tree-outof-ssa.c (rewrite_out_of_ssa): Likewise.
	* tree-flow.h (in_ssa_p
	(referenced_vars, referenced_vars_dup_list, ssa_names,
	modified_noreturn_calls, global_var, aliases_computed_p, in_ssa_p,
	free_ssanames, operand_memory, operand_memory_index, free_defs,
	free_uses, free_vuses, free_maydefs, free_mustdefs): New macros.
	(struct ssa): New struct.
	* Makefile.in (tree-ssa-operands): No longer produce GGC file.
	* tree-ssa-structalias.c (update_alias_info): Update for localized vars.
	* tree-ssanames.c (ssa_names, free_ssanames): Bring to SSA structure.
	* tree-ssa-operands.c (ops_active, operand_memory_index, free_defs,
	free_uses_free_vuses, free_maydefs, free_mustdefs): Bring local; update
	all uses.
Index: tree-into-ssa.c
===================================================================
*** tree-into-ssa.c	(revision 114491)
--- tree-into-ssa.c	(working copy)
*************** Boston, MA 02110-1301, USA.  */
*** 55,63 ****
     Graph. ACM Transactions on Programming Languages and Systems,
     13(4):451-490, October 1991.  */
  
- /* True if the code is in ssa form.  */
- bool in_ssa_p;
- 
  /* Structure to map a variable VAR to the set of blocks that contain
     definitions for VAR.  */
  struct def_blocks_d
--- 55,60 ----
*************** rewrite_into_ssa (void)
*** 1908,1914 ****
    sbitmap_free (interesting_blocks);
  
    timevar_pop (TV_TREE_SSA_OTHER);
!   in_ssa_p = true;
    return 0;
  }
  
--- 1905,1911 ----
    sbitmap_free (interesting_blocks);
  
    timevar_pop (TV_TREE_SSA_OTHER);
!   cfun->ssa->x_in_ssa_p = true;
    return 0;
  }
  
Index: tree-ssa-alias.c
===================================================================
*** tree-ssa-alias.c	(revision 114491)
--- tree-ssa-alias.c	(working copy)
*************** Boston, MA 02110-1301, USA.  */
*** 46,60 ****
  #include "ipa-type-escape.h"
  #include "vec.h"
  #include "bitmap.h"
  #include "vecprim.h"
  
  /* Obstack used to hold grouping bitmaps and other temporary bitmaps used by
     aliasing  */
  static bitmap_obstack alias_obstack;
  
- /* 'true' after aliases have been computed (see compute_may_aliases).  */
- bool aliases_computed_p;
- 
  /* Structure to map a variable to its alias set and keep track of the
     virtual operands that will be needed to represent it.  */
  struct alias_map_d
--- 46,58 ----
  #include "ipa-type-escape.h"
  #include "vec.h"
  #include "bitmap.h"
+ #include "ipa-prop.h"
  #include "vecprim.h"
  
  /* Obstack used to hold grouping bitmaps and other temporary bitmaps used by
     aliasing  */
  static bitmap_obstack alias_obstack;
  
  /* Structure to map a variable to its alias set and keep track of the
     virtual operands that will be needed to represent it.  */
  struct alias_map_d
*************** static void set_pt_anything (tree ptr);
*** 117,142 ****
  
  /* Global declarations.  */
  
- /* Call clobbered variables in the function.  If bit I is set, then
-    REFERENCED_VARS (I) is call-clobbered.  */
- bitmap call_clobbered_vars;
- 
- /* Addressable variables in the function.  If bit I is set, then
-    REFERENCED_VARS (I) has had its address taken.  Note that
-    CALL_CLOBBERED_VARS and ADDRESSABLE_VARS are not related.  An
-    addressable variable is not necessarily call-clobbered (e.g., a
-    local addressable whose address does not escape) and not all
-    call-clobbered variables are addressable (e.g., a local static
-    variable).  */
- bitmap addressable_vars;
- 
- /* When the program has too many call-clobbered variables and call-sites,
-    this variable is used to represent the clobbering effects of function
-    calls.  In these cases, all the call clobbered variables in the program
-    are forced to alias this variable.  This reduces compile times by not
-    having to keep track of too many V_MAY_DEF expressions at call sites.  */
- tree global_var;
- 
  /* qsort comparison function to sort type/name tags by DECL_UID.  */
  
  static int
--- 115,120 ----
*************** init_alias_info (void)
*** 890,896 ****
        /* Similarly, clear the set of addressable variables.  In this
  	 case, we can just clear the set because addressability is
  	 only computed here.  */
!       bitmap_clear (addressable_vars);
  
        /* Clear flow-insensitive alias information from each symbol.  */
        FOR_EACH_REFERENCED_VAR (var, rvi)
--- 868,874 ----
        /* Similarly, clear the set of addressable variables.  In this
  	 case, we can just clear the set because addressability is
  	 only computed here.  */
!       bitmap_clear (cfun->ssa->addressable_vars);
  
        /* Clear flow-insensitive alias information from each symbol.  */
        FOR_EACH_REFERENCED_VAR (var, rvi)
*************** setup_pointers_and_addressables (struct 
*** 1671,1677 ****
           cleanup passes.  */
        if (TREE_ADDRESSABLE (var))
  	{
! 	  if (!bitmap_bit_p (addressable_vars, DECL_UID (var))
  	      && TREE_CODE (var) != RESULT_DECL
  	      && !is_global_var (var))
  	    {
--- 1649,1655 ----
           cleanup passes.  */
        if (TREE_ADDRESSABLE (var))
  	{
! 	  if (!bitmap_bit_p (cfun->ssa->addressable_vars, DECL_UID (var))
  	      && TREE_CODE (var) != RESULT_DECL
  	      && !is_global_var (var))
  	    {
*************** setup_pointers_and_addressables (struct 
*** 1691,1697 ****
  
  		  for (sv = svars; sv; sv = sv->next)
  		    {	      
! 		      if (bitmap_bit_p (addressable_vars, DECL_UID (sv->var)))
  			okay_to_mark = false;
  		      mark_sym_for_renaming (sv->var);
  		    }
--- 1669,1675 ----
  
  		  for (sv = svars; sv; sv = sv->next)
  		    {	      
! 		      if (bitmap_bit_p (cfun->ssa->addressable_vars, DECL_UID (sv->var)))
  			okay_to_mark = false;
  		      mark_sym_for_renaming (sv->var);
  		    }
*************** maybe_create_global_var (struct alias_in
*** 1816,1822 ****
      {
        /* Count all the call-clobbered variables.  */
        n_clobbered = 0;
!       EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
  	{
  	  n_clobbered++;
  	}
--- 1794,1800 ----
      {
        /* Count all the call-clobbered variables.  */
        n_clobbered = 0;
!       EXECUTE_IF_SET_IN_BITMAP (cfun->ssa->call_clobbered_vars, 0, i, bi)
  	{
  	  n_clobbered++;
  	}
*************** maybe_create_global_var (struct alias_in
*** 1859,1865 ****
    /* Mark all call-clobbered symbols for renaming.  Since the initial
       rewrite into SSA ignored all call sites, we may need to rename
       .GLOBAL_VAR and the call-clobbered variables.   */
!   EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
      {
        tree var = referenced_var (i);
  
--- 1837,1843 ----
    /* Mark all call-clobbered symbols for renaming.  Since the initial
       rewrite into SSA ignored all call sites, we may need to rename
       .GLOBAL_VAR and the call-clobbered variables.   */
!   EXECUTE_IF_SET_IN_BITMAP (cfun->ssa->call_clobbered_vars, 0, i, bi)
      {
        tree var = referenced_var (i);
  
Index: function.h
===================================================================
*** function.h	(revision 114491)
--- function.h	(working copy)
*************** struct expr_status GTY(())
*** 159,164 ****
--- 159,165 ----
  #define forced_labels (cfun->expr->x_forced_labels)
  #define stack_pointer_delta (cfun->expr->x_stack_pointer_delta)
  
+ struct ssa;
  struct temp_slot;
  typedef struct temp_slot *temp_slot_p;
  
*************** struct function GTY(())
*** 178,183 ****
--- 179,185 ----
    /* The control flow graph for this function.  */
    struct control_flow_graph *cfg;
    bool after_inlining;
+   struct ssa *ssa;
  
    /* For function.c.  */
  
*************** extern bool pass_by_reference (CUMULATIV
*** 576,581 ****
--- 578,584 ----
  extern bool reference_callee_copied (CUMULATIVE_ARGS *, enum machine_mode,
  				     tree, bool);
  
+ extern int get_last_funcdef_no (void);
  extern void used_types_insert (tree);
  
  #endif  /* GCC_FUNCTION_H */
Index: tree-flow-inline.h
===================================================================
*** tree-flow-inline.h	(revision 114491)
--- tree-flow-inline.h	(working copy)
*************** mark_stmt_modified (tree t)
*** 265,271 ****
    ann = stmt_ann (t);
    if (ann == NULL)
      ann = create_stmt_ann (t);
!   else if (noreturn_call_p (t))
      VEC_safe_push (tree, gc, modified_noreturn_calls, t);
    ann->modified = 1;
  }
--- 265,271 ----
    ann = stmt_ann (t);
    if (ann == NULL)
      ann = create_stmt_ann (t);
!   else if (noreturn_call_p (t) && cfun->ssa)
      VEC_safe_push (tree, gc, modified_noreturn_calls, t);
    ann->modified = 1;
  }
*************** is_call_clobbered (tree var)
*** 747,753 ****
    if (!MTAG_P (var))
      return DECL_CALL_CLOBBERED (var);
    else
!     return bitmap_bit_p (call_clobbered_vars, DECL_UID (var)); 
  }
  
  /* Mark variable VAR as being clobbered by function calls.  */
--- 747,753 ----
    if (!MTAG_P (var))
      return DECL_CALL_CLOBBERED (var);
    else
!     return bitmap_bit_p (cfun->ssa->call_clobbered_vars, DECL_UID (var)); 
  }
  
  /* Mark variable VAR as being clobbered by function calls.  */
*************** mark_call_clobbered (tree var, unsigned 
*** 757,763 ****
    var_ann (var)->escape_mask |= escape_type;
    if (!MTAG_P (var))
      DECL_CALL_CLOBBERED (var) = true;
!   bitmap_set_bit (call_clobbered_vars, DECL_UID (var));
  }
  
  /* Clear the call-clobbered attribute from variable VAR.  */
--- 757,763 ----
    var_ann (var)->escape_mask |= escape_type;
    if (!MTAG_P (var))
      DECL_CALL_CLOBBERED (var) = true;
!   bitmap_set_bit (cfun->ssa->call_clobbered_vars, DECL_UID (var));
  }
  
  /* Clear the call-clobbered attribute from variable VAR.  */
*************** clear_call_clobbered (tree var)
*** 770,776 ****
      MTAG_GLOBAL (var) = 0;
    if (!MTAG_P (var))
      DECL_CALL_CLOBBERED (var) = false;
!   bitmap_clear_bit (call_clobbered_vars, DECL_UID (var));
  }
  
  /* Mark variable VAR as being non-addressable.  */
--- 770,776 ----
      MTAG_GLOBAL (var) = 0;
    if (!MTAG_P (var))
      DECL_CALL_CLOBBERED (var) = false;
!   bitmap_clear_bit (cfun->ssa->call_clobbered_vars, DECL_UID (var));
  }
  
  /* Mark variable VAR as being non-addressable.  */
*************** mark_non_addressable (tree var)
*** 779,785 ****
  {
    if (!MTAG_P (var))
      DECL_CALL_CLOBBERED (var) = false;
!   bitmap_clear_bit (call_clobbered_vars, DECL_UID (var));
    TREE_ADDRESSABLE (var) = 0;
  }
  
--- 779,785 ----
  {
    if (!MTAG_P (var))
      DECL_CALL_CLOBBERED (var) = false;
!   bitmap_clear_bit (cfun->ssa->call_clobbered_vars, DECL_UID (var));
    TREE_ADDRESSABLE (var) = 0;
  }
  
Index: gimplify.c
===================================================================
*** gimplify.c	(revision 114491)
--- gimplify.c	(working copy)
*************** force_gimple_operand (tree expr, tree *s
*** 6227,6233 ****
  		       gimple_test_f, fb_rvalue);
    gcc_assert (ret != GS_ERROR);
  
!   if (referenced_vars)
      {
        for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
  	add_referenced_var (t);
--- 6227,6233 ----
  		       gimple_test_f, fb_rvalue);
    gcc_assert (ret != GS_ERROR);
  
!   if (cfun->ssa && referenced_vars)
      {
        for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
  	add_referenced_var (t);
Index: tree-dfa.c
===================================================================
*** tree-dfa.c	(revision 114491)
--- tree-dfa.c	(working copy)
*************** static tree find_vars_r (tree *, int *, 
*** 73,88 ****
  
  /* Global declarations.  */
  
- /* Array of all variables referenced in the function.  */
- htab_t referenced_vars;
- /* List of referenced variables with duplicate UID's.  */
- VEC(tree,gc) *referenced_vars_dup_list;
- 
- /* Default definition for this symbols.  If set for symbol, it
-    means that the first reference to this variable in the function is a
-    USE or a VUSE.  In those cases, the SSA renamer creates an SSA name
-    for this variable with an empty defining statement.  */
- htab_t default_defs;
  
  
  /*---------------------------------------------------------------------------
--- 73,78 ----
*************** make_rename_temp (tree type, const char 
*** 228,234 ****
    if (TREE_CODE (type) == COMPLEX_TYPE)
      DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
  
!   if (referenced_vars)
      {
        add_referenced_var (t);
        mark_sym_for_renaming (t);
--- 218,224 ----
    if (TREE_CODE (type) == COMPLEX_TYPE)
      DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
  
!   if (cfun->ssa && referenced_vars)
      {
        add_referenced_var (t);
        mark_sym_for_renaming (t);
*************** referenced_var_check_and_insert (tree to
*** 676,693 ****
     variable.  */
  
  tree 
! default_def (tree var)
  {
    struct int_tree_map *h, in;
    gcc_assert (SSA_VAR_P (var));
    in.uid = DECL_UID (var);
!   h = (struct int_tree_map *) htab_find_with_hash (default_defs, &in,
                                                     DECL_UID (var));
    if (h)
      return h->to;
    return NULL_TREE;
  }
  
  /* Insert the pair VAR's UID, DEF into the default_defs hashtable.  */
  
  void
--- 666,689 ----
     variable.  */
  
  tree 
! default_def_fn (struct function *fn, tree var)
  {
    struct int_tree_map *h, in;
    gcc_assert (SSA_VAR_P (var));
    in.uid = DECL_UID (var);
!   h = (struct int_tree_map *) htab_find_with_hash (fn->ssa->default_defs, &in,
                                                     DECL_UID (var));
    if (h)
      return h->to;
    return NULL_TREE;
  }
  
+ tree 
+ default_def (tree var)
+ {
+   return default_def_fn (cfun, var);
+ }
+ 
  /* Insert the pair VAR's UID, DEF into the default_defs hashtable.  */
  
  void
*************** set_default_def (tree var, tree def)
*** 701,712 ****
    in.uid = DECL_UID (var);
    if (!def && default_def (var))
      {
!       loc = htab_find_slot_with_hash (default_defs, &in, DECL_UID (var), INSERT);
!       htab_remove_elt (default_defs, *loc);
        return;
      }
    gcc_assert (TREE_CODE (def) == SSA_NAME);
!   loc = htab_find_slot_with_hash (default_defs, &in, DECL_UID (var), INSERT);
    /* Default definition might be changed by tail call optimization.  */
    if (!*loc)
      {
--- 697,708 ----
    in.uid = DECL_UID (var);
    if (!def && default_def (var))
      {
!       loc = htab_find_slot_with_hash (cfun->ssa->default_defs, &in, DECL_UID (var), INSERT);
!       htab_remove_elt (cfun->ssa->default_defs, *loc);
        return;
      }
    gcc_assert (TREE_CODE (def) == SSA_NAME);
!   loc = htab_find_slot_with_hash (cfun->ssa->default_defs, &in, DECL_UID (var), INSERT);
    /* Default definition might be changed by tail call optimization.  */
    if (!*loc)
      {
Index: tree-cfgcleanup.c
===================================================================
*** tree-cfgcleanup.c	(revision 114491)
--- tree-cfgcleanup.c	(working copy)
*************** cleanup_control_expr_graph (basic_block 
*** 127,140 ****
    return retval;
  }
  
- /* A list of all the noreturn calls passed to modify_stmt.
-    cleanup_control_flow uses it to detect cases where a mid-block
-    indirect call has been turned into a noreturn call.  When this
-    happens, all the instructions after the call are no longer
-    reachable and must be deleted as dead.  */
- 
- VEC(tree,gc) *modified_noreturn_calls;
- 
  /* Try to remove superfluous control structures.  */
  
  static bool
--- 127,132 ----
*************** cleanup_control_flow (void)
*** 146,158 ****
    tree stmt;
  
    /* Detect cases where a mid-block call is now known not to return.  */
!   while (VEC_length (tree, modified_noreturn_calls))
!     {
!       stmt = VEC_pop (tree, modified_noreturn_calls);
!       bb = bb_for_stmt (stmt);
!       if (bb != NULL && last_stmt (bb) != stmt && noreturn_call_p (stmt))
! 	split_block (bb, stmt);
!     }
  
    FOR_EACH_BB (bb)
      {
--- 138,151 ----
    tree stmt;
  
    /* Detect cases where a mid-block call is now known not to return.  */
!   if (cfun->ssa)
!     while (VEC_length (tree, modified_noreturn_calls))
!       {
! 	stmt = VEC_pop (tree, modified_noreturn_calls);
! 	bb = bb_for_stmt (stmt);
! 	if (bb != NULL && last_stmt (bb) != stmt && noreturn_call_p (stmt))
! 	  split_block (bb, stmt);
!       }
  
    FOR_EACH_BB (bb)
      {
Index: tree-ssa.c
===================================================================
*** tree-ssa.c	(revision 114491)
--- tree-ssa.c	(working copy)
*************** verify_call_clobbering (void)
*** 627,633 ****
       that everything in call_clobbered_vars is marked
       DECL_CALL_CLOBBERED, and that everything marked
       DECL_CALL_CLOBBERED is in call_clobbered_vars.  */
!   EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
      {
        var = referenced_var (i);
        if (!MTAG_P (var) && !DECL_CALL_CLOBBERED (var))
--- 627,633 ----
       that everything in call_clobbered_vars is marked
       DECL_CALL_CLOBBERED, and that everything marked
       DECL_CALL_CLOBBERED is in call_clobbered_vars.  */
!   EXECUTE_IF_SET_IN_BITMAP (cfun->ssa->call_clobbered_vars, 0, i, bi)
      {
        var = referenced_var (i);
        if (!MTAG_P (var) && !DECL_CALL_CLOBBERED (var))
*************** verify_call_clobbering (void)
*** 640,646 ****
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
        if (!MTAG_P (var) && DECL_CALL_CLOBBERED (var)
! 	  && !bitmap_bit_p (call_clobbered_vars, DECL_UID (var)))
  	{
  	  error ("variable marked DECL_CALL_CLOBBERED but not in call_clobbered_vars bitmap.");
  	  debug_variable (var);
--- 640,646 ----
    FOR_EACH_REFERENCED_VAR (var, rvi)
      {
        if (!MTAG_P (var) && DECL_CALL_CLOBBERED (var)
! 	  && !bitmap_bit_p (cfun->ssa->call_clobbered_vars, DECL_UID (var)))
  	{
  	  error ("variable marked DECL_CALL_CLOBBERED but not in call_clobbered_vars bitmap.");
  	  debug_variable (var);
*************** int_tree_map_hash (const void *item)
*** 830,840 ****
  void
  init_tree_ssa (void)
  {
    referenced_vars = htab_create_ggc (20, int_tree_map_hash, 
  				     int_tree_map_eq, NULL);
!   default_defs = htab_create_ggc (20, int_tree_map_hash, int_tree_map_eq, NULL);
!   call_clobbered_vars = BITMAP_ALLOC (NULL);
!   addressable_vars = BITMAP_ALLOC (NULL);
    init_alias_heapvars ();
    init_ssanames ();
    init_phinodes ();
--- 830,842 ----
  void
  init_tree_ssa (void)
  {
+   cfun->ssa = ggc_alloc_cleared (sizeof (struct ssa));
    referenced_vars = htab_create_ggc (20, int_tree_map_hash, 
  				     int_tree_map_eq, NULL);
!   cfun->ssa->default_defs = htab_create_ggc (20, int_tree_map_hash, 
! 				             int_tree_map_eq, NULL);
!   cfun->ssa->call_clobbered_vars = BITMAP_GGC_ALLOC ();
!   cfun->ssa->addressable_vars = BITMAP_GGC_ALLOC ();
    init_alias_heapvars ();
    init_ssanames ();
    init_phinodes ();
*************** delete_tree_ssa (void)
*** 906,916 ****
  
    global_var = NULL_TREE;
    
!   htab_delete (default_defs);
!   BITMAP_FREE (call_clobbered_vars);
!   call_clobbered_vars = NULL;
!   BITMAP_FREE (addressable_vars);
!   addressable_vars = NULL;
    modified_noreturn_calls = NULL;
    aliases_computed_p = false;
    delete_alias_heapvars ();
--- 908,916 ----
  
    global_var = NULL_TREE;
    
!   htab_delete (cfun->ssa->default_defs);
!   cfun->ssa->call_clobbered_vars = NULL;
!   cfun->ssa->addressable_vars = NULL;
    modified_noreturn_calls = NULL;
    aliases_computed_p = false;
    delete_alias_heapvars ();
Index: tree-outof-ssa.c
===================================================================
*** tree-outof-ssa.c	(revision 114491)
--- tree-outof-ssa.c	(working copy)
*************** rewrite_out_of_ssa (void)
*** 2545,2551 ****
    /* Flush out flow graph and SSA data.  */
    delete_var_map (map);
  
!   in_ssa_p = false;
    return 0;
  }
  
--- 2545,2551 ----
    /* Flush out flow graph and SSA data.  */
    delete_var_map (map);
  
!   cfun->ssa->x_in_ssa_p = false;
    return 0;
  }
  
Index: tree-flow.h
===================================================================
*** tree-flow.h	(revision 114491)
--- tree-flow.h	(working copy)
*************** Boston, MA 02110-1301, USA.  */
*** 30,35 ****
--- 30,36 ----
  #include "tree-ssa-operands.h"
  #include "cgraph.h"
  #include "ipa-reference.h"
+ #include "ipa-prop.h"
  
  /* Forward declare structures for the garbage collector GTY markers.  */
  #ifndef GCC_BASIC_BLOCK_H
*************** struct basic_block_def;
*** 39,46 ****
  typedef struct basic_block_def *basic_block;
  #endif
  
! /* True if the code is in ssa form.  */
! extern bool in_ssa_p;
  
  typedef struct
  {
--- 40,120 ----
  typedef struct basic_block_def *basic_block;
  #endif
  
! struct ssa GTY(()) {
!   /* Array of all variables referenced in the function.  */
!   htab_t GTY((param_is (struct int_tree_map))) x_referenced_vars;
!   /* List of referenced variables in the function with duplicate UID's.  */
!   VEC(tree,gc) *x_referenced_vars_dup_list;
!   /* A list of all the noreturn calls passed to modify_stmt.
!      cleanup_control_flow uses it to detect cases where a mid-block
!      indirect call has been turned into a noreturn call.  When this
!      happens, all the instructions after the call are no longer
!      reachable and must be deleted as dead.  */
!   VEC(tree,gc) *x_modified_noreturn_calls;
!   /* Array of all SSA_NAMEs used in the function.  */
!   VEC(tree,gc) *x_ssa_names;
! 
!   /* Artificial variable used to model the effects of function calls.  */
!   tree x_global_var;
! 
!   /* Call clobbered variables in the function.  If bit I is set, then
!      REFERENCED_VARS (I) is call-clobbered.  */
!   bitmap call_clobbered_vars;
! 
!   /* Addressable variables in the function.  If bit I is set, then
!      REFERENCED_VARS (I) has had its address taken.  Note that
!      CALL_CLOBBERED_VARS and ADDRESSABLE_VARS are not related.  An
!      addressable variable is not necessarily call-clobbered (e.g., a
!      local addressable whose address does not escape) and not all
!      call-clobbered variables are addressable (e.g., a local static
!      variable).  */
!   bitmap addressable_vars;
! 
!   /* 'true' after aliases have been computed (see compute_may_aliases).  */
!   bool x_aliases_computed_p;
! 
!   bool x_in_ssa_p;
! 
!   /* Free list of SSA_NAMEs.  */
!   tree x_free_ssanames;
! 
!   struct ssa_operand_memory_d *x_operand_memory;
!   unsigned x_operand_memory_index;
! 
!   bool ops_active;
! 
!   struct def_optype_d * GTY((skip)) x_free_defs;
!   struct use_optype_d * GTY((skip)) x_free_uses;
!   struct vuse_optype_d * GTY((skip)) x_free_vuses;
!   struct maydef_optype_d * GTY((skip)) x_free_maydefs;
!   struct mustdef_optype_d * GTY((skip)) x_free_mustdefs;
! 
!   /* Hashtable holding definition for symbol.  If this field is not NULL, it
!      means that the first reference to this variable in the function is a
!      USE or a VUSE.  In those cases, the SSA renamer creates an SSA name
!      for this variable with an empty defining statement.  */
!   htab_t GTY((param_is (struct int_tree_map))) default_defs;
! };
! #define referenced_vars cfun->ssa->x_referenced_vars
! #define referenced_vars_dup_list cfun->ssa->x_referenced_vars_dup_list
! #define ssa_names cfun->ssa->x_ssa_names
! #define modified_noreturn_calls cfun->ssa->x_modified_noreturn_calls
! #define global_var cfun->ssa->x_global_var
! #define aliases_computed_p cfun->ssa->x_aliases_computed_p
! #define in_ssa_p (cfun->ssa && cfun->ssa->x_in_ssa_p)
! 
! /* FIXME: Little rewrite of tree-ssa-operands could probably make those shared
!    across all functions avoiding need to privatize them.  Envolving
!    tree-ssa-operands implementation however makes this step bit impractircal.
!    */
! #define free_defs (cfun->ssa->x_free_defs)
! #define free_uses (cfun->ssa->x_free_uses)
! #define free_vuses (cfun->ssa->x_free_vuses)
! #define free_maydefs (cfun->ssa->x_free_maydefs)
! #define free_mustdefs (cfun->ssa->x_free_mustdefs)
! #define free_ssanames (cfun->ssa->x_free_ssanames)
! #define operand_memory (cfun->ssa->x_operand_memory)
! #define operand_memory_index (cfun->ssa->x_operand_memory_index)
  
  typedef struct
  {
*************** struct var_ann_d GTY(())
*** 203,209 ****
    /* During into-ssa and the dominator optimizer, this field holds the
       current version of this variable (an SSA_NAME).  */
    tree current_def;
!   
    /* If this variable is a structure, this fields holds a list of
       symbols representing each of the fields of the structure.  */
    subvar_t subvars;
--- 277,283 ----
    /* During into-ssa and the dominator optimizer, this field holds the
       current version of this variable (an SSA_NAME).  */
    tree current_def;
! 
    /* If this variable is a structure, this fields holds a list of
       symbols representing each of the fields of the structure.  */
    subvar_t subvars;
*************** typedef struct immediate_use_iterator_d
*** 263,269 ****
  
  
  /* Use this iterator in combination with FOR_EACH_IMM_USE_STMT to 
!    get access to each occurrence of ssavar on the stmt returned by
     that iterator..  for instance:
  
       FOR_EACH_IMM_USE_STMT (stmt, iter, var)
--- 337,343 ----
  
  
  /* Use this iterator in combination with FOR_EACH_IMM_USE_STMT to 
!    get access to each occurence of ssavar on the stmt returned by
     that iterator..  for instance:
  
       FOR_EACH_IMM_USE_STMT (stmt, iter, var)
*************** union tree_ann_d GTY((desc ("ann_type ((
*** 326,333 ****
    struct stmt_ann_d GTY((tag ("STMT_ANN"))) stmt;
  };
  
- extern GTY(()) VEC(tree,gc) *modified_noreturn_calls;
- 
  typedef union tree_ann_d *tree_ann_t;
  typedef struct var_ann_d *var_ann_t;
  typedef struct function_ann_d *function_ann_t;
--- 400,405 ----
*************** typedef struct
*** 417,454 ****
         VEC_iterate (tree, (VEC), (ITER).i, (VAR)); \
         (ITER).i++)
  
- /* Array of all variables referenced in the function.  */
- extern GTY((param_is (struct int_tree_map))) htab_t referenced_vars;
- /* List of referenced variables in the function with duplicate UID's.  */
- extern VEC(tree,gc) *referenced_vars_dup_list;
- 
- /* Default defs for undefined symbols. */
- extern GTY((param_is (struct int_tree_map))) htab_t default_defs;
- 
  extern tree referenced_var_lookup (unsigned int);
  #define num_referenced_vars htab_elements (referenced_vars)
  #define referenced_var(i) referenced_var_lookup (i)
  
- /* Array of all SSA_NAMEs used in the function.  */
- extern GTY(()) VEC(tree,gc) *ssa_names;
- 
  #define num_ssa_names (VEC_length (tree, ssa_names))
  #define ssa_name(i) (VEC_index (tree, ssa_names, (i)))
  
- /* Artificial variable used to model the effects of function calls.  */
- extern GTY(()) tree global_var;
- 
- /* Call clobbered variables in the function.  If bit I is set, then
-    REFERENCED_VARS (I) is call-clobbered.  */
- extern bitmap call_clobbered_vars;
- 
- /* Addressable variables in the function.  If bit I is set, then
-    REFERENCED_VARS (I) has had its address taken.  */
- extern bitmap addressable_vars;
- 
- /* 'true' after aliases have been computed (see compute_may_aliases).  */
- extern bool aliases_computed_p;
- 
  /* Macros for showing usage statistics.  */
  #define SCALE(x) ((unsigned long) ((x) < 1024*10	\
  		  ? (x)					\
--- 489,501 ----
*************** extern void debug_points_to_info_for (tr
*** 669,674 ****
--- 716,722 ----
  extern bool may_be_aliased (tree);
  extern bool is_aliased_with (tree, tree);
  extern struct ptr_info_def *get_ptr_info (tree);
+ extern void add_type_alias (tree, tree);
  extern void new_type_alias (tree, tree);
  extern void count_uses_and_derefs (tree, tree, unsigned *, unsigned *, bool *);
  static inline subvar_t get_subvars_for_var (tree);
Index: Makefile.in
===================================================================
*** Makefile.in	(revision 114491)
--- Makefile.in	(working copy)
*************** tree-dfa.o : tree-dfa.c $(TREE_FLOW_H) $
*** 1967,1973 ****
  tree-ssa-operands.o : tree-ssa-operands.c $(TREE_FLOW_H) $(CONFIG_H) \
     $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) errors.h $(TREE_INLINE_H) \
     $(FLAGS_H) $(FUNCTION_H) $(TM_H) $(TIMEVAR_H) tree-pass.h toplev.h \
!    gt-tree-ssa-operands.h coretypes.h langhooks.h $(IPA_REFERENCE_H)
  tree-eh.o : tree-eh.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(RTL_H) $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) except.h langhooks.h \
     $(GGC_H) tree-pass.h coretypes.h $(TIMEVAR_H) $(TM_P_H) \
--- 1967,1973 ----
  tree-ssa-operands.o : tree-ssa-operands.c $(TREE_FLOW_H) $(CONFIG_H) \
     $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) errors.h $(TREE_INLINE_H) \
     $(FLAGS_H) $(FUNCTION_H) $(TM_H) $(TIMEVAR_H) tree-pass.h toplev.h \
!    coretypes.h langhooks.h $(IPA_REFERENCE_H)
  tree-eh.o : tree-eh.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(RTL_H) $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) except.h langhooks.h \
     $(GGC_H) tree-pass.h coretypes.h $(TIMEVAR_H) $(TM_P_H) \
*************** cgraphunit.o : cgraphunit.c $(CONFIG_H) 
*** 2286,2292 ****
     $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(FLAGS_H) $(GGC_H) \
     $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(TREE_GIMPLE_H) \
     $(TREE_FLOW_H) tree-pass.h $(C_COMMON_H) debug.h $(DIAGNOSTIC_H) \
!    $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) ipa-prop.h
  ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) 
  ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h  \
     langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) ipa-prop.h \
--- 2286,2293 ----
     $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(FLAGS_H) $(GGC_H) \
     $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(TREE_GIMPLE_H) \
     $(TREE_FLOW_H) tree-pass.h $(C_COMMON_H) debug.h $(DIAGNOSTIC_H) \
!    $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) ipa-prop.h \
!    gt-cgraphunit.h
  ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) 
  ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h  \
     langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) ipa-prop.h \
*************** GTFILES = $(srcdir)/input.h $(srcdir)/co
*** 2837,2843 ****
    $(srcdir)/cselib.h $(srcdir)/basic-block.h  $(srcdir)/cgraph.h \
    $(srcdir)/c-common.h $(srcdir)/c-tree.h $(srcdir)/reload.h \
    $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
!   $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c\
    $(srcdir)/dbxout.c $(srcdir)/dwarf2out.c $(srcdir)/dwarf2asm.c \
    $(srcdir)/dojump.c $(srcdir)/tree-profile.c \
    $(srcdir)/emit-rtl.c $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
--- 2838,2844 ----
    $(srcdir)/cselib.h $(srcdir)/basic-block.h  $(srcdir)/cgraph.h \
    $(srcdir)/c-common.h $(srcdir)/c-tree.h $(srcdir)/reload.h \
    $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
!   $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/cgraphunit.c \
    $(srcdir)/dbxout.c $(srcdir)/dwarf2out.c $(srcdir)/dwarf2asm.c \
    $(srcdir)/dojump.c $(srcdir)/tree-profile.c \
    $(srcdir)/emit-rtl.c $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
*************** GTFILES = $(srcdir)/input.h $(srcdir)/co
*** 2854,2860 ****
    $(srcdir)/tree-dfa.c $(srcdir)/tree-ssa-propagate.c \
    $(srcdir)/tree-iterator.c $(srcdir)/gimplify.c \
    $(srcdir)/tree-chrec.h $(srcdir)/tree-vect-generic.c \
!   $(srcdir)/tree-ssa-operands.h $(srcdir)/tree-ssa-operands.c \
    $(srcdir)/tree-profile.c $(srcdir)/tree-nested.c \
    $(srcdir)/ipa-reference.c $(srcdir)/tree-ssa-structalias.h \
    $(srcdir)/tree-ssa-structalias.c \
--- 2855,2861 ----
    $(srcdir)/tree-dfa.c $(srcdir)/tree-ssa-propagate.c \
    $(srcdir)/tree-iterator.c $(srcdir)/gimplify.c \
    $(srcdir)/tree-chrec.h $(srcdir)/tree-vect-generic.c \
!   $(srcdir)/tree-ssa-operands.h \
    $(srcdir)/tree-profile.c $(srcdir)/tree-nested.c \
    $(srcdir)/ipa-reference.c $(srcdir)/tree-ssa-structalias.h \
    $(srcdir)/tree-ssa-structalias.c \
*************** gt-tree-mudflap.h gt-tree-vect-generic.h
*** 2890,2897 ****
  gt-tree-profile.h gt-tree-ssa-address.h \
  gt-tree-ssanames.h gt-tree-iterator.h gt-gimplify.h \
  gt-tree-phinodes.h gt-tree-nested.h \
! gt-tree-ssa-operands.h gt-tree-ssa-propagate.h \
! gt-tree-ssa-structalias.h \
  gt-stringpool.h gt-targhooks.h gt-omp-low.h : s-gtype ; @true
  
  define echo_quoted_to_gtyp
--- 2891,2898 ----
  gt-tree-profile.h gt-tree-ssa-address.h \
  gt-tree-ssanames.h gt-tree-iterator.h gt-gimplify.h \
  gt-tree-phinodes.h gt-tree-nested.h \
! gt-tree-ssa-propagate.h \
! gt-tree-ssa-structalias.h gt-cgraphunit.h \
  gt-stringpool.h gt-targhooks.h gt-omp-low.h : s-gtype ; @true
  
  define echo_quoted_to_gtyp
Index: tree-ssa-structalias.c
===================================================================
*** tree-ssa-structalias.c	(revision 114491)
--- tree-ssa-structalias.c	(working copy)
*************** update_alias_info (tree stmt, struct ali
*** 2978,2984 ****
    addr_taken = addresses_taken (stmt);
    if (addr_taken)
      {
!       bitmap_ior_into (addressable_vars, addr_taken);
  
        /* If STMT is an escape point, all the addresses taken by it are
  	 call-clobbered.  */
--- 2978,2984 ----
    addr_taken = addresses_taken (stmt);
    if (addr_taken)
      {
!       bitmap_ior_into (cfun->ssa->addressable_vars, addr_taken);
  
        /* If STMT is an escape point, all the addresses taken by it are
  	 call-clobbered.  */
*************** update_alias_info (tree stmt, struct ali
*** 3023,3029 ****
  	     so that they can be treated like regular statements?
  	     Currently, they are treated as second-class
  	     statements.  */
! 	  add_to_addressable_set (TREE_OPERAND (op, 0), &addressable_vars);
  	  continue;
  	}
  
--- 3023,3029 ----
  	     so that they can be treated like regular statements?
  	     Currently, they are treated as second-class
  	     statements.  */
! 	  add_to_addressable_set (TREE_OPERAND (op, 0), &cfun->ssa->addressable_vars);
  	  continue;
  	}
  
Index: config/i386/i386.opt
===================================================================
*** config/i386/i386.opt	(revision 114491)
--- config/i386/i386.opt	(working copy)
*************** minline-all-stringops
*** 125,130 ****
--- 125,134 ----
  Target Report Mask(INLINE_ALL_STRINGOPS)
  Inline all known string operations
  
+ minline-stringops-dynamically
+ Target Report Mask(INLINE_STRINGOPS_DYNAMICALLY)
+ Inline memset/memcpy string operations, but perform inline version only for small blocks
+ 
  mintel-syntax
  Target Undocumented
  ;; Deprecated
Index: config/i386/i386.c
===================================================================
*** config/i386/i386.c	(revision 114491)
--- config/i386/i386.c	(working copy)
*************** ix86_expand_movmem (rtx dst, rtx src, rt
*** 12526,12531 ****
--- 12526,12533 ----
        rtx countreg2;
        rtx label = NULL;
        rtx srcmem, dstmem;
+       rtx hot_label = NULL;
+       rtx jump_around_label = NULL;
        int desired_alignment = (TARGET_PENTIUMPRO
  			       && (count == 0 || count >= (unsigned int) 260)
  			       ? 8 : UNITS_PER_WORD);
*************** ix86_expand_movmem (rtx dst, rtx src, rt
*** 12533,12546 ****
        dst = change_address (dst, BLKmode, destreg);
        src = change_address (src, BLKmode, srcreg);
  
        /* In case we don't know anything about the alignment, default to
           library version, since it is usually equally fast and result in
           shorter code.
  
  	 Also emit call when we know that the count is large and call overhead
  	 will not be important.  */
!       if (!TARGET_INLINE_ALL_STRINGOPS
! 	  && (align < UNITS_PER_WORD || !TARGET_REP_MOVL_OPTIMAL))
  	return 0;
  
        if (TARGET_SINGLE_STRINGOP)
--- 12535,12565 ----
        dst = change_address (dst, BLKmode, destreg);
        src = change_address (src, BLKmode, srcreg);
  
+       if (!TARGET_INLINE_STRINGOPS_DYNAMICALLY && count == 0)
+ 	{
+ 	  rtx i;
+ 	  hot_label = gen_label_rtx ();
+ 	  jump_around_label = gen_label_rtx ();
+ 	  emit_cmp_and_jump_insns (count_exp, GEN_INT (260 - 1),
+ 				   LEU, 0, counter_mode, 1, hot_label);
+ 	  i = get_last_insn ();
+ 	  gcc_assert (GET_CODE (i) == JUMP_INSN);
+ 	  REG_NOTES (i)
+ 	    = gen_rtx_EXPR_LIST (REG_BR_PROB,
+ 				 GEN_INT (REG_BR_PROB_BASE * 90 / 100),
+ 				 REG_NOTES (i));
+ 	  emit_block_move_via_libcall (dst, src, count_exp, false);
+ 	  emit_jump (jump_around_label);
+ 	  emit_label (hot_label);
+ 	}
        /* In case we don't know anything about the alignment, default to
           library version, since it is usually equally fast and result in
           shorter code.
  
  	 Also emit call when we know that the count is large and call overhead
  	 will not be important.  */
!       else if (!TARGET_INLINE_ALL_STRINGOPS
! 	       && (align < UNITS_PER_WORD || !TARGET_REP_MOVL_OPTIMAL))
  	return 0;
  
        if (TARGET_SINGLE_STRINGOP)
*************** ix86_expand_movmem (rtx dst, rtx src, rt
*** 12673,12678 ****
--- 12692,12699 ----
  	  emit_label (label);
  	  LABEL_NUSES (label) = 1;
  	}
+       if (jump_around_label)
+         emit_label (jump_around_label);
      }
  
    return 1;
*************** ix86_expand_clrmem (rtx dst, rtx count_e
*** 12823,12841 ****
      {
        rtx countreg2;
        rtx label = NULL;
        /* Compute desired alignment of the string operation.  */
        int desired_alignment = (TARGET_PENTIUMPRO
  			       && (count == 0 || count >= (unsigned int) 260)
  			       ? 8 : UNITS_PER_WORD);
  
        /* In case we don't know anything about the alignment, default to
           library version, since it is usually equally fast and result in
           shorter code.
  
  	 Also emit call when we know that the count is large and call overhead
  	 will not be important.  */
!       if (!TARGET_INLINE_ALL_STRINGOPS
! 	  && (align < UNITS_PER_WORD || !TARGET_REP_MOVL_OPTIMAL))
  	return 0;
  
        if (TARGET_SINGLE_STRINGOP)
--- 12844,12882 ----
      {
        rtx countreg2;
        rtx label = NULL;
+       rtx hot_label = NULL;
+       rtx jump_around_label = NULL;
        /* Compute desired alignment of the string operation.  */
        int desired_alignment = (TARGET_PENTIUMPRO
  			       && (count == 0 || count >= (unsigned int) 260)
  			       ? 8 : UNITS_PER_WORD);
  
+       if (!TARGET_INLINE_STRINGOPS_DYNAMICALLY && count == 0)
+ 	{
+ 	  rtx i;
+ 	  hot_label = gen_label_rtx ();
+ 	  jump_around_label = gen_label_rtx ();
+ 	  emit_cmp_and_jump_insns (count_exp, GEN_INT (260 - 1),
+ 				   LEU, 0, counter_mode, 1, hot_label);
+ 	  i = get_last_insn ();
+ 	  gcc_assert (GET_CODE (i) == JUMP_INSN);
+ 	  REG_NOTES (i)
+ 	    = gen_rtx_EXPR_LIST (REG_BR_PROB,
+ 				 GEN_INT (REG_BR_PROB_BASE * 90 / 100),
+ 				 REG_NOTES (i));
+ 	  clear_storage_via_libcall (dst, count_exp, false);
+ 	  emit_jump (jump_around_label);
+ 	  emit_label (hot_label);
+ 	}
        /* In case we don't know anything about the alignment, default to
           library version, since it is usually equally fast and result in
           shorter code.
  
  	 Also emit call when we know that the count is large and call overhead
  	 will not be important.  */
!       else if (!TARGET_INLINE_ALL_STRINGOPS
! 	       && (align < UNITS_PER_WORD || !TARGET_REP_MOVL_OPTIMAL)
! 	       && !count)
  	return 0;
  
        if (TARGET_SINGLE_STRINGOP)
*************** ix86_expand_clrmem (rtx dst, rtx count_e
*** 12945,12950 ****
--- 12986,12993 ----
  	  emit_label (label);
  	  LABEL_NUSES (label) = 1;
  	}
+       if (jump_around_label)
+         emit_label (jump_around_label);
      }
    return 1;
  }
Index: tree-ssanames.c
===================================================================
*** tree-ssanames.c	(revision 114491)
--- tree-ssanames.c	(working copy)
*************** Boston, MA 02110-1301, USA.  */
*** 57,69 ****
     We could also use a zone allocator for these objects since they have
     a very well defined lifetime.  If someone wants to experiment with that
     this is the place to try it.  */
-    
- /* Array of all SSA_NAMEs used in the function.  */
- VEC(tree,gc) *ssa_names;
- 
- /* Free list of SSA_NAMEs.  This list is wiped at the end of each function
-    after we leave SSA form.  */
- static GTY (()) tree free_ssanames;
  
  /* Version numbers with special meanings.  We start allocating new version
     numbers after the special ones.  */
--- 57,62 ----
*************** replace_ssa_name_symbol (tree ssa_name, 
*** 307,311 ****
    SSA_NAME_VAR (ssa_name) = sym;
    TREE_TYPE (ssa_name) = TREE_TYPE (sym);
  }
- 
- #include "gt-tree-ssanames.h"
--- 300,302 ----
Index: tree-ssa-operands.c
===================================================================
*** tree-ssa-operands.c	(revision 114491)
--- tree-ssa-operands.c	(working copy)
*************** static VEC(tree,heap) *build_vuses;
*** 117,134 ****
  static VEC(tree,heap) *build_v_must_defs;
  
  /* These arrays are the cached operand vectors for call clobbered calls.  */
- static bool ops_active = false;
- 
- static GTY (()) struct ssa_operand_memory_d *operand_memory = NULL;
- static unsigned operand_memory_index;
  
  static void get_expr_operands (tree, tree *, int);
  
- static def_optype_p free_defs = NULL;
- static use_optype_p free_uses = NULL;
- static vuse_optype_p free_vuses = NULL;
- static maydef_optype_p free_maydefs = NULL;
- static mustdef_optype_p free_mustdefs = NULL;
  
  /* Allocates operand OP of given TYPE from the appropriate free list,
     or of the new value if the list is empty.  */
--- 117,125 ----
*************** operand_build_sort_virtual (VEC(tree,hea
*** 212,218 ****
  bool
  ssa_operands_active (void)
  {
!   return ops_active;
  }
  
  
--- 203,209 ----
  bool
  ssa_operands_active (void)
  {
!   return cfun->ssa && cfun->ssa->ops_active;
  }
  
  
*************** init_ssa_operands (void)
*** 258,264 ****
  
    gcc_assert (operand_memory == NULL);
    operand_memory_index = SSA_OPERAND_MEMORY_SIZE;
!   ops_active = true;
    memset (&clobber_stats, 0, sizeof (clobber_stats));
  }
  
--- 249,255 ----
  
    gcc_assert (operand_memory == NULL);
    operand_memory_index = SSA_OPERAND_MEMORY_SIZE;
!   cfun->ssa->ops_active = true;
    memset (&clobber_stats, 0, sizeof (clobber_stats));
  }
  
*************** fini_ssa_operands (void)
*** 285,291 ****
        ggc_free (ptr);
      }
  
!   ops_active = false;
    
    if (dump_file && (dump_flags & TDF_STATS))
      {
--- 276,282 ----
        ggc_free (ptr);
      }
  
!   cfun->ssa->ops_active = false;
    
    if (dump_file && (dump_flags & TDF_STATS))
      {
*************** add_virtual_operand (tree var, stmt_ann_
*** 1238,1243 ****
--- 1229,1236 ----
        /* The variable is not aliased or it is an alias tag.  */
        if (flags & opf_is_def)
  	{
+ 	  if (s_ann && !aliases_computed_p && TREE_ADDRESSABLE (var))
+ 	    s_ann->has_volatile_ops = true;
  	  if (flags & opf_kill_def)
  	    {
  	      /* V_MUST_DEF for non-aliased, non-GIMPLE register 
*************** get_indirect_ref_operands (tree stmt, tr
*** 1441,1446 ****
--- 1434,1443 ----
  	  if (v_ann->symbol_mem_tag)
  	    add_virtual_operand (v_ann->symbol_mem_tag, s_ann, flags,
  				 full_ref, offset, size, false);
+ 	  /* Aliasing information is missing; mark statement as volatile so we
+ 	     won't optimize it out too actively.  */
+ 	  else if (s_ann && !aliases_computed_p && (flags & (opf_is_def | opf_kill_def)))
+ 	    s_ann->has_volatile_ops = true;
  	}
      }
    else if (TREE_CODE (ptr) == INTEGER_CST)
*************** add_call_clobber_ops (tree stmt, tree ca
*** 1547,1553 ****
    not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL; 
    not_written_b = callee ? ipa_reference_get_not_written_global (callee) : NULL; 
    /* Add a V_MAY_DEF operand for every call clobbered variable.  */
!   EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, u, bi)
      {
        tree var = referenced_var_lookup (u);
        unsigned int escape_mask = var_ann (var)->escape_mask;
--- 1544,1550 ----
    not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL; 
    not_written_b = callee ? ipa_reference_get_not_written_global (callee) : NULL; 
    /* Add a V_MAY_DEF operand for every call clobbered variable.  */
!   EXECUTE_IF_SET_IN_BITMAP (cfun->ssa->call_clobbered_vars, 0, u, bi)
      {
        tree var = referenced_var_lookup (u);
        unsigned int escape_mask = var_ann (var)->escape_mask;
*************** add_call_read_ops (tree stmt, tree calle
*** 1625,1631 ****
    not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL; 
  
    /* Add a VUSE for each call-clobbered variable.  */
!   EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, u, bi)
      {
        tree var = referenced_var (u);
        tree real_var = var;
--- 1622,1628 ----
    not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL; 
  
    /* Add a VUSE for each call-clobbered variable.  */
!   EXECUTE_IF_SET_IN_BITMAP (cfun->ssa->call_clobbered_vars, 0, u, bi)
      {
        tree var = referenced_var (u);
        tree real_var = var;
*************** get_call_expr_operands (tree stmt, tree 
*** 1672,1678 ****
       we avoid adding superfluous virtual operands, which can be a
       significant compile time sink (See PR 15855).  */
    if (aliases_computed_p
!       && !bitmap_empty_p (call_clobbered_vars)
        && !(call_flags & ECF_NOVOPS))
      {
        /* A 'pure' or a 'const' function never call-clobbers anything. 
--- 1669,1675 ----
       we avoid adding superfluous virtual operands, which can be a
       significant compile time sink (See PR 15855).  */
    if (aliases_computed_p
!       && !bitmap_empty_p (cfun->ssa->call_clobbered_vars)
        && !(call_flags & ECF_NOVOPS))
      {
        /* A 'pure' or a 'const' function never call-clobbers anything. 
*************** get_asm_expr_operands (tree stmt)
*** 1762,1775 ****
  	if (global_var)
  	  add_stmt_operand (&global_var, s_ann, opf_is_def);
  	else
! 	  EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
  	    {
  	      tree var = referenced_var (i);
  	      add_stmt_operand (&var, s_ann, opf_is_def | opf_non_specific);
  	    }
  
  	/* Now clobber all addressables.  */
! 	EXECUTE_IF_SET_IN_BITMAP (addressable_vars, 0, i, bi)
  	    {
  	      tree var = referenced_var (i);
  
--- 1759,1772 ----
  	if (global_var)
  	  add_stmt_operand (&global_var, s_ann, opf_is_def);
  	else
! 	  EXECUTE_IF_SET_IN_BITMAP (cfun->ssa->call_clobbered_vars, 0, i, bi)
  	    {
  	      tree var = referenced_var (i);
  	      add_stmt_operand (&var, s_ann, opf_is_def | opf_non_specific);
  	    }
  
  	/* Now clobber all addressables.  */
! 	EXECUTE_IF_SET_IN_BITMAP (cfun->ssa->addressable_vars, 0, i, bi)
  	    {
  	      tree var = referenced_var (i);
  
*************** debug_immediate_uses_for (tree var)
*** 2560,2564 ****
  {
    dump_immediate_uses_for (stderr, var);
  }
- 
- #include "gt-tree-ssa-operands.h"
--- 2557,2559 ----



More information about the Gcc-patches mailing list