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 to tree-profiling branch to do escape type analysis.


Tested on darwin. There are 4 new regressions with this patch. All of them are instances of a known problem with the vectorizer that this patch happens to tickle.

These are gcc.dg/vect/vect-56.c, gcc.dg/vect/vect-60.c, gcc.dg/vect/vect-77.c, gcc.dg/vect/vect78-.c

Kenny

2005-01-18 Kenneth Zadeck <zadeck@naturalbridge.com>
* alias.c: Fixed header comment.
* c-common.c: (handle_free_attribure)
new function to handle "free" attribute.
* c=decl.c (merge_decls): process "free" attribute.
* calls.c (flags_from_decl_or_type): process "free" attribute.
* ipa-static-vars-anal.c (unique_type_id_for,
ipa_static_star_count_of_interesting_type, ipa_static_type_contained_p,
ipa_static_address_not_taken_of_field, mark_any_type_seen, mark_type_seen,
mark_type, mark_interesting_type, parent_type_p, count_stars, check_cast_type,
check_cast, check_function_parameter_and_return_types,
mark_interesting_addressof, type_for_uid, subtype_map_for_uid,
close_type_seen, compare_type_brand, get_name_of_type, discover_unique_type
close_type_exposed_parameter, close_type_full_escape, delete_addressof_map,
close_addressof, do_type_analysis, ): new function for type escape analysis.
* ipa-static-vars-anal.c (check_operand, check_tree, look_for_address_of,
check_call, scan_for_static_refs, ipa_init, analyze_function,
static_execute): fixed to perform type escape analysis.
* ipa-static-vars-anal.c (convert_UIDs_in_bitmap, propagate_bits): fixed typo.
* ipa-static-vars-anal.c (searchc_env): added missing cast.
* ipa-static-vars-anal.c (get_base_var): moved from tree-gimple.c.
* ipa-static-vars-anal.c (check_call): renamed from
process_call_for_static_vars.
* ipa-static-vars-anal.c (analyze_variable): added debugging.
* ipa-static-vars-anal.c (static_execute): removed debugging.
* tree-dfa.c (create_stmt_ann) fixed typo.
* tree.c (build4_stat) fixed typo.
* tree-inline-flow.h: fixed typo.
* tree-ssa-alias.c (may_alias_p): improvements to aliasing based on type
escape analysis.
* tree.h: added free attribute.


2005-01-18 Daniel Berlin <dberlin@dberlin.org> (committed by Kenneth Zadeck <zadeck@naturalbridge.com>)

   * c-typeck.c (build_array_ref): Build a MEM_REF instead of
   an indirect_ref if we can.
   (build_unary_op): Drop MEM_REF to pointer addition when you
   take the address of it.
   (lvalue_p): MEM_REF is the same as INDIRECT_REF here.
   * emit-rtl.c (set_mem_attributes_minus_bitpos):
   Handle MEM_REF.
   * expr.c (expand_expr_real_1): Abort if we try to expand a MEM_REF.
   * gimple-low.c (lower_memref): New function.
   (lower_memrefs): Ditto.
   (pass_lower_memref): Ditto.
   * gimplify.c (gimplify_expr): Add gimplification of MEM_REF.
   (check_pointer_types_r): Add MEM_REF.
   * tree-eh.c (tree_could_trap_p): MEM_REF is like INDIRECT_REF here.
   * tree-gimple.c (is_gimple_addressable): Add MEM_REF.
   (is_gimple_min_lval): Ditto.
   (get_base_address): Handle MEM_REF.
   * tree-inline.c (estimate_num_insns_1): Ditto.
   * tree-optimize.c: Add memref lowering passes
   * tree-pass.h: Add pass_lower_memref.
   * tree-pretty-print.c (dump_generic_node): Print out MEM_REF.
   * tree-ssa-alias.c (find_ptr_dereference): Add MEM_REF handling.
   * tree-ssa-loop-im.c (for_each_index): Ditto.
   * tree-ssa-operands.c (get_mem_ref_operands): New function.
   (build_ssa_operands): Add MEM_REF.
   (get_expr_operands): Use get_mem_ref_operands.
   * tree-ssa-pre (is_copy_stmt, follow_copies_till_vuse, do_eustores,
   gate_eustores): new function to eliminate useless stores.

? gcc/aliasingcomment.txt
? gcc/makefile.promote
? gcc/notes
? gcc/static2.diff
Index: gcc/ChangeLog.profiling
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/ChangeLog.profiling,v
retrieving revision 1.1.2.104
diff -c -3 -p -r1.1.2.104 ChangeLog.profiling
*** gcc/ChangeLog.profiling	18 Jan 2005 18:24:18 -0000	1.1.2.104
--- gcc/ChangeLog.profiling	18 Jan 2005 18:44:46 -0000
***************
*** 1,3 ****
--- 1,32 ----
+ 2005-01-18  Daniel Berlin  <dberlin@dberlin.org> (committed by Kenneth Zadeck <zadeck@naturalbridge.com>)
+ 
+ 	* c-typeck.c (build_array_ref): Build a MEM_REF instead of
+ 	an indirect_ref if we can.
+ 	(build_unary_op): Drop MEM_REF to pointer addition when you
+ 	take the address of it.
+ 	(lvalue_p): MEM_REF is the same as INDIRECT_REF here.
+ 	* emit-rtl.c (set_mem_attributes_minus_bitpos):
+ 	Handle MEM_REF.
+ 	* expr.c (expand_expr_real_1): Abort if we try to expand a MEM_REF.
+ 	* gimple-low.c (lower_memref): New function.
+ 	(lower_memrefs): Ditto.
+ 	(pass_lower_memref): Ditto.
+ 	* gimplify.c (gimplify_expr): Add gimplification of MEM_REF.
+ 	(check_pointer_types_r): Add MEM_REF.
+ 	* tree-eh.c (tree_could_trap_p): MEM_REF is like INDIRECT_REF here.
+ 	* tree-gimple.c (is_gimple_addressable): Add MEM_REF.
+ 	(is_gimple_min_lval): Ditto.
+ 	(get_base_address): Handle MEM_REF.
+ 	* tree-inline.c (estimate_num_insns_1): Ditto.
+ 	* tree-optimize.c: Add memref lowering passes
+ 	* tree-pass.h: Add pass_lower_memref.
+ 	* tree-pretty-print.c (dump_generic_node): Print out MEM_REF.
+ 	* tree-ssa-alias.c (find_ptr_dereference): Add MEM_REF handling.
+ 	* tree-ssa-loop-im.c (for_each_index): Ditto.
+ 	* tree-ssa-operands.c (get_mem_ref_operands): New function.
+ 	(build_ssa_operands): Add MEM_REF.
+ 	(get_expr_operands): Use get_mem_ref_operands. 
+ 
  2005-01-18  Jan Hubicka  <jh@suse.cz> (committed by Kenneth Zadeck <zadeck@naturalbridge.com>)
  	* cgraphunit.c (cgraph_optimize): fixed improperly initialized bitmap obstack.
  	* tree-optimize.c (tree_lowering_passes, tree_early_local_passes): 
Index: gcc/Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.179.2.32
diff -c -3 -p -r1.903.2.179.2.32 Makefile.in
*** gcc/Makefile.in	9 Jan 2005 14:16:26 -0000	1.903.2.179.2.32
--- gcc/Makefile.in	18 Jan 2005 18:44:48 -0000
*************** gimplify.o : gimplify.c $(CONFIG_H) $(SY
*** 1757,1763 ****
  gimple-low.o : gimple-low.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
     diagnostic.h $(TREE_GIMPLE_H) tree-inline.h varray.h langhooks.h \
     langhooks-def.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h except.h \
!    $(FLAGS_H) $(RTL_H) function.h $(EXPR_H) tree-pass.h
  tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
     $(TREE_H) errors.h tree-inline.h diagnostic.h $(HASHTAB_H) \
     $(TM_H) coretypes.h
--- 1757,1763 ----
  gimple-low.o : gimple-low.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
     diagnostic.h $(TREE_GIMPLE_H) tree-inline.h varray.h langhooks.h \
     langhooks-def.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h except.h \
!    $(FLAGS_H) $(RTL_H) function.h $(EXPR_H) tree-pass.h pointer-set.h
  tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
     $(TREE_H) errors.h tree-inline.h diagnostic.h $(HASHTAB_H) \
     $(TM_H) coretypes.h
*************** ipa_prop.o : ipa_prop.c $(CONFIG_H) $(SY
*** 1935,1941 ****
  ipa-static-vars-anal.o : ipa-static-vars-anal.c $(CONFIG_H) $(SYSTEM_H) \
     coretypes.h $(TM_H) $(TREE_H) $(TREE_FLOW_H) tree-inline.h langhooks.h \
     pointer-set.h $(GGC_H) $(IPA_STATIC_H) $(C_COMMON_H) $(TREE_GIMPLE_H) \
!    $(CGRAPH_H) output.h $(FLAGS_H) tree-pass.h  
  ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) 
  ipa-inline.o : ipa-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h tree-inline.h $(FLAGS_H) $(CGRAPH_H) intl.h $(TREE_FLOW_H) \
--- 1935,1941 ----
  ipa-static-vars-anal.o : ipa-static-vars-anal.c $(CONFIG_H) $(SYSTEM_H) \
     coretypes.h $(TM_H) $(TREE_H) $(TREE_FLOW_H) tree-inline.h langhooks.h \
     pointer-set.h $(GGC_H) $(IPA_STATIC_H) $(C_COMMON_H) $(TREE_GIMPLE_H) \
!    $(CGRAPH_H) output.h $(FLAGS_H) tree-pass.h $(DIAGNOSTIC_H)  
  ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) 
  ipa-inline.o : ipa-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h tree-inline.h $(FLAGS_H) $(CGRAPH_H) intl.h $(TREE_FLOW_H) \
*************** reorg.o : reorg.c $(CONFIG_H) $(SYSTEM_H
*** 2124,2130 ****
  alias.o : alias.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \
     hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) toplev.h output.h $(ALIAS_H) $(EMIT_RTL_H) \
     $(GGC_H) function.h cselib.h $(TREE_H) $(TM_P_H) langhooks.h $(TARGET_H) \
!    gt-alias.h $(TIMEVAR_H) $(CGRAPH_H)
  regmove.o : regmove.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) insn-config.h \
     $(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) function.h \
     $(EXPR_H) $(BASIC_BLOCK_H) toplev.h $(TM_P_H) except.h reload.h
--- 2124,2130 ----
  alias.o : alias.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \
     hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) toplev.h output.h $(ALIAS_H) $(EMIT_RTL_H) \
     $(GGC_H) function.h cselib.h $(TREE_H) $(TM_P_H) langhooks.h $(TARGET_H) \
!    gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) ipa-static.h
  regmove.o : regmove.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) insn-config.h \
     $(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) function.h \
     $(EXPR_H) $(BASIC_BLOCK_H) toplev.h $(TM_P_H) except.h reload.h
Index: gcc/alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/alias.c,v
retrieving revision 1.176.2.21.2.14
diff -c -3 -p -r1.176.2.21.2.14 alias.c
*** gcc/alias.c	15 Dec 2004 22:17:26 -0000	1.176.2.21.2.14
--- gcc/alias.c	18 Jan 2005 18:44:48 -0000
*************** Software Foundation, 59 Temple Place - S
*** 45,50 ****
--- 45,96 ----
  #include "cgraph.h"
  #include "varray.h"
  
+ /* The aliasing api provided here solves related but different problems:
+ 
+    Say there exists (in c) 
+ 
+    struct X {
+      struct Y y1;
+      struct Z z2;
+    } x1, *px1,  *px2;
+ 
+    struct Y y2, *py;
+    struct Z z2, *pz;
+ 
+ 
+    py = &px1.y1;
+ 
+    Consider the four questions:
+ 
+    can a store to x1 interfere with px2->y2?
+    can a store to x1 interfere with px2->z2?
+    can a store to x1 change the value pointed to by with py?
+    can a store to x1 change the value pointed to by with pz?
+ 
+    the answer to these questions can be yes, yes, yes, no
+ 
+    The first two questions can be answered with a simple examination
+    of the type system.  If structure X contains a field of type Y then
+    a store thru a pointer to an X can overwrite any field that is
+    contained (recursively) in an X (unless we know that px1 != px2).
+ 
+    The last two of the questions can be solved in the same way as the
+    first two questions but this is too conservative.  The observation
+    is that if the address of a field is not explicitly taken and the
+    type is completely local to the compilation unit, then it is
+    impossible that a pointer to an instance of the field type overlaps
+    with an enclosing structure.
+ 
+    Historically in GCC, these two problems were combined and a single
+    data structure was used to represent the solution to these
+    problems.  We now have two similar but different data structures,
+    The data structure to solve the last two question is similar to the
+    first, but does not contain have the fields in it whose address are
+    never taken.  For types that do escape the compilation unit, the
+    data structures will have identical information.
+ 
+ */
+ 
  /* The alias sets assigned to MEMs assist the back-end in determining
     which MEMs can alias which other MEMs.  In general, two MEMs in
     different alias sets cannot alias each other, with one important
Index: gcc/c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.344.2.61.2.16
diff -c -3 -p -r1.344.2.61.2.16 c-common.c
*** gcc/c-common.c	9 Jan 2005 14:16:34 -0000	1.344.2.61.2.16
--- gcc/c-common.c	18 Jan 2005 18:44:50 -0000
*************** static tree handle_tls_model_attribute (
*** 546,551 ****
--- 546,552 ----
  static tree handle_no_instrument_function_attribute (tree *, tree,
  						     tree, int, bool *);
  static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+ static tree handle_free_attribute (tree *, tree, tree, int, bool *);
  static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
  					     bool *);
  static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
*************** const struct attribute_spec c_common_att
*** 614,619 ****
--- 615,622 ----
  			      handle_alias_attribute },
    { "no_instrument_function", 0, 0, true,  false, false,
  			      handle_no_instrument_function_attribute },
+   { "free",                   0, 0, true,  false, false,
+ 			      handle_free_attribute },
    { "malloc",                 0, 0, true,  false, false,
  			      handle_malloc_attribute },
    { "no_stack_limit",         0, 0, true,  false, false,
*************** handle_malloc_attribute (tree *node, tre
*** 4750,4755 ****
--- 4753,4777 ----
    return NULL_TREE;
  }
  
+ /* Handle a "free" attribute; arguments as in
+    struct attribute_spec.handler.  */
+ 
+ static tree
+ handle_free_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ 			 int ARG_UNUSED (flags), bool *no_add_attrs)
+ {
+   if (TREE_CODE (*node) == FUNCTION_DECL)
+     DECL_IS_FREE (*node) = 1;
+   /* ??? TODO: Support types.  */
+   else
+     {
+       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+       *no_add_attrs = true;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
  /* Handle a "no_limit_stack" attribute; arguments as in
     struct attribute_spec.handler.  */
  
Index: gcc/c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.334.2.80.2.19
diff -c -3 -p -r1.334.2.80.2.19 c-decl.c
*** gcc/c-decl.c	9 Jan 2005 14:16:38 -0000	1.334.2.80.2.19
--- gcc/c-decl.c	18 Jan 2005 18:44:52 -0000
*************** merge_decls (tree newdecl, tree olddecl,
*** 1677,1682 ****
--- 1677,1683 ----
        TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
        TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
        DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
+       DECL_IS_FREE (newdecl) |= DECL_IS_FREE (olddecl);
        DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
      }
  
Index: gcc/c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.196.2.39.2.15
diff -c -3 -p -r1.196.2.39.2.15 c-typeck.c
*** gcc/c-typeck.c	9 Jan 2005 14:16:46 -0000	1.196.2.39.2.15
--- gcc/c-typeck.c	18 Jan 2005 18:44:54 -0000
***************
*** 1,6 ****
  /* Build expressions with type checking for C compiler.
!    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
!    1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
  
  This file is part of GCC.
  
--- 1,6 ----
  /* Build expressions with type checking for C compiler.
!    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
!    1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
  
  This file is part of GCC.
  
*************** build_array_ref (tree array, tree index)
*** 1769,1777 ****
  	  else if (!flag_isoc99 && !lvalue_p (foo))
  	    pedwarn ("ISO C90 forbids subscripting non-lvalue array");
  	}
! 
        type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
        rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
        /* Array ref is const/volatile if the array elements are
           or if the array is.  */
        TREE_READONLY (rval)
--- 1769,1779 ----
  	  else if (!flag_isoc99 && !lvalue_p (foo))
  	    pedwarn ("ISO C90 forbids subscripting non-lvalue array");
  	}
!       
        type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
        rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
+ 
+ 
        /* Array ref is const/volatile if the array elements are
           or if the array is.  */
        TREE_READONLY (rval)
*************** build_array_ref (tree array, tree index)
*** 1792,1806 ****
    else
      {
        tree ar = default_conversion (array);
! 
        if (ar == error_mark_node)
  	return ar;
  
        gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
        gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
  
!       return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0),
! 				 "array indexing");
      }
  }
  
--- 1794,1826 ----
    else
      {
        tree ar = default_conversion (array);
!       tree type;
!       tree res;
        if (ar == error_mark_node)
  	return ar;
  
        gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
        gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
+       type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (ar)));
  
!       /* If this type has no size, either we're screwed or we've issued an
! 	 error, so it doesn't matter if we build a MEM_REF here or not.  */
!       if (TYPE_SIZE_UNIT (type) 
! 	  && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST)
!         {
! 	  res = build2 (MEM_REF, type, ar, index);
! 	  TREE_READONLY (res) = TYPE_READONLY (TREE_TYPE (TREE_TYPE (ar)));
! 	  TREE_SIDE_EFFECTS (res)
! 	    |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (ar)))
! 		| TREE_SIDE_EFFECTS (ar));
! 	  TREE_THIS_VOLATILE (res)
! 	    |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (ar)))
! 		| TREE_THIS_VOLATILE (ar));
! 	  return res;
! 	 }
!       else
! 	return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0),
! 				   "array indexing"); 
      }
  }
  
*************** build_unary_op (enum tree_code code, tre
*** 2715,2721 ****
  	  return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
  				  TREE_OPERAND (arg, 1), 1);
  	}
! 
        /* Anything not already handled and not a true memory reference
  	 or a non-lvalue array is an error.  */
        else if (typecode != FUNCTION_TYPE && !flag
--- 2735,2750 ----
  	  return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
  				  TREE_OPERAND (arg, 1), 1);
  	}
!       /* Same for the equivalent MEM_REF */
!       if (TREE_CODE (arg) == MEM_REF)
! 	{
! 	  if (!c_mark_addressable (MEM_REF_SYMBOL (arg)))
! 	    return error_mark_node;
! 	  return build_binary_op (PLUS_EXPR, 
! 				  MEM_REF_SYMBOL (arg),
! 				  MEM_REF_INDEX (arg), 1);
! 	}
! 							      
        /* Anything not already handled and not a true memory reference
  	 or a non-lvalue array is an error.  */
        else if (typecode != FUNCTION_TYPE && !flag
*************** lvalue_p (tree ref)
*** 2792,2797 ****
--- 2821,2827 ----
      case VAR_DECL:
      case PARM_DECL:
      case RESULT_DECL:
+     case MEM_REF:
      case ERROR_MARK:
        return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
  	      && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE);
Index: gcc/calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.229.2.42.2.15
diff -c -3 -p -r1.229.2.42.2.15 calls.c
*** gcc/calls.c	9 Jan 2005 14:16:48 -0000	1.229.2.42.2.15
--- gcc/calls.c	18 Jan 2005 18:44:55 -0000
*************** flags_from_decl_or_type (tree exp)
*** 578,583 ****
--- 578,587 ----
        if (DECL_IS_MALLOC (exp))
  	flags |= ECF_MALLOC;
  
+       /* The function exp may have the `free' attribute.  */
+       if (DECL_IS_FREE (exp))
+ 	flags |= ECF_FREE;
+ 
        /* The function exp may have the `pure' attribute.  */
        if (DECL_IS_PURE (exp))
  	flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
Index: gcc/emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.280.2.29.2.17
diff -c -3 -p -r1.280.2.29.2.17 emit-rtl.c
*** gcc/emit-rtl.c	9 Jan 2005 14:17:09 -0000	1.280.2.29.2.17
--- gcc/emit-rtl.c	18 Jan 2005 18:44:57 -0000
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1509,1514 ****
--- 1509,1515 ----
       this is an INDIRECT_REF, or if TYPE_ALIGN_OK.  */
    if (objectp || TREE_CODE (t) == INDIRECT_REF 
        || TREE_CODE (t) == ALIGN_INDIRECT_REF 
+       || TREE_CODE (t) == MEM_REF
        || TYPE_ALIGN_OK (type))
      align = MAX (align, TYPE_ALIGN (type));
    else 
Index: gcc/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.467.2.76.2.21
diff -c -3 -p -r1.467.2.76.2.21 expr.c
*** gcc/expr.c	9 Jan 2005 14:17:10 -0000	1.467.2.76.2.21
--- gcc/expr.c	18 Jan 2005 18:44:59 -0000
*************** get_inner_reference (tree exp, HOST_WIDE
*** 5346,5352 ****
  	    /* ??? Right now we don't do anything with DECL_OFFSET_ALIGN.  */
  	  }
  	  break;
- 
  	case ARRAY_REF:
  	case ARRAY_RANGE_REF:
  	  {
--- 5346,5351 ----
*************** expand_expr_real_1 (tree exp, rtx target
*** 6783,6789 ****
  
  	return temp;
        }
! 
      case ARRAY_REF:
  
        {
--- 6782,6789 ----
  
  	return temp;
        }
!     case MEM_REF:
!       gcc_unreachable ();
      case ARRAY_REF:
  
        {
Index: gcc/gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimple-low.c,v
retrieving revision 1.1.4.17.2.12
diff -c -3 -p -r1.1.4.17.2.12 gimple-low.c
*** gcc/gimple-low.c	9 Jan 2005 14:17:24 -0000	1.1.4.17.2.12
--- gcc/gimple-low.c	18 Jan 2005 18:44:59 -0000
*************** Software Foundation, 59 Temple Place - S
*** 41,47 ****
  #include "expr.h"
  #include "toplev.h"
  #include "tree-pass.h"
! 
  struct lower_data
  {
    /* Block the current statement belongs to.  */
--- 41,47 ----
  #include "expr.h"
  #include "toplev.h"
  #include "tree-pass.h"
! #include "pointer-set.h"
  struct lower_data
  {
    /* Block the current statement belongs to.  */
*************** struct tree_opt_pass pass_mark_used_bloc
*** 606,608 ****
--- 606,693 ----
    TODO_dump_func,			/* todo_flags_finish */
    0					/* letter */
  };
+ 
+ /* Lower a MEM_REF tree to it's equivalent INDIRECT_REF form.  TP is a
+    pointer to the tree we are currently walking, and DATA is a pointer
+    to it's block_stmt_iterator, used for inserting whatever
+    expressions are necessary to create GIMPLE from it.  */ 
+ 
+ static tree
+ lower_memref (tree *tp,
+ 	      int *walk_subtrees ATTRIBUTE_UNUSED,
+ 	      void *data)
+ {
+   block_stmt_iterator *bsip = (block_stmt_iterator *)data;
+   if (TREE_CODE (*tp) == MEM_REF)
+     {
+       tree indirect;
+       tree stmts;
+       tree with;
+       with = build2 (MULT_EXPR, TREE_TYPE (MEM_REF_INDEX (*tp)),
+ 		     MEM_REF_INDEX (*tp),
+ 		     size_in_bytes (TREE_TYPE (TREE_TYPE (MEM_REF_SYMBOL (*tp)))));
+       with = fold_convert (TREE_TYPE (MEM_REF_SYMBOL (*tp)), with);      
+       with = build2 (PLUS_EXPR, TREE_TYPE (MEM_REF_SYMBOL (*tp)),
+ 		     MEM_REF_SYMBOL (*tp), with);
+       
+ 
+       with = force_gimple_operand (with, &stmts, false, NULL_TREE);
+       if (stmts)
+ 	bsi_insert_before (bsip, stmts, BSI_SAME_STMT);
+       
+       indirect = build1 (INDIRECT_REF, TREE_TYPE (*tp), with);
+       TREE_READONLY (indirect) = TREE_READONLY (*tp);
+       TREE_SIDE_EFFECTS (indirect) = TREE_SIDE_EFFECTS (*tp);
+       TREE_THIS_VOLATILE (indirect) = TREE_THIS_VOLATILE (*tp);
+       
+       indirect = force_gimple_operand (indirect, &stmts, false, NULL_TREE);
+       if (stmts)
+ 	bsi_insert_before (bsip, stmts, BSI_SAME_STMT);
+       *tp = indirect;
+     }
+   return NULL_TREE;
+ }
+       
+ /* Convert MEM_REF trees into their equivalent INDIRECT_REF form
+    across the entire function.  MEM_REF (symbol, index) = INDIRECT_REF
+    (symbol + (index * size in bytes of the type symbol points to))  */
+ 
+ static void
+ lower_memrefs (void)
+ {
+   struct pointer_set_t *visited_nodes;
+   basic_block bb;
+   FOR_ALL_BB (bb)
+     {
+       block_stmt_iterator bsi;
+       for (bsi = bsi_start (bb);
+ 	   !bsi_end_p (bsi);
+ 	   bsi_next (&bsi))
+       {
+ 	tree stmt = bsi_stmt (bsi);
+ 	visited_nodes = pointer_set_create ();
+ 	walk_tree (&stmt,  lower_memref, (void *)&bsi, visited_nodes);
+ 	pointer_set_destroy (visited_nodes);
+ 		   
+       }
+     }
+ }
+ struct tree_opt_pass pass_lower_memref = 
+ {
+   "memrefs",				/* name */
+   NULL,					/* gate */
+   NULL, NULL,				/* IPA analysis */
+   lower_memrefs,			/* execute */
+   NULL, NULL,				/* IPA analysis */
+   NULL,					/* sub */
+   NULL,					/* next */
+   0,					/* static_pass_number */
+   0,					/* tv_id */
+   0,					/* properties_required */
+   0,					/* properties_provided */
+   0,					/* properties_destroyed */
+   0,					/* todo_flags_start */
+   TODO_dump_func,			/* todo_flags_finish */
+   0					/* letter */
+ };
+ 
Index: gcc/gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 1.1.2.141.2.17
diff -c -3 -p -r1.1.2.141.2.17 gimplify.c
*** gcc/gimplify.c	9 Jan 2005 14:17:24 -0000	1.1.2.141.2.17
--- gcc/gimplify.c	18 Jan 2005 18:45:01 -0000
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 3765,3771 ****
  			       is_gimple_val, fb_rvalue);
  	  recalculate_side_effects (*expr_p);
  	  break;
! 
  	case ALIGN_INDIRECT_REF:
  	case MISALIGNED_INDIRECT_REF:
  	case INDIRECT_REF:
--- 3765,3782 ----
  			       is_gimple_val, fb_rvalue);
  	  recalculate_side_effects (*expr_p);
  	  break;
! 	case MEM_REF:
! 	  {
!  	    enum gimplify_status r0, r1;
! 	    
! 	    r0 = gimplify_expr (&MEM_REF_SYMBOL (*expr_p), pre_p, post_p,
! 				is_gimple_reg, fb_rvalue);
! 	    r1 = gimplify_expr (&MEM_REF_INDEX (*expr_p), pre_p, post_p,
! 				is_gimple_reg, fb_rvalue);
! 	    recalculate_side_effects (*expr_p);	 
! 	    ret = MIN (r0, r1);
! 	  }
! 	  break;
  	case ALIGN_INDIRECT_REF:
  	case MISALIGNED_INDIRECT_REF:
  	case INDIRECT_REF:
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 3826,3832 ****
  	    ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p,
  				 NULL, is_gimple_val, fb_rvalue);
  	  break;
- 
  	case LABEL_EXPR:
  	  ret = GS_ALL_DONE;
  	  gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
--- 3837,3842 ----
*************** check_pointer_types_r (tree *tp, int *wa
*** 4347,4352 ****
--- 4357,4363 ----
    switch (TREE_CODE (t))
      {
      case INDIRECT_REF:
+     case MEM_REF:
      case ARRAY_REF:
        otype = TREE_TYPE (t);
        ptype = TREE_TYPE (TREE_OPERAND (t, 0));
Index: gcc/ipa-static-vars-anal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/ipa-static-vars-anal.c,v
retrieving revision 1.1.2.6
diff -c -3 -p -r1.1.2.6 ipa-static-vars-anal.c
*** gcc/ipa-static-vars-anal.c	19 Dec 2004 19:11:09 -0000	1.1.2.6
--- gcc/ipa-static-vars-anal.c	18 Jan 2005 18:45:01 -0000
*************** Software Foundation, 59 Temple Place - S
*** 69,74 ****
--- 69,76 ----
  #include "output.h"
  #include "flags.h"
  #include "timevar.h"
+ #include "diagnostic.h"
+ #include "langhooks.h"
  
  /* FIXME -- PROFILE-RESTRUCTURE: change comment from DECL_UID to var-ann. */    
  /* This splay tree contains all of the static variables that are
*************** static bitmap module_statics_written;
*** 95,100 ****
--- 97,161 ----
     code is found that clobbers all memory. */
  static bitmap all_module_statics;
  
+ /* This bitmap contains the set of local vars that are the lhs of
+    calls to mallocs.  These variables, when seen on the rhs as part of
+    a cast, the cast are not marked as doing bad things to the type
+    even though they are generally of the form 
+    "foo = (type_of_foo)void_temp". */
+ static bitmap results_of_malloc;
+ 
+ /* Scratch bitmap for avoiding work. */
+ static bitmap been_there_done_that;
+ 
+ /* There are two levels of escape that types can undergo.
+ 
+    EXPOSED_PARAMETER - some instance of the variable is
+    passed by value into an externally visible function or some
+    instance of the variable is passed out of an externally visible
+    function as a return value.  In this case any of the fields of the
+    variable that are pointer types end up having their types marked as
+    FULL_ESCAPE.
+ 
+    FULL_ESCAPE - when bad things happen to good types. One of the
+    following things happens to the type: (a) either an instance of the
+    variable has it's address passed to an externally visible function,
+    (b) the address is taken and some bad cast happens to the address
+    or (c) explicit arithmetic is done to the address.
+ */
+ 
+ enum escape_t
+ {
+   EXPOSED_PARAMETER,
+   FULL_ESCAPE
+ };
+ 
+ /* The following two bit vectors global_types_* correspond to
+    previous cases above.  During the analysis phase, a bit is set in
+    one of these vectors if an operation of the offending class is
+    discovered to happen on the associated type.  */
+  
+ static bitmap global_types_exposed_parameter;
+ static bitmap global_types_full_escape;
+ 
+ /* All of the types seen in this compilation unit. */
+ static bitmap global_types_seen;
+ static splay_tree uid_to_type;
+ 
+ /* Map the several instances of a type into a single instance.  These
+    can arise in several ways, nono of which can be justified except by
+    laziness and stupidity.  */
+ static splay_tree uid_to_unique_type;
+ static splay_tree all_unique_types;
+ 
+ /* A splay tree of bitmaps.  An element X in the splay tree has a bit
+    set in its bitmap at TYPE_UID (TYPE_MAIN_VARIANT (Y) if there was
+    an operation in the program of the form "&X.Y".  */
+ static splay_tree uid_to_addressof_map;
+ 
+ /* Tree to hold the subtype maps used to mark subtypes of escaped
+    types.  */
+ static splay_tree uid_to_subtype_map;
+ 
  /* Records tree nodes seen in cgraph_create_edges.  Simply using
     walk_tree_without_duplicates doesn't guarantee each node is visited
     once because it gets a new htab upon each recursive call from
*************** print_order (FILE* out, 
*** 134,139 ****
--- 195,230 ----
    fflush(out);
  }
  
+ /* All of the "unique_type" code is a hack to get around the sleezy
+    implementation used to compile more than file.  If the same type is
+    declared in several files, multiple types will appear that are the
+    same.  The code in this unit chooses one "unique" instance of that
+    type as the representative and has all of the others point to
+    it.  */
+ 
+ /* Find the unique representative for a type with UID.  */  
+ static int
+ unique_type_id_for (int uid)
+ {
+   splay_tree_node result = 
+     splay_tree_lookup(uid_to_unique_type, (splay_tree_key) uid);
+ 
+   if (result)
+     return TYPE_UID((tree) result->value);
+   else 
+     {
+       abort();
+       return uid;
+     }
+ }
+ 
+ /* Return true if the type with UID is the unique representative.  */
+ static bool 
+ unique_type_id_p (int uid)
+ {
+   return uid == unique_type_id_for (uid);
+ }
+ 
  /* FIXME -- PROFILE-RESTRUCTURE: Remove this function, it becomes a nop. */    
  /* Convert IN_DECL bitmap which is indexed by DECL_UID to IN_ANN, a
     bitmap indexed by var_ann (VAR_DECL)->uid.  */
*************** convert_UIDs_in_bitmap (bitmap in_ann, b
*** 153,159 ****
  	  tree t = (tree)n->value;
  	  var_ann_t va = var_ann (t);
  	  if (va) 
! 	    bitmap_set_bit(in_ann, va->uid);
  	}
      }
  }
--- 244,250 ----
  	  tree t = (tree)n->value;
  	  var_ann_t va = var_ann (t);
  	  if (va) 
! 	    bitmap_set_bit (in_ann, va->uid);
  	}
      }
  }
*************** ipa_get_statics_not_written_global (tree
*** 354,359 ****
--- 445,542 ----
      return NULL;
  }
  
+ /* Return 0 if TYPE is a record or union type.  Return a positive
+    number if TYPE is a pointer to a record or union.  The number is
+    the number of pointer types stripped to get to the record or union
+    type.  Return -1 if TYPE is none of the above.  */
+  
+ int
+ ipa_static_star_count_of_interesting_type (tree type) 
+ {
+   int count = 0;
+   /* Strip the *'s off.  */
+   while (POINTER_TYPE_P (type))
+     {
+       type = TREE_TYPE (type);
+       count++;
+     }
+ 
+   /* We are interested in records, and unions only.  */
+   if (TREE_CODE (type) == RECORD_TYPE 
+       || TREE_CODE (type) == QUAL_UNION_TYPE 
+       || TREE_CODE (type) == UNION_TYPE)
+     return count;
+   else 
+     return -1;
+ } 
+  
+ /* Return true if the record, or union TYPE passed in escapes this
+    compilation unit.  */
+ 
+ bool
+ ipa_static_type_contained_p (tree type)
+ {
+   int uid;
+ 
+   if (initialization_status == UNINITIALIZED)
+     return false;
+ 
+   while (POINTER_TYPE_P (type))
+     type = TREE_TYPE (type);
+ 
+   type = TYPE_MAIN_VARIANT (type);
+   uid = unique_type_id_for (TYPE_UID (type));
+   return bitmap_bit_p (global_types_full_escape, uid);
+ }
+ 
+ /* Return true if no fields with type FIELD_TYPE within a record of
+    RECORD_TYPE has its address taken.  */
+ 
+ bool 
+ ipa_static_address_not_taken_of_field (tree record_type, tree field_type)
+ { 
+   splay_tree_node result;
+   int uid;
+   
+   if (initialization_status == UNINITIALIZED)
+     return false;
+ 
+   /* Strip off all of the pointer tos on the record type.  Strip the
+      same number of pointer tos from the field type.  If the field
+      type has fewer, it could not have been aliased. */
+   while (POINTER_TYPE_P (record_type))
+     {
+       record_type = TREE_TYPE (record_type);
+       if (POINTER_TYPE_P (field_type)) 
+ 	field_type = TREE_TYPE (field_type);
+       else 
+ 	return true;
+     }
+   
+   /* The record type must be contained.  The field type may
+      escape.  */
+   if (!ipa_static_type_contained_p (record_type))
+     return false;
+ 
+   record_type = TYPE_MAIN_VARIANT (record_type);
+   uid = unique_type_id_for (TYPE_UID (record_type));
+   result = splay_tree_lookup (uid_to_addressof_map, (splay_tree_key) uid);
+   
+   if (result) 
+     {
+       bitmap field_type_map = (bitmap) result->value;
+       field_type = TYPE_MAIN_VARIANT (field_type);
+       uid = unique_type_id_for (TYPE_UID (field_type));
+       /* If the bit is there, the address was taken. If not, it
+ 	 wasn't.  */
+       return !bitmap_bit_p (field_type_map, uid);
+     }
+   else
+     /* No bitmap means no addresses were taken.  */
+     return true;
+ }
+ 
+ 
  struct searchc_env {
    struct cgraph_node **stack;
    int stack_size;
*************** reduced_inorder (struct cgraph_node **or
*** 478,484 ****
  	node->next_cycle = NULL;
  	
  	splay_tree_insert (env.nodes_marked_new,
! 			   node->uid, (splay_tree_value)node);
        } 
      else 
        node->aux = NULL;
--- 661,668 ----
  	node->next_cycle = NULL;
  	
  	splay_tree_insert (env.nodes_marked_new,
! 			   (splay_tree_key)node->uid, 
! 			   (splay_tree_value)node);
        } 
      else 
        node->aux = NULL;
*************** reduced_inorder (struct cgraph_node **or
*** 500,520 ****
        }
    return env.order_pos;
  }
  
  /* Add VAR to all_module_statics and the two static_vars_to_consider*
     sets.  */
  
! static inline
! void add_static_var (tree var) 
  {
!   /* FIXME -- PROFILE-RESTRUCTURE: Change the call from
!      DECL_UID to get the uid from the var_ann field. */    
!   splay_tree_insert (static_vars_to_consider_by_uid,
! 		     DECL_UID (var), (splay_tree_value)var);
!   
!   /* FIXME -- PROFILE-RESTRUCTURE: Change the call from
!      DECL_UID to get the uid from the var_ann field. */    
!   bitmap_set_bit (all_module_statics, DECL_UID (var));
  }
  
  /* FIXME this needs to be enhanced.  If we are compiling a single
--- 684,955 ----
        }
    return env.order_pos;
  }
+ 
+ 
+ 
+ /* Mark a TYPE as being seen.  This is only called from two places:
+    mark_type_seen which only calls it with record and union types and
+    mark_interesting_addressof which can mark any field type.  */ 
+ 
+ static bool
+ mark_any_type_seen (tree type)
+ {
+   int uid;
+   
+   type = TYPE_MAIN_VARIANT (type);
+   uid = TYPE_UID (type);
+   if (bitmap_bit_p (global_types_seen, uid))
+     return false;
+   else
+     {
+       splay_tree_insert (uid_to_type, 
+ 			 (splay_tree_key) uid,
+ 			 (splay_tree_value) type);	  
+       bitmap_set_bit (global_types_seen, uid);
+     }
+   return true;
+ }
+ 
+ /* Mark the underlying record or union type of TYPE as being seen.
+    Pointer tos are stripped from the type and non record or unions are
+    not considered.  */
+ 
+ static bool
+ mark_type_seen (tree type)
+ {
+   while (POINTER_TYPE_P (type))
+     type = TREE_TYPE (type);
+ 
+   /* We are interested in records, and unions only.  */
+   if (TREE_CODE (type) == RECORD_TYPE 
+ 	  || TREE_CODE (type) == QUAL_UNION_TYPE 
+ 	  || TREE_CODE (type) == UNION_TYPE)
+     return mark_any_type_seen (type);
+   else 
+     return false;
+ }
+ 
+ /* Add TYPE to the suspect type set. Return true if the bit needed to
+    be marked.  */
+ 
+ static bool
+ mark_type (tree type, enum escape_t escape_status)
+ {
+   bitmap map = NULL;
+   int uid;
+ 
+   while (POINTER_TYPE_P (type))
+     type = TREE_TYPE (type);
+   
+   switch (escape_status) 
+     {
+     case EXPOSED_PARAMETER:
+       map = global_types_exposed_parameter;
+       break;
+     case FULL_ESCAPE:
+       map = global_types_full_escape;
+       break;
+     }
+ 
+   uid = TYPE_UID (TYPE_MAIN_VARIANT (type));
+   if (bitmap_bit_p (map, uid))
+     return false;
+   else
+     {
+       bitmap_set_bit (map, uid);
+       mark_type_seen (type);
+ 
+       if (escape_status == FULL_ESCAPE)
+ 	{
+ 	  /* Effeciency hack. When things are bad, do not mess around
+ 	     with this type anymore.  */
+ 	  bitmap_set_bit (global_types_exposed_parameter, uid);
+ 	}      
+     }
+   return true;
+ }
+ 
+ /* Add interesting TYPE to the suspect type set. If the set is
+    EXPOSED_PARAMETER and the TYPE is a pointer type, the set is
+    changed to FULL_ESCAPE.  */
+ 
+ static void 
+ mark_interesting_type (tree type, enum escape_t escape_status)
+ {
+   if (ipa_static_star_count_of_interesting_type (type) >= 0)
+     {
+       if ((escape_status == EXPOSED_PARAMETER)
+ 	  && POINTER_TYPE_P (type))
+ 	/* EXPOSED_PARAMETERs are only structs or unions are passed by
+ 	   value.  Anything passed by reference to an external
+ 	   function fully exposes the type.  */
+ 	mark_type (type, FULL_ESCAPE);
+       else
+ 	mark_type (type, escape_status);
+     }
+ }
+ 
+ /* Return true if PARENT is supertype of CHILD.  Both types must be
+    known to be structures or unions. */
+  
+ static bool
+ parent_type_p (tree parent, tree child)
+ {
+   int i;
+   tree binfo, base_binfo;
+   if (TYPE_BINFO (parent)) 
+     for (binfo = TYPE_BINFO (parent), i = 0;
+ 	 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+       {
+ 	tree binfotype = BINFO_TYPE (base_binfo);
+ 	if (binfotype == child) 
+ 	  return true;
+ 	else if (parent_type_p (binfotype, child))
+ 	  return true;
+       }
+   return false;
+ }
+ 
+ /* Return the number of pointer tos for TYPE and return TYPE with all
+    of these stripped off.  */
+ 
+ static int 
+ count_stars (tree* type_ptr)
+ {
+   tree type = *type_ptr;
+   int i = 0;
+   while (POINTER_TYPE_P (type))
+     {
+       type = TREE_TYPE (type);
+       i++;
+     }
+ 
+   *type_ptr = type;
+   return i;
+ }
+ 
+ enum cast_type {
+   CT_UP,
+   CT_DOWN,
+   CT_SIDEWAYS,
+   CT_USELESS
+ };
+ 
+ /* Check the cast FROM_TYPE to TO_TYPE.  This function requires that
+    the two types have already passed the
+    ipa_static_star_count_of_interesting_type test.  */
+ 
+ static enum cast_type
+ check_cast_type (tree to_type, tree from_type)
+ {
+   int to_stars = count_stars (&to_type);
+   int from_stars = count_stars (&from_type);
+   if (to_stars != from_stars) 
+     return CT_SIDEWAYS;
+ 
+   if (to_type == from_type)
+     return CT_USELESS;
+ 
+   if (parent_type_p (to_type, from_type)) return CT_UP;
+   if (parent_type_p (from_type, to_type)) return CT_DOWN;
+   return CT_SIDEWAYS;
+ }     
+ 
+ /* Check a cast FROM this variable, TO_TYPE.  Mark the escaping types
+    if appropriate.  */ 
+ static void
+ check_cast (tree to_type, tree from) 
+ {
+   tree from_type = TYPE_MAIN_VARIANT (TREE_TYPE (from));
+   bool to_interesting_type, from_interesting_type;
+ 
+   to_type = TYPE_MAIN_VARIANT (to_type);
+   if (from_type == to_type) 
+     return;
+ 
+   to_interesting_type = 
+     ipa_static_star_count_of_interesting_type (to_type) >= 0;
+   from_interesting_type = 
+     ipa_static_star_count_of_interesting_type (from_type) >= 0;
+ 
+   if (to_interesting_type) 
+     if (from_interesting_type)
+       {
+ 	/* Both types are interesting. This can be one of four types
+ 	   of cast: useless, up, down, or sideways.  We do not care
+ 	   about up or useless.  Sideways casts are always bad and
+ 	   both sides get marked as escaping.  Downcasts are not
+ 	   interesting here because if type is marked as escaping, all
+ 	   of it's subtypes escape.  */
+ 	switch (check_cast_type (to_type, from_type)) 
+ 	  {
+ 	  case CT_UP:
+ 	  case CT_USELESS:
+ 	  case CT_DOWN:
+ 	    mark_type_seen (to_type);
+ 	    mark_type_seen (from_type);
+ 	    break;
+ 
+ 	  case CT_SIDEWAYS:
+ 	    mark_type (to_type, FULL_ESCAPE);
+ 	    mark_type (from_type, FULL_ESCAPE);
+ 	    break;
+ 	  }
+       }
+     else
+       {
+ 	/* If this is a cast from the local that is a result from a
+ 	   call to malloc, do not mark the cast as bad.  */
+ 	if (DECL_P (from) && !bitmap_bit_p (results_of_malloc, DECL_UID (from)))
+ 	  mark_type (to_type, FULL_ESCAPE);
+ 	else
+ 	  mark_type_seen (to_type);
+       }
+   else if (from_interesting_type)
+     mark_type (from_type, FULL_ESCAPE);
+ }
+ 
+ /* Register the parameter and return types of function FN as
+    escaping.  */
+ static void 
+ check_function_parameter_and_return_types (tree fn, bool escapes) 
+ {
+   tree arg;
+ 
+   for (arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
+        arg && TREE_VALUE (arg) != void_type_node;
+        arg = TREE_CHAIN (arg))
+     {
+       if (escapes)
+ 	mark_interesting_type (arg, EXPOSED_PARAMETER);
+       else
+ 	mark_type_seen (arg);
+     }
+   
+   if (escapes)
+     mark_interesting_type (TREE_TYPE (TREE_TYPE (fn)), EXPOSED_PARAMETER); 
+   else 
+     mark_type_seen (TREE_TYPE (TREE_TYPE (fn)));
+ }
  
  /* Add VAR to all_module_statics and the two static_vars_to_consider*
     sets.  */
  
! static inline void 
! add_static_var (tree var) 
  {
!   int uid = DECL_UID (var);
!   if (!bitmap_bit_p (all_module_statics, uid))
!     {
!       /* FIXME -- PROFILE-RESTRUCTURE: Change the call from
! 	 DECL_UID to get the uid from the var_ann field. */    
!       splay_tree_insert (static_vars_to_consider_by_uid,
! 			 uid, (splay_tree_value)var);
!       
!       /* FIXME -- PROFILE-RESTRUCTURE: Change the call from
! 	 DECL_UID to get the uid from the var_ann field. */    
!       bitmap_set_bit (all_module_statics, uid);
!     }
  }
  
  /* FIXME this needs to be enhanced.  If we are compiling a single
*************** check_operand (ipa_local_static_vars_inf
*** 584,606 ****
  {
    if (!t) return;
  
    /* FIXME -- PROFILE-RESTRUCTURE: Change the call from DECL_UID to
       get the uid from the var_ann field. */    
!   if ((TREE_CODE (t) == VAR_DECL) 
!       && has_proper_scope_for_analysis (local, t, checking_write)) 
      {
!       if (checking_write)
  	{
! 	  if (local)
! 	    bitmap_set_bit (local->statics_written_by_decl_uid, DECL_UID (t));
! 	  /* Mark the write so we can tell which statics are
! 	     readonly.  */
! 	  bitmap_set_bit (module_statics_written, DECL_UID (t));
  	}
-       else if (local)
- 	bitmap_set_bit (local->statics_read_by_decl_uid, DECL_UID (t));
      }
-   else return;
  }
  
  /* Examine tree T for references to static variables. All internal
--- 1019,1048 ----
  {
    if (!t) return;
  
+   /* This is an assignment from a function, register the types as
+      escaping.  */
+   if (TREE_CODE (t) == FUNCTION_DECL)
+     check_function_parameter_and_return_types (t, true);
+ 
    /* FIXME -- PROFILE-RESTRUCTURE: Change the call from DECL_UID to
       get the uid from the var_ann field. */    
!   else if (TREE_CODE (t) == VAR_DECL)
      {
!       mark_type_seen (TREE_TYPE (t));
!       if (has_proper_scope_for_analysis (local, t, checking_write)) 
  	{
! 	  if (checking_write)
! 	    {
! 	      if (local)
! 		bitmap_set_bit (local->statics_written_by_decl_uid, DECL_UID (t));
! 	      /* Mark the write so we can tell which statics are
! 		 readonly.  */
! 	      bitmap_set_bit (module_statics_written, DECL_UID (t));
! 	    }
! 	  else if (local)
! 	    bitmap_set_bit (local->statics_read_by_decl_uid, DECL_UID (t));
  	}
      }
  }
  
  /* Examine tree T for references to static variables. All internal
*************** check_tree (ipa_local_static_vars_info_t
*** 626,632 ****
    /* The bottom of an indirect reference can only be read, not
       written.  So just recurse and whatever we find, check it against
       the read bitmaps.  */
!   if (INDIRECT_REF_P (t))
      {
        check_tree (local, TREE_OPERAND (t, 0), false);
        
--- 1068,1074 ----
    /* The bottom of an indirect reference can only be read, not
       written.  So just recurse and whatever we find, check it against
       the read bitmaps.  */
!   if (INDIRECT_REF_P (t) || TREE_CODE (t) == MEM_REF)
      {
        check_tree (local, TREE_OPERAND (t, 0), false);
        
*************** check_tree (ipa_local_static_vars_info_t
*** 644,653 ****
  	}
      }
  
!   if (SSA_VAR_P (t))
      check_operand (local, t, checking_write);
  }
  
  /* Scan tree T to see if there are any addresses taken in within T.  */
  
  static void 
--- 1086,1153 ----
  	}
      }
  
!   if (SSA_VAR_P (t) || (TREE_CODE (t) == FUNCTION_DECL))
      check_operand (local, t, checking_write);
  }
  
+ /* Given a memory reference T, will return the variable at the bottom
+    of the access.  Unlike get_base_address, this will recurse thru
+    INDIRECT_REFS.  */
+ 
+ static tree
+ get_base_var (tree t)
+ {
+   if ((TREE_CODE (t) == EXC_PTR_EXPR) || (TREE_CODE (t) == FILTER_EXPR))
+     return t;
+ 
+   while (!SSA_VAR_P (t) 
+ 	 && (!CONSTANT_CLASS_P (t))
+ 	 && TREE_CODE (t) != LABEL_DECL
+ 	 && TREE_CODE (t) != FUNCTION_DECL
+ 	 && TREE_CODE (t) != CONST_DECL)
+     {
+       t = TREE_OPERAND (t, 0);
+     }
+   return t;
+ } 
+ 
+ /* Create an address_of edge FROM_TYPE.TO_TYPE.  */
+ static void
+ mark_interesting_addressof (tree to_type, tree from_type)
+ {
+   from_type = TYPE_MAIN_VARIANT (from_type);
+   to_type = TYPE_MAIN_VARIANT (to_type);
+   if (ipa_static_star_count_of_interesting_type (from_type) == 0)
+     {
+       int uid = TYPE_UID (from_type);
+       bitmap from_type_map;
+       splay_tree_node result = 
+ 	splay_tree_lookup (uid_to_addressof_map, (splay_tree_key) uid);
+  
+       if (result) 
+ 	from_type_map = (bitmap) result->value;  
+       else 
+ 	{
+ 	  from_type_map = BITMAP_ALLOC (&ipa_obstack);
+ 	  splay_tree_insert (uid_to_addressof_map,
+ 			     uid, 
+ 			     (splay_tree_value)from_type_map);
+ 	}
+       bitmap_set_bit (from_type_map, TYPE_UID (to_type));
+       mark_type_seen (from_type);
+       mark_any_type_seen (to_type);
+     }
+   else 
+     {
+       fprintf(stderr, "trying to mark the address of pointer type ");
+       print_generic_expr (stderr, from_type, 0);
+       fprintf(stderr, "\n");
+       abort ();
+     }
+ }
+ 
+ 
+ 
  /* Scan tree T to see if there are any addresses taken in within T.  */
  
  static void 
*************** look_for_address_of (ipa_local_static_va
*** 656,661 ****
--- 1156,1177 ----
    if (TREE_CODE (t) == ADDR_EXPR)
      {
        tree x = get_base_var (t);
+       tree cref = TREE_OPERAND (t, 0);
+ 
+       /* If we have an expression of the form "&a.b.c.d", mark a.b,
+ 	 b.c and c.d. as having it's address taken.  */ 
+       tree fielddecl = NULL_TREE;
+       while (cref!= x)
+ 	{
+ 	  if (TREE_CODE (cref) == COMPONENT_REF)
+ 	    {
+ 	      fielddecl =  TREE_OPERAND (cref, 1);
+ 	      mark_interesting_addressof (TREE_TYPE (fielddecl), 
+ 					  DECL_FIELD_CONTEXT (fielddecl));
+ 	    }
+ 	  cref = TREE_OPERAND (cref, 0);
+ 	}
+ 
        if (TREE_CODE (x) == VAR_DECL) 
  	{
  	  if (has_proper_scope_for_analysis (local, x, false))
*************** look_for_address_of (ipa_local_static_va
*** 673,678 ****
--- 1189,1225 ----
  }
  
  
+ /* Scan tree T to see if there are any casts within it.
+    LHS Is the LHS of the expression involving the cast.  */
+ 
+ static void 
+ look_for_casts (tree lhs __attribute__((unused)), tree t)
+ {
+   if (is_gimple_cast (t) || TREE_CODE (t) == VIEW_CONVERT_EXPR)
+     {
+       tree castfromvar = TREE_OPERAND (t, 0);
+       check_cast (TREE_TYPE (t), castfromvar);
+     }
+   else if (TREE_CODE (t) == COMPONENT_REF
+ 	   || TREE_CODE (t) == INDIRECT_REF
+ 	   || TREE_CODE (t) == BIT_FIELD_REF)
+     {
+       tree base = get_base_address (t);
+       while (t != base)
+ 	{
+ 	  t = TREE_OPERAND (t, 0);
+ 	  if (TREE_CODE (t) == VIEW_CONVERT_EXPR)
+ 	    {
+ 	      /* This may be some part of a component ref.
+ 		 IE it may be a.b.VIEW_CONVERT_EXPR<weird_type>(c).d, AFAIK.
+ 		 castfromref will give you a.b.c, not a. */
+ 	      tree castfromref = TREE_OPERAND (t, 0);
+ 	      check_cast (TREE_TYPE (t), castfromref);
+ 	    }
+ 	}
+     } 
+ } 
+ 
  /* Check to see if T is a read or address of operation on a static var
     we are interested in analyzing.  LOCAL is passed in to get access to
     its bit vectors.  */
*************** get_asm_expr_operands (ipa_local_static_
*** 774,786 ****
     parameter is the tree node for the caller and the second operand is
     the tree node for the entire call expression.  */
  
! static void
! process_call_for_static_vars(ipa_local_static_vars_info_t local, tree call_expr) 
  {
    int flags = call_expr_flags(call_expr);
    tree operandList = TREE_OPERAND (call_expr, 1);
    tree operand;
    tree callee_t = get_callee_fndecl (call_expr);
    struct cgraph_node* callee;
    enum availability avail = AVAIL_NOT_AVAILABLE;
  
--- 1321,1335 ----
     parameter is the tree node for the caller and the second operand is
     the tree node for the entire call expression.  */
  
! static bool
! check_call (ipa_local_static_vars_info_t local, 
! 	      tree call_expr) 
  {
    int flags = call_expr_flags(call_expr);
    tree operandList = TREE_OPERAND (call_expr, 1);
    tree operand;
    tree callee_t = get_callee_fndecl (call_expr);
+   tree argument;
    struct cgraph_node* callee;
    enum availability avail = AVAIL_NOT_AVAILABLE;
  
*************** process_call_for_static_vars(ipa_local_s
*** 806,814 ****
--- 1355,1395 ----
  
    if (callee_t)
      {
+       tree arg_type;
+       tree last_arg_type;
        callee = cgraph_node(callee_t);
        avail = cgraph_function_body_availability (callee);
  
+       /* If the function is FREE or a wrapper it is allowed to make an
+ 	 implicit cast to void* without causing the type to
+ 	 escape.  */
+       if (!flags & ECF_FREE) 
+ 	{
+ 	  /* Check that there are no implicit casts in the passing of
+ 	     parameters.  */
+ 	  operand = operandList;
+ 	  for (arg_type = TYPE_ARG_TYPES (TREE_TYPE (callee_t));
+ 	       arg_type && TREE_VALUE (arg_type) != void_type_node;
+ 	       arg_type = TREE_CHAIN (arg_type))
+ 	    {
+ 	      operand = TREE_CHAIN (operand);
+ 	      argument = TREE_VALUE (operand);
+ 	      check_cast (arg_type, argument);
+ 	      last_arg_type = arg_type;
+ 	    }
+ 	  
+ 	  /* In the case where we have a var_args function, we need to
+ 	     check the remaining parameters against the last argument.  */
+ 	  arg_type = last_arg_type;
+ 	  for (;
+ 	       operand != NULL_TREE;
+ 	       operand = TREE_CHAIN (operand))
+ 	    {
+ 	      argument = TREE_VALUE (operand);
+ 	      check_cast (arg_type, argument);
+ 	    }
+ 	}
+ 
        /* When bad things happen to bad functions, they cannot be const
  	 or pure.  */
        if (local && local->pure_const_not_set_in_source)
*************** process_call_for_static_vars(ipa_local_s
*** 833,869 ****
       look because if there is also code, we need to mark the variables
       it is reading from. */
    if (flags & ECF_CONST) 
!     return;
! 
!   if (!local) return;
  
    /* The callee is either unknown (indirect call) or there is just no
!      scanable code for it (external call) .  We look to see if there
       are any bits available for the callee (such as by declaration or
       because it is builtin) and process solely on the basis of those
       bits. */
  
    if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
      {
!       if (flags & ECF_PURE) 
  	{
! 	  local->calls_read_all = true;
! 	  if (local->pure_const_not_set_in_source
! 	      && local->pure_const_state == IPA_CONST)
! 	    local->pure_const_state = IPA_PURE;
  	}
!       else 
  	{
! 	  local->calls_read_all = true;
! 	  local->calls_write_all = true;
! 	  if (local->pure_const_not_set_in_source)
! 	    local->pure_const_state = IPA_NEITHER;
  	}
      }
    else
      {
        /* We have the code and we will scan it for the effects. */
!       if (flags & ECF_PURE) 
  	{
  	  /* Since we have the code for the function, we do not need to
  	     set calls_read_all, we can determine the precise reads
--- 1414,1465 ----
       look because if there is also code, we need to mark the variables
       it is reading from. */
    if (flags & ECF_CONST) 
!     return false;
  
    /* The callee is either unknown (indirect call) or there is just no
!      scannable code for it (external call) .  We look to see if there
       are any bits available for the callee (such as by declaration or
       because it is builtin) and process solely on the basis of those
       bits. */
  
    if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
      {
!       /* If this is a direct call to an external function, mark all of
! 	 the parameter and return types.  */
!       for (operand = operandList;
! 	   operand != NULL_TREE;
! 	   operand = TREE_CHAIN (operand))
  	{
! 	  mark_interesting_type (TREE_TYPE (TREE_VALUE (operand)), 
! 				 EXPOSED_PARAMETER);
  	}
! 	  
!       if (callee_t) 
! 	mark_interesting_type (TREE_TYPE (TREE_TYPE (callee_t)), 
! 			       EXPOSED_PARAMETER);
! 
!       if (local) 
  	{
! 	  if (flags & ECF_PURE) 
! 	    {
! 	      local->calls_read_all = true;
! 	      if (local->pure_const_not_set_in_source
! 		  && local->pure_const_state == IPA_CONST)
! 		local->pure_const_state = IPA_PURE;
! 	    }
! 	  else 
! 	    {
! 	      local->calls_read_all = true;
! 	      local->calls_write_all = true;
! 	      if (local->pure_const_not_set_in_source)
! 		local->pure_const_state = IPA_NEITHER;
! 	    }
  	}
      }
    else
      {
        /* We have the code and we will scan it for the effects. */
!       if (local && (flags & ECF_PURE)) 
  	{
  	  /* Since we have the code for the function, we do not need to
  	     set calls_read_all, we can determine the precise reads
*************** process_call_for_static_vars(ipa_local_s
*** 873,878 ****
--- 1469,1476 ----
  	    local->pure_const_state = IPA_PURE;
  	}
      }
+ 
+   return (flags & ECF_MALLOC);
  }
  
  /* FIXME -- PROFILE-RESTRUCTURE: Change to walk by explicitly walking
*************** scan_for_static_refs (tree *tp, 
*** 909,928 ****
      case MODIFY_EXPR:
        {
  	/* First look on the lhs and see what variable is stored to */
  	tree rhs = TREE_OPERAND (t, 1);
! 	check_lhs_var (local, TREE_OPERAND (t, 0));
  
  	/* Next check the operands on the rhs to see if they are ok. */
  	switch (TREE_CODE_CLASS (TREE_CODE (rhs))) 
  	  {
! 	  case tcc_binary:
! 	    check_rhs_var (local, TREE_OPERAND (rhs, 0));
! 	    check_rhs_var (local, TREE_OPERAND (rhs, 1));
  	    break;
  	  case tcc_unary:
! 	    check_rhs_var (local, TREE_OPERAND (rhs, 0));
  	    break;
  	  case tcc_reference:
  	    check_rhs_var (local, rhs);
  	    break;
  	  case tcc_declaration:
--- 1507,1569 ----
      case MODIFY_EXPR:
        {
  	/* First look on the lhs and see what variable is stored to */
+ 	tree lhs = TREE_OPERAND (t, 0);
  	tree rhs = TREE_OPERAND (t, 1);
! 
! 	check_lhs_var (local, lhs);
!  	check_cast (TREE_TYPE (lhs), rhs);
! 
! 	/* For the purposes of figuring out what the cast affects */
  
  	/* Next check the operands on the rhs to see if they are ok. */
  	switch (TREE_CODE_CLASS (TREE_CODE (rhs))) 
  	  {
! 	  case tcc_binary:	    
!  	    {
!  	      tree op0 = TREE_OPERAND (rhs, 0);
!  	      tree op1 = TREE_OPERAND (rhs, 1);
!  
!  	      /* If this is pointer arithmetic of any sort, then we
!  		 need to mark the types as bad.  For binary
!  		 operations, no binary operator we currently support
!  		 is always "safe" in regard to what it would do to
!  		 pointers for purposes of determining which types
!  		 escape.  It is possible that min and max under the
!  		 right set of circumstances and if the moon is in the
!  		 correct place could be safe, but it is hard to see
!  		 how this is worth the effort.  */
!  
!  	      if (POINTER_TYPE_P (TREE_TYPE (op0)))
!  		mark_interesting_type (TREE_TYPE (op0), FULL_ESCAPE);
!  	      if (POINTER_TYPE_P (TREE_TYPE (op1)))
!  		mark_interesting_type (TREE_TYPE (op1), FULL_ESCAPE);
!  	      
! 	      look_for_casts (lhs, op0);
! 	      look_for_casts (lhs, op1);
!  	      check_rhs_var (local, op0);
!  	      check_rhs_var (local, op1);
! 	    }
  	    break;
  	  case tcc_unary:
!  	    {
!  	      tree op0 = TREE_OPERAND (rhs, 0);
! 	      /* For unary operations, if the operation is NEGATE or ABS on
! 		 a pointer, this is also considered pointer arithmetic and thus,
! 		 bad for business.  */
!  	      if ((TREE_CODE (op0) == NEGATE_EXPR
!  		   || TREE_CODE (op0) == ABS_EXPR)
!  		  && POINTER_TYPE_P (TREE_TYPE (op0)))
!  		{
!  		  mark_interesting_type (TREE_TYPE (op0), FULL_ESCAPE);
!  		}
!  	      check_rhs_var (local, op0);
! 	      look_for_casts (lhs, op0);
! 	      look_for_casts (lhs, rhs);
!  	    }
! 
  	    break;
  	  case tcc_reference:
+ 	    look_for_casts (lhs, rhs);
  	    check_rhs_var (local, rhs);
  	    break;
  	  case tcc_declaration:
*************** scan_for_static_refs (tree *tp, 
*** 932,941 ****
  	    switch (TREE_CODE (rhs)) 
  	      {
  	      case ADDR_EXPR:
  		check_rhs_var (local, rhs);
  		break;
  	      case CALL_EXPR: 
! 		process_call_for_static_vars (local, rhs);
  		break;
  	      default:
  		break;
--- 1573,1587 ----
  	    switch (TREE_CODE (rhs)) 
  	      {
  	      case ADDR_EXPR:
+ 		look_for_casts (lhs, TREE_OPERAND (rhs, 0));
  		check_rhs_var (local, rhs);
  		break;
  	      case CALL_EXPR: 
! 		/* If this is a call to malloc, squirrel away the
! 		   result so we do mark the resulting cast as being
! 		   bad.  */
! 		if (check_call (local, rhs))
! 		  bitmap_set_bit (results_of_malloc, DECL_UID (lhs));
  		break;
  	      default:
  		break;
*************** scan_for_static_refs (tree *tp, 
*** 967,973 ****
        break;
  
      case CALL_EXPR: 
!       process_call_for_static_vars (local, t);
        *walk_subtrees = 0;
        break;
        
--- 1613,1619 ----
        break;
  
      case CALL_EXPR: 
!       check_call (local, t);
        *walk_subtrees = 0;
        break;
        
*************** scan_for_static_refs (tree *tp, 
*** 982,987 ****
--- 1628,1634 ----
    return NULL;
  }
  
+ 
  /* Lookup the tree node for the static variable that has UID.  */
  static tree
  get_static_decl_by_uid (int index)
*************** propagate_bits (struct cgraph_node *x)
*** 1047,1053 ****
  		  if (y_global->statics_read_by_decl_uid 
  		      == all_module_statics)
  		    {
! 		      BITMAP_XFREE(x_global->statics_read_by_decl_uid);
  		      x_global->statics_read_by_decl_uid 
  			= all_module_statics;
  		    }
--- 1694,1700 ----
  		  if (y_global->statics_read_by_decl_uid 
  		      == all_module_statics)
  		    {
! 		      BITMAP_XFREE (x_global->statics_read_by_decl_uid);
  		      x_global->statics_read_by_decl_uid 
  			= all_module_statics;
  		    }
*************** propagate_bits (struct cgraph_node *x)
*** 1064,1070 ****
  		  if (y_global->statics_written_by_decl_uid 
  		      == all_module_statics)
  		    {
! 		      BITMAP_XFREE(x_global->statics_written_by_decl_uid);
  		      x_global->statics_written_by_decl_uid 
  			= all_module_statics;
  		    }
--- 1711,1717 ----
  		  if (y_global->statics_written_by_decl_uid 
  		      == all_module_statics)
  		    {
! 		      BITMAP_XFREE (x_global->statics_written_by_decl_uid);
  		      x_global->statics_written_by_decl_uid 
  			= all_module_statics;
  		    }
*************** merge_callee_local_info (struct cgraph_n
*** 1145,1151 ****
  
  /* The init routine for analyzing global static variable usage.  See
     comments at top for description.  */
! 
  static void 
  ipa_init (void) 
  {
--- 1792,1798 ----
  
  /* The init routine for analyzing global static variable usage.  See
     comments at top for description.  */
! int cant_touch = 0;
  static void 
  ipa_init (void) 
  {
*************** ipa_init (void) 
*** 1160,1165 ****
--- 1807,1820 ----
    module_statics_escape = BITMAP_ALLOC (&ipa_obstack);
    module_statics_written = BITMAP_ALLOC (&ipa_obstack);
    all_module_statics = BITMAP_ALLOC (&ipa_obstack);
+   global_types_seen = BITMAP_ALLOC (&ipa_obstack);
+   global_types_exposed_parameter = BITMAP_ALLOC (&ipa_obstack);
+   global_types_full_escape = BITMAP_ALLOC (&ipa_obstack);
+   results_of_malloc = BITMAP_ALLOC (&ipa_obstack);
+   cant_touch = 1;
+   uid_to_type = splay_tree_new (splay_tree_compare_ints, 0, 0);
+   uid_to_subtype_map = splay_tree_new (splay_tree_compare_ints, 0, 0);
+   uid_to_addressof_map = splay_tree_new (splay_tree_compare_ints, 0, 0);
  
    /* There are some shared nodes, in particular the initializers on
       static declarations.  We do not need to scan them more than once
*************** analyze_variable (struct cgraph_varpool_
*** 1188,1200 ****
        break;
  
      case FINISHED:
! /*       fprintf(stderr,  */
! /* 	      "AV analyze_variable called after execute for variable %s\n" , */
! /* 	      lang_hooks.decl_printable_name (global, 2)); */
!       /*abort ();*/
        break;
      }
  
    if (TREE_CODE (global) == VAR_DECL)
      {
        if (DECL_INITIAL (global)) 
--- 1843,1862 ----
        break;
  
      case FINISHED:
!       fprintf(stderr,  
! 	      "AV analyze_variable called after execute for variable %s\n" , 
! 	      lang_hooks.decl_printable_name (global, 2)); 
!       abort ();
        break;
      }
  
+   /* If this variable has exposure beyond the compilation unit, add
+      it's type to the global types.  */
+   if (vnode->externally_visible)
+     mark_interesting_type (TREE_TYPE (global), FULL_ESCAPE);
+   else 
+     mark_type_seen (TREE_TYPE (global));
+ 
    if (TREE_CODE (global) == VAR_DECL)
      {
        if (DECL_INITIAL (global)) 
*************** analyze_function (struct cgraph_node *fn
*** 1238,1243 ****
--- 1900,1910 ----
  /* 		  fprintf(stderr, "cfg=%x\n", */
  /* 			  DECL_STRUCT_FUNCTION (fn->decl) -> cfg); */
  
+   /* If this function can be called from the outside, register the
+      types as escaping.  */
+   check_function_parameter_and_return_types (decl, fn->local.externally_visible);
+     
+ 
    /* Add the info to the tree's annotation.  */
    fn->static_vars_info = info;
    var_ann->static_vars_info = info;
*************** analyze_function (struct cgraph_node *fn
*** 1292,1300 ****
        for (step = BLOCK_VARS (DECL_INITIAL (decl));
  	   step;
  	   step = TREE_CHAIN (step))
! 	if (DECL_INITIAL (step))
! 	  walk_tree (&DECL_INITIAL (step), scan_for_static_refs, 
! 		     fn, visited_nodes);
      }
    
    /* Also look here for private statics.  */
--- 1959,1971 ----
        for (step = BLOCK_VARS (DECL_INITIAL (decl));
  	   step;
  	   step = TREE_CHAIN (step))
! 	{
! 	  if (DECL_INITIAL (step))
! 	    walk_tree (&DECL_INITIAL (step), scan_for_static_refs, 
! 		       fn, visited_nodes);
! 	  mark_type_seen (TREE_TYPE (step));
! 	}
! 
      }
    
    /* Also look here for private statics.  */
*************** analyze_function (struct cgraph_node *fn
*** 1309,1323 ****
  	  if (DECL_INITIAL (var) && TREE_STATIC (var))
  	    walk_tree (&DECL_INITIAL (var), scan_for_static_refs, 
  		       fn, visited_nodes);
  	}
      }
  }
  
  /* Produce the global information by preforming a transitive closure
     on the local information that was produced by ipa_analyze_function
     and ipa_analyze_variable.  */
  
- 
  static void
  static_execute (void)
  {
--- 1980,2493 ----
  	  if (DECL_INITIAL (var) && TREE_STATIC (var))
  	    walk_tree (&DECL_INITIAL (var), scan_for_static_refs, 
  		       fn, visited_nodes);
+ 	  mark_type_seen (TREE_TYPE (var));
  	}
      }
  }
  
+ 
+ 
+ /* Convert a type_UID into a type.  */
+ static tree
+ type_for_uid (int uid)
+ {
+   splay_tree_node result = 
+     splay_tree_lookup (uid_to_type, (splay_tree_key) uid);
+   
+   if (result)
+     return (tree) result->value;  
+   else return NULL;
+ }
+ 
+ /* Return the a bitmap with the subtypes of the type for UID.  If it
+    does not exist, return either NULL or a new bitmap depending on the
+    value of CREATE.  */ 
+ 
+ static bitmap
+ subtype_map_for_uid (int uid, bool create)
+ {
+   splay_tree_node result = 
+     splay_tree_lookup (uid_to_subtype_map, (splay_tree_key) uid);
+   
+   if (result) 
+     return (bitmap) result->value;  
+   else if (create)
+     {
+       bitmap subtype_map = BITMAP_ALLOC (&ipa_obstack);
+       splay_tree_insert (uid_to_subtype_map,
+ 			 uid, 
+ 			 (splay_tree_value)subtype_map);
+       return subtype_map;
+     }
+   else return NULL;
+ }
+ 
+ /* Mark all of the supertypes and field types of TYPE as being seen.
+    Also accumulate the subtypes for each type so that
+    close_types_full_escape can mark a subtype as escaping if the
+    supertype escapes.  */
+ 
+ static void
+ close_type_seen (tree type)
+ {
+   tree field;
+   int i, uid;
+   tree binfo, base_binfo;
+ 
+   /* See thru all pointer tos. */
+   while (POINTER_TYPE_P (type))
+     type = TREE_TYPE (type);
+   
+   type = TYPE_MAIN_VARIANT (type);
+   uid = TYPE_UID (type);
+ 
+   if (bitmap_bit_p (been_there_done_that, uid))
+     return;
+   bitmap_set_bit (been_there_done_that, uid);
+ 
+   /* If we are doing a language with a type heirarchy, mark all of
+      the superclasses.  */
+   if (TYPE_BINFO (type)) 
+     for (binfo = TYPE_BINFO (type), i = 0;
+ 	 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+       {
+ 	tree binfo_type = BINFO_TYPE (base_binfo);
+ 	bitmap subtype_map = subtype_map_for_uid 
+ 	  (TYPE_UID (TYPE_MAIN_VARIANT (binfo_type)), true);
+ 	bitmap_set_bit (subtype_map, uid);
+ 	if (mark_type_seen (binfo_type))
+ 	  close_type_seen (binfo_type);
+       }
+       
+   /* If the field is a struct or union type, mark all of the
+      subfields.  */
+   for (field = TYPE_FIELDS (type);
+        field;
+        field = TREE_CHAIN (field))
+     {
+       tree field_type;
+       if (TREE_CODE (field) != FIELD_DECL)
+ 	continue;
+ 
+       field_type = TREE_TYPE (field);
+       if (ipa_static_star_count_of_interesting_type (field_type) >= 0)
+ 	if (mark_type_seen (field_type))
+ 	  close_type_seen (field_type);
+     }
+ }
+ 
+ struct type_brand_s 
+ {
+   char* name;
+   int seq;
+ };
+ 
+ /* Splay tree comparison function on type_brand_s structures.  */
+ 
+ static int 
+ compare_type_brand (splay_tree_key sk1, splay_tree_key sk2)
+ {
+   struct type_brand_s * k1 = (struct type_brand_s *) sk1;
+   struct type_brand_s * k2 = (struct type_brand_s *) sk2;
+ 
+   int value = strcmp(k1->name, k2->name);
+   if (value == 0)
+     return k2->seq - k1->seq;
+   else 
+     return value;
+ }
+ 
+ /* Get the name of TYPE or return the string "<UNNAMED>".  */
+ static char*
+ get_name_of_type (tree type)
+ {
+   tree name = TYPE_NAME (type);
+   
+   if (!name)
+     /* Unnamed type, do what you like here.  */
+     return (char*)"<UNNAMED>";
+   
+   /* It will be a TYPE_DECL in the case of a typedef, otherwise, an
+      identifier_node */
+   if (TREE_CODE (name) == TYPE_DECL)
+     {
+       /*  Each DECL has a DECL_NAME field which contains an
+ 	  IDENTIFIER_NODE.  (Some decls, most often labels, may have
+ 	  zero as the DECL_NAME).  */
+       if (DECL_NAME (name))
+ 	return (char*)IDENTIFIER_POINTER (DECL_NAME (name));
+       else
+ 	/* Unnamed type, do what you like here.  */
+ 	return (char*)"<UNNAMED>";
+     }
+   else if (TREE_CODE (name) == IDENTIFIER_NODE)
+     return (char*)IDENTIFIER_POINTER (name);
+   else 
+     return (char*)"<UNNAMED>";
+ }
+ 
+ 
+ /* Use a completely lame algorithm for removing duplicate types.  This
+    code should not be here except for a bad implementation of whole
+    program compilation.  */
+ /* Return either TYPE if this is first time TYPE has been seen an
+    compatible TYPE that has already been processed.  */ 
+ 
+ static tree
+ discover_unique_type (tree type)
+ {
+   struct type_brand_s * brand = xmalloc(sizeof(struct type_brand_s));
+   int i = 0;
+   splay_tree_node result;
+   
+   while (1)
+   {
+     brand->name = get_name_of_type (type);
+     brand->seq = i;
+     result = splay_tree_lookup (all_unique_types, (splay_tree_key) brand);
+     if (result)
+       {
+ 	tree other_type = (tree) result->value;
+ 	if (lang_hooks.types_compatible_p (type, other_type) == 1)
+ 	  {
+ 	    free (brand);
+ 	    return other_type;
+ 	  }
+ 	/* Not compatible, look for next instance with same name.  */
+       }
+     else 
+       {
+ 	/* No more instances, create new one.  */
+ 	brand->seq = i++;
+ 	splay_tree_insert (all_unique_types, 
+ 			   (splay_tree_key) brand,
+ 			   (splay_tree_value) type);	  
+ 	
+ 	return type;
+       }
+     i++;
+   } 
+ }
+ 
+ /* Take a TYPE that has been passed by value to an external function
+    and mark all of the fields that have pointer types as escaping. For
+    any of the non pointer types that are structures or unions,
+    recurse.  TYPE is never a pointer type.  */ 
+ 
+ static void
+ close_type_exposed_parameter (tree type)
+ {
+   tree field;
+   int uid = TYPE_UID (TYPE_MAIN_VARIANT (type));
+ 
+   if (bitmap_bit_p (been_there_done_that, uid))
+     return;
+   bitmap_set_bit (been_there_done_that, uid);
+ 
+   /* If the field is a struct or union type, mark all of the
+      subfields.  */
+   for (field = TYPE_FIELDS (type);
+        field;
+        field = TREE_CHAIN (field))
+     {
+       tree field_type;
+ 
+       if (TREE_CODE (field) != FIELD_DECL)
+ 	continue;
+ 
+       field_type = TREE_TYPE (field);
+       mark_interesting_type (field_type, EXPOSED_PARAMETER);
+ 
+       if (ipa_static_star_count_of_interesting_type (field_type) == 0) 
+ 	close_type_exposed_parameter (field_type);
+     }
+ }
+ 
+ /* The next function handles the case where a type fully escapes.
+    This means that not only does the type itself escape, 
+ 
+    a) the type of every field recursively escapes
+    b) the type of every subtype escapes as well as the super as well
+    as all of the pointer to types for each field.
+ 
+    Note that pointer to types are not marked as escaping.  If the
+    pointed to type escapes, the pointer to type also escapes.
+ 
+    Take a TYPE that has had the address taken for an instance of it
+    and mark all of the types for its fields as having their addresses
+    taken. */ 
+ 
+ static void
+ close_type_full_escape (tree type)
+ {
+   tree field;
+   unsigned int i;
+   int uid;
+   tree binfo, base_binfo;
+   bitmap_iterator bi;
+   bitmap subtype_map;
+ 
+   /* Strip off any pointer types.  */
+   while (POINTER_TYPE_P (type))
+     type = TREE_TYPE (type);
+ 
+   type = TYPE_MAIN_VARIANT (type);
+   uid = TYPE_UID (type);
+ 
+   if (bitmap_bit_p (been_there_done_that, uid))
+     return;
+   bitmap_set_bit (been_there_done_that, uid);
+ 
+   subtype_map = subtype_map_for_uid (uid, false);
+ 
+   /* If we are doing a language with a type heirarchy, mark all of
+      the superclasses.  */
+   if (TYPE_BINFO (type)) 
+     for (binfo = TYPE_BINFO (type), i = 0;
+ 	 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+       {
+ 	tree binfotype = BINFO_TYPE (base_binfo);
+ 	if (ipa_static_star_count_of_interesting_type (binfotype) >= 0)
+ 	  if (mark_type (binfotype, FULL_ESCAPE))
+ 	    close_type_full_escape (binfotype);
+       }
+       
+   /* Mark as escaped any types that have been down casted to
+      this type. */
+   if (subtype_map)
+     EXECUTE_IF_SET_IN_BITMAP (subtype_map, 0, i, bi)
+       {
+ 	tree subtype = type_for_uid (i); 
+ 	if (mark_type (subtype, FULL_ESCAPE))
+ 	  close_type_full_escape (subtype);
+       }
+ 
+   /* If the field is a struct or union type, mark all of the
+      subfields.  */
+   for (field = TYPE_FIELDS (type);
+        field;
+        field = TREE_CHAIN (field))
+     {
+       tree field_type;
+       if (TREE_CODE (field) != FIELD_DECL)
+ 	continue;
+ 
+       field_type = TREE_TYPE (field);
+       if (ipa_static_star_count_of_interesting_type (field_type) >= 0)
+ 	if (mark_type (field_type, FULL_ESCAPE))
+ 	  close_type_full_escape (field_type);
+     }
+ }
+ 
+ /* It is not necessary to carry around the addressof map for any
+    escaping TYPE.  */
+  
+ static void 
+ delete_addressof_map (tree from_type) 
+ {
+   int uid = TYPE_UID (TYPE_MAIN_VARIANT (from_type));
+   splay_tree_node result = 
+     splay_tree_lookup (uid_to_addressof_map, (splay_tree_key) uid);
+   
+   if (result) 
+     {
+       bitmap map = (bitmap) result->value;
+       BITMAP_XFREE (map);
+       splay_tree_remove (uid_to_addressof_map, (splay_tree_key) uid);
+     }
+ }
+ 
+ /* Transitively close the addressof bitmap for the type with UID.
+    This means that if we had a.b and b.c, a would have both b an c in
+    it's maps.  */ 
+ 
+ static bitmap
+ close_addressof (int uid) 
+ {
+   bitmap_iterator bi;
+   splay_tree_node result = 
+     splay_tree_lookup (uid_to_addressof_map, (splay_tree_key) uid);
+   bitmap map = NULL;
+   bitmap new_map;
+   unsigned int i;
+   
+   if (result) 
+     map = (bitmap) result->value;
+   else 
+     return NULL;
+ 
+   if (bitmap_bit_p (been_there_done_that, uid))
+     return map;
+   bitmap_set_bit (been_there_done_that, uid);
+ 
+   /* The new_map will have all of the bits for the enclosed fields and
+      will have the unique id version of the old map.  */
+   new_map = BITMAP_ALLOC (&ipa_obstack);
+ 
+   EXECUTE_IF_SET_IN_BITMAP (map, 0, i, bi)
+     {
+       int new_uid = unique_type_id_for (i);
+       bitmap submap = close_addressof (new_uid);
+       bitmap_set_bit (new_map, new_uid);
+       if (submap) 
+ 	bitmap_ior_into (new_map, submap);
+     }      
+   result->value = (splay_tree_value) new_map;
+ 
+   BITMAP_FREE (map);
+   return new_map;
+ }
+ 
+ /* Do all of the closures to discover which types escape the
+    compilation unit.  */
+ 
+ static void
+ do_type_analysis (void)
+ { 
+   unsigned int i;
+   bitmap_iterator bi;
+   splay_tree_node result;
+ 
+   been_there_done_that = BITMAP_ALLOC (&ipa_obstack);
+ 
+   /* Examine the types that we have directly seen in scanning the code
+      and add to that any contained types or superclasses.  */
+ 
+   EXECUTE_IF_SET_IN_BITMAP (global_types_seen, 0, i, bi)
+     {
+       tree type = type_for_uid (i);
+       /* Only look at records and unions with no pointer tos.  */
+       if (ipa_static_star_count_of_interesting_type (type) == 0)
+ 	close_type_seen (type);
+     }
+   bitmap_clear (been_there_done_that);
+ 
+   /* Map the duplicate types to a single unique type.  This is a hack
+      it is not a general algorithm.  */
+   uid_to_unique_type = splay_tree_new (splay_tree_compare_ints, 0, 0);
+   all_unique_types = splay_tree_new (compare_type_brand, 0, 0);
+   
+   EXECUTE_IF_SET_IN_BITMAP (global_types_seen, 0, i, bi)
+     {
+       tree unique_type = discover_unique_type (type_for_uid (i));
+       splay_tree_insert (uid_to_unique_type, 
+ 			 (splay_tree_key) i, 
+ 			 (splay_tree_value) unique_type);
+       if (0)
+ 	fprintf(stderr, "dta i=%d,%d j=%d,%s\n", i, 
+ 		TYPE_UID(type_for_uid(i)),
+ 		TYPE_UID(unique_type), get_name_of_type(unique_type));
+     }
+ 
+   /* Get rid of the temporary data structures used to find the unique
+      type.  */
+   result = splay_tree_min (all_unique_types);
+   while (result)
+     {
+       struct type_brand_s * b = (struct type_brand_s *) result->key;
+       splay_tree_remove (all_unique_types, result->key);
+       free (b);
+       result = splay_tree_min (all_unique_types);
+     }
+   splay_tree_delete (all_unique_types);
+   all_unique_types = NULL;
+ 
+   /* Examine all of the types passed by value and mark any enclosed
+      pointer types as escaping.  */
+ 
+   EXECUTE_IF_SET_IN_BITMAP (global_types_exposed_parameter, 0, i, bi)
+     {
+       close_type_exposed_parameter (type_for_uid (i));
+     }
+   bitmap_clear (been_there_done_that);
+ 
+   /* Close the types for escape.  If something escapes, then any
+      enclosed types escape as well as any subtypes.  */
+ 
+   EXECUTE_IF_SET_IN_BITMAP (global_types_full_escape, 0, i, bi)
+     {
+       tree type = type_for_uid (i);
+       close_type_full_escape (type);
+     }
+   bitmap_clear (been_there_done_that);
+ 
+   result = splay_tree_min (uid_to_addressof_map);
+   while (result)
+     {
+       int uid = result->key;
+       tree type = type_for_uid (uid);
+       if (bitmap_bit_p (global_types_full_escape, uid))
+ 	/* If the type escaped, we will never use the map, so get rid
+ 	   of it.  */ 
+ 	delete_addressof_map (type);
+       else  
+ 	{
+ 	  if (unique_type_id_p (uid))
+ 	    /* Close the addressof map, i.e. copy all of the
+ 	       transitive substructures up to this level.  */
+ 	    close_addressof (uid);
+ 	  else
+ 	    /* This type is not the unique designate, so get rid of
+ 	       it.  */
+ 	    delete_addressof_map (type);
+ 	}
+       result = splay_tree_successor (uid_to_addressof_map, uid);
+     }
+   
+   /* If a type is set in global_types_full_escape, make sure that the
+      unique type is also set in that map.  */
+   EXECUTE_IF_SET_IN_BITMAP (global_types_full_escape, 0, i, bi)
+     {
+       unsigned int j = unique_type_id_for (i);
+       if (i != j)
+ 	{
+ 	  bitmap_set_bit(global_types_full_escape, j);
+ 	  bitmap_clear_bit(global_types_full_escape, i);
+ 	}
+     }
+ 
+   if (0)
+     { 
+       EXECUTE_IF_SET_IN_BITMAP (global_types_seen, 0, i, bi)
+ 	{
+ 	  /* The pointer types are in the global_types_full_escape bitmap
+ 	     but not in the backwards map.  */
+ 	  tree type = type_for_uid (i);
+ 	  fprintf(stderr, "type ");
+ 	  print_generic_expr (stderr, type, 0);
+ 	  if (bitmap_bit_p (global_types_full_escape, i))
+ 	    fprintf(stderr, " escaped\n");
+ 	  else if (i == unique_type_id_p (i))
+ 	    fprintf(stderr, " contained\n");
+ 	  else
+ 	    fprintf(stderr, " replaced\n");
+ 	}
+     }
+ 
+   /* Get rid of the subtype map.  */
+   result = splay_tree_min (uid_to_subtype_map);
+   while (result)
+     {
+       bitmap b = (bitmap)result->value;
+       BITMAP_XFREE(b);
+       splay_tree_remove (uid_to_subtype_map, result->key);
+       result = splay_tree_min (uid_to_subtype_map);
+     }
+   splay_tree_delete (uid_to_subtype_map);
+   uid_to_subtype_map = NULL;
+ 
+   BITMAP_XFREE (global_types_exposed_parameter);
+   BITMAP_XFREE (been_there_done_that);
+   BITMAP_XFREE (results_of_malloc);
+ 
+   cant_touch = 0;
+ }
+ 
+ 
  /* Produce the global information by preforming a transitive closure
     on the local information that was produced by ipa_analyze_function
     and ipa_analyze_variable.  */
  
  static void
  static_execute (void)
  {
*************** static_execute (void)
*** 1508,1523 ****
  	      break;
  	    }
  
- /* 	if (l->pure_const_state == IPA_PURE) */
- /* 	  { */
- /* 	    fprintf (stderr, " before %s(%d)=%d\n", cgraph_node_name (node),  */
- /* 		     node->uid, l->pure_const_state); */
- /* 	  l->pure_const_state = IPA_NEITHER; */
- 
- 
- /* 	  } */
- 
- 	
  	/* Any variables that are not in all_module_statics are
  	   removed from the local maps.  This will include all of the
  	   variables that were found to escape in the function
--- 2678,2683 ----
*************** static_execute (void)
*** 1732,1737 ****
--- 2892,2899 ----
  	}
      }
  
+   do_type_analysis ();
+ 
    /* Cleanup. */
    for (i = 0; i < order_pos; i++ )
      {
*************** static_execute (void)
*** 1748,1759 ****
        node_g->statics_not_read_by_decl_uid = BITMAP_ALLOC (&ipa_obstack);
        node_g->statics_not_written_by_decl_uid = BITMAP_ALLOC (&ipa_obstack);
  
-       /* FIXME -- PROFILE-RESTRUCTURE: Delete next 4 assignments.  */
-       node_g->statics_read_by_ann_uid = BITMAP_ALLOC (&ipa_obstack);
-       node_g->statics_written_by_ann_uid = BITMAP_ALLOC (&ipa_obstack);
-       node_g->statics_not_read_by_ann_uid = BITMAP_ALLOC (&ipa_obstack);
-       node_g->statics_not_written_by_ann_uid = BITMAP_ALLOC (&ipa_obstack);
- 
        if (node_g->statics_read_by_decl_uid != all_module_statics) 
  	{
  	  bitmap_and_compl (node_g->statics_not_read_by_decl_uid, 
--- 2910,2915 ----
*************** static_execute (void)
*** 1766,1771 ****
--- 2922,2933 ----
  			  all_module_statics,
  			  node_g->statics_written_by_decl_uid);
  
+       /* FIXME -- PROFILE-RESTRUCTURE: Delete next 4 assignments.  */
+       node_g->statics_read_by_ann_uid = BITMAP_ALLOC (&ipa_obstack);
+       node_g->statics_written_by_ann_uid = BITMAP_ALLOC (&ipa_obstack);
+       node_g->statics_not_read_by_ann_uid = BITMAP_ALLOC (&ipa_obstack);
+       node_g->statics_not_written_by_ann_uid = BITMAP_ALLOC (&ipa_obstack);
+ 
        w = node;
        while (w)
  	{
Index: gcc/ipa-static.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/ipa-static.h,v
retrieving revision 1.1.2.2
diff -c -3 -p -r1.1.2.2 ipa-static.h
*** gcc/ipa-static.h	3 Dec 2004 03:58:45 -0000	1.1.2.2
--- gcc/ipa-static.h	18 Jan 2005 18:45:01 -0000
*************** bitmap ipa_get_statics_read_global (tree
*** 120,124 ****
--- 120,128 ----
  bitmap ipa_get_statics_written_global (tree fn);
  bitmap ipa_get_statics_not_read_global (tree fn);
  bitmap ipa_get_statics_not_written_global (tree fn);
+ bool   ipa_static_type_contained_p (tree type);
+ bool   ipa_static_address_not_taken_of_field (tree record_type, tree field_type);
+ int    ipa_static_star_count_of_interesting_type (tree type); 
+ 
  
  #endif  /* GCC_IPA_STATIC_H  */
Index: gcc/tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dfa.c,v
retrieving revision 1.1.4.217.2.16
diff -c -3 -p -r1.1.4.217.2.16 tree-dfa.c
*** gcc/tree-dfa.c	15 Dec 2004 22:19:14 -0000	1.1.4.217.2.16
--- gcc/tree-dfa.c	18 Jan 2005 18:45:02 -0000
*************** create_stmt_ann (tree t)
*** 450,456 ****
    return ann;
  }
  
- 
  /* Create a new annotation for a tree T.  */
  
  tree_ann_t
--- 450,455 ----
Index: gcc/tree-eh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-eh.c,v
retrieving revision 1.1.2.23.2.13
diff -c -3 -p -r1.1.2.23.2.13 tree-eh.c
*** gcc/tree-eh.c	9 Jan 2005 14:17:45 -0000	1.1.2.23.2.13
--- gcc/tree-eh.c	18 Jan 2005 18:45:02 -0000
*************** tree_could_trap_p (tree expr)
*** 1833,1838 ****
--- 1833,1839 ----
  
        return !in_array_bounds_p (expr);
  
+     case MEM_REF:
      case INDIRECT_REF:
      case ALIGN_INDIRECT_REF:
      case MISALIGNED_INDIRECT_REF:
Index: gcc/tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow-inline.h,v
retrieving revision 1.1.2.66.2.9
diff -c -3 -p -r1.1.2.66.2.9 tree-flow-inline.h
*** gcc/tree-flow-inline.h	9 Jan 2005 14:17:45 -0000	1.1.2.66.2.9
--- gcc/tree-flow-inline.h	18 Jan 2005 18:45:02 -0000
*************** get_stmt_ann (tree stmt)
*** 66,72 ****
    return (ann) ? ann : create_stmt_ann (stmt);
  }
  
- 
  /* Return the annotation type for annotation ANN.  */
  static inline enum tree_ann_type
  ann_type (tree_ann_t ann)
--- 66,71 ----
Index: gcc/tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 1.1.4.187.2.22
diff -c -3 -p -r1.1.4.187.2.22 tree-flow.h
*** gcc/tree-flow.h	15 Dec 2004 22:19:15 -0000	1.1.4.187.2.22
--- gcc/tree-flow.h	18 Jan 2005 18:45:03 -0000
*************** bool tree_duplicate_loop_to_header_edge 
*** 705,710 ****
--- 705,711 ----
  					 unsigned int *, int);
  struct loop *tree_ssa_loop_version (struct loops *, struct loop *, tree,
  				    basic_block *);
+ void set_ref_original (tree, tree);
  
  /* In tree-ssa-loop-im.c  */
  /* The possibilities of statement movement.  */
Index: gcc/tree-gimple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-gimple.c,v
retrieving revision 2.1.2.12
diff -c -3 -p -r2.1.2.12 tree-gimple.c
*** gcc/tree-gimple.c	16 Dec 2004 01:20:26 -0000	2.1.2.12
--- gcc/tree-gimple.c	18 Jan 2005 18:45:03 -0000
*************** is_gimple_condexpr (tree t)
*** 160,167 ****
  bool
  is_gimple_addressable (tree t)
  {
!   return (is_gimple_id (t) || handled_component_p (t)
! 	  || INDIRECT_REF_P (t));
  }
  
  /* Return true if T is function invariant.  Or rather a restricted
--- 160,167 ----
  bool
  is_gimple_addressable (tree t)
  {
!   return (is_gimple_id (t) || handled_component_p (t) 
! 	  || TREE_CODE (t) == MEM_REF || INDIRECT_REF_P (t));
  }
  
  /* Return true if T is function invariant.  Or rather a restricted
*************** bool
*** 379,385 ****
  is_gimple_min_lval (tree t)
  {
    return (is_gimple_id (t)
! 	  || TREE_CODE (t) == INDIRECT_REF);
  }
  
  /* Return true if T is a typecast operation.  */
--- 379,386 ----
  is_gimple_min_lval (tree t)
  {
    return (is_gimple_id (t)
! 	  || TREE_CODE (t) == INDIRECT_REF
! 	  || TREE_CODE (t) == MEM_REF);
  }
  
  /* Return true if T is a typecast operation.  */
*************** get_call_expr_in (tree t)
*** 419,445 ****
    return NULL_TREE;
  }
  
- /* Given a memory reference T, will return the variable at the bottom
-    of the access.  Unlike get_base_address below, this will recurse
-    thru INDIRECT_REFS.  */
- 
- tree
- get_base_var (tree t)
- {
-   if ((TREE_CODE (t) == EXC_PTR_EXPR) || (TREE_CODE (t) == FILTER_EXPR))
-     return t;
- 
-   while (!SSA_VAR_P (t) 
- 	 && (!CONSTANT_CLASS_P (t))
- 	 && TREE_CODE (t) != LABEL_DECL
- 	 && TREE_CODE (t) != FUNCTION_DECL
- 	 && TREE_CODE (t) != CONST_DECL)
-     {
-       t = TREE_OPERAND (t, 0);
-     }
-   return t;
- } 
- 
  /* Given a memory reference expression T, return its base address.
     The base address of a memory reference expression is the main
     object being referenced.  For instance, the base address for
--- 420,425 ----
*************** get_base_address (tree t)
*** 458,464 ****
    if (SSA_VAR_P (t)
        || TREE_CODE (t) == STRING_CST
        || TREE_CODE (t) == CONSTRUCTOR
!       || INDIRECT_REF_P (t))
      return t;
    else
      return NULL_TREE;
--- 438,445 ----
    if (SSA_VAR_P (t)
        || TREE_CODE (t) == STRING_CST
        || TREE_CODE (t) == CONSTRUCTOR
!       || INDIRECT_REF_P (t)
!       || TREE_CODE (t) == MEM_REF)
      return t;
    else
      return NULL_TREE;
Index: gcc/tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.26.2.83.2.27
diff -c -3 -p -r1.26.2.83.2.27 tree-inline.c
*** gcc/tree-inline.c	15 Jan 2005 21:14:34 -0000	1.26.2.83.2.27
--- gcc/tree-inline.c	18 Jan 2005 18:45:04 -0000
*************** estimate_num_insns_1 (tree *tp, int *wal
*** 1723,1728 ****
--- 1723,1729 ----
      case BLOCK:
      case COMPONENT_REF:
      case BIT_FIELD_REF:
+     case MEM_REF:
      case INDIRECT_REF:
      case ARRAY_REF:
      case ARRAY_RANGE_REF:
Index: gcc/tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.122.2.33
diff -c -3 -p -r1.1.4.122.2.33 tree-optimize.c
*** gcc/tree-optimize.c	18 Jan 2005 18:24:19 -0000	1.1.4.122.2.33
--- gcc/tree-optimize.c	18 Jan 2005 18:45:04 -0000
*************** init_tree_optimization_passes (void)
*** 402,407 ****
--- 402,408 ----
    NEXT_PASS (pass_init_datastructures);
    NEXT_PASS (pass_all_optimizations);
    NEXT_PASS (pass_warn_function_return);
+   NEXT_PASS (pass_lower_memref);
    NEXT_PASS (pass_mudflap_2);
    NEXT_PASS (pass_free_datastructures);
    NEXT_PASS (pass_expand);
*************** init_tree_optimization_passes (void)
*** 411,420 ****
--- 412,423 ----
    p = &pass_all_optimizations.sub;
    NEXT_PASS (pass_referenced_vars);
    NEXT_PASS (pass_maybe_create_global_var);
+   NEXT_PASS (pass_lower_memref);
    NEXT_PASS (pass_build_ssa);
    NEXT_PASS (pass_may_alias);
    NEXT_PASS (pass_rename_ssa_copies);
    NEXT_PASS (pass_early_warn_uninitialized);
+   NEXT_PASS (pass_eliminate_useless_stores);
    NEXT_PASS (pass_dce);
    NEXT_PASS (pass_dominator);
    NEXT_PASS (pass_redundant_phi);
Index: gcc/tree-pass.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pass.h,v
retrieving revision 1.1.2.12.2.15
diff -c -3 -p -r1.1.2.12.2.15 tree-pass.h
*** gcc/tree-pass.h	9 Jan 2005 14:17:49 -0000	1.1.2.12.2.15
--- gcc/tree-pass.h	18 Jan 2005 18:45:04 -0000
*************** extern struct tree_opt_pass pass_expand;
*** 193,200 ****
  extern struct tree_opt_pass pass_rest_of_compilation;
  extern struct tree_opt_pass pass_fre;
  extern struct tree_opt_pass pass_linear_transform;
  extern struct tree_opt_pass pass_maybe_create_global_var;
! 
  extern struct tree_opt_pass pass_ipa_inline;
  extern struct tree_opt_pass pass_ipa_static;
  
--- 193,201 ----
  extern struct tree_opt_pass pass_rest_of_compilation;
  extern struct tree_opt_pass pass_fre;
  extern struct tree_opt_pass pass_linear_transform;
+ extern struct tree_opt_pass pass_eliminate_useless_stores;
  extern struct tree_opt_pass pass_maybe_create_global_var;
! extern struct tree_opt_pass pass_lower_memref;
  extern struct tree_opt_pass pass_ipa_inline;
  extern struct tree_opt_pass pass_ipa_static;
  
Index: gcc/tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pretty-print.c,v
retrieving revision 1.1.2.73.2.17
diff -c -3 -p -r1.1.2.73.2.17 tree-pretty-print.c
*** gcc/tree-pretty-print.c	15 Dec 2004 22:19:20 -0000	1.1.2.73.2.17
--- gcc/tree-pretty-print.c	18 Jan 2005 18:45:04 -0000
*************** dump_generic_node (pretty_printer *buffe
*** 444,449 ****
--- 444,458 ----
        NIY;
        break;
  
+     case MEM_REF:
+       {
+ 	dump_generic_node (buffer, MEM_REF_SYMBOL (node), spc, flags, false);
+ 	pp_string (buffer, "[");
+ 	dump_generic_node (buffer, MEM_REF_INDEX (node), spc, flags, false);
+ 	pp_string (buffer, "]");
+       }
+       break;
+ 
      case ARRAY_TYPE:
        {
  	tree tmp;
Index: gcc/tree-ssa-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-alias.c,v
retrieving revision 1.1.2.1.2.15
diff -c -3 -p -r1.1.2.1.2.15 tree-ssa-alias.c
*** gcc/tree-ssa-alias.c	9 Jan 2005 14:17:50 -0000	1.1.2.1.2.15
--- gcc/tree-ssa-alias.c	18 Jan 2005 18:45:05 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 42,48 ****
  #include "tree-pass.h"
  #include "convert.h"
  #include "params.h"
! 
  
  /* Structure to map a variable to its alias set and keep track of the
     virtual operands that will be needed to represent it.  */
--- 42,48 ----
  #include "tree-pass.h"
  #include "convert.h"
  #include "params.h"
! #include "ipa-static.h"
  
  /* 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_stats_d
*** 124,129 ****
--- 124,131 ----
    unsigned int simple_resolved;
    unsigned int tbaa_queries;
    unsigned int tbaa_resolved;
+   unsigned int structnoaddress_queries;
+   unsigned int structnoaddress_resolved;
  };
  
  
*************** find_ptr_dereference (tree *tp, int *wal
*** 575,580 ****
--- 577,585 ----
    if (INDIRECT_REF_P (*tp)
        && TREE_OPERAND (*tp, 0) == ptr)
      return *tp;
+   else if (TREE_CODE (*tp) == MEM_REF
+ 	   && MEM_REF_SYMBOL (*tp) == ptr)
+     return *tp;
  
    return NULL_TREE;
  }
*************** may_alias_p (tree ptr, HOST_WIDE_INT mem
*** 1638,1643 ****
--- 1643,1705 ----
        return false;
      }
  
+   /* If var is a record or union type, ptr cannot point into var
+      unless there is some operation explicit address operation in the
+      program that can reference a field of the ptr's dereferenced
+      type.  This also assumes that the types of both var and ptr are
+      contained within the compilation unit, and that there is no fancy
+      addressing arithmetic associated with any of the types
+      involved.  */
+ 
+   {
+     tree ptr_type = TREE_TYPE (ptr);
+ 
+     /* The star counts are -1 if the type at the end of the pointer_to
+        chain is not a record or union type. */
+     if (ipa_static_star_count_of_interesting_type (var) >= 0)
+       {
+ 	int ptr_star_count = 0;
+ 	/* ipa_static_star_count_of_interesting_type is a little too
+ 	   restrictive for the pointer type, need to allow pointers to
+ 	   primitive types as long as those types cannot be pointers
+ 	   to everything.  */
+ 	/* Strip the *'s off.  */
+ 	while (POINTER_TYPE_P (ptr_type))
+ 	  {
+ 	    ptr_type = TREE_TYPE (ptr_type);
+ 	    ptr_star_count++;
+ 	  }
+ 
+ 	/* There does not appear to be a better test to see if the
+ 	   pointer type was one of the pointer to everything
+ 	   types.  */
+ 	if (TREE_CODE (ptr_type) == CHAR_TYPE
+ 	    && TREE_CODE (ptr_type) == VOID_TYPE)
+ 	  ptr_star_count = -1;
+ 
+ 	if (ptr_star_count > 0)
+ 	  {
+ 	    alias_stats.structnoaddress_queries++;
+ 	    if (ipa_static_address_not_taken_of_field (TREE_TYPE (var), 
+ 						TREE_TYPE (ptr_type)))
+ 	      {
+ 		alias_stats.structnoaddress_resolved++;
+ 		alias_stats.alias_noalias++;
+ 		return false;
+ 	      }
+ 	  }
+ 	else if (ptr_star_count == 0)
+ 	  {
+ 	    /* If ptr_type was not really a pointer to type, it cannot
+ 	       alias.  */
+ 	    alias_stats.structnoaddress_queries++;
+ 	    alias_stats.structnoaddress_resolved++;
+ 	    alias_stats.alias_noalias++;
+ 	    return false;
+ 	  }
+       }
+   }
+ 
    alias_stats.alias_mayalias++;
    return true;
  }
*************** dump_alias_stats (FILE *file)
*** 2236,2241 ****
--- 2298,2307 ----
  	   alias_stats.tbaa_queries);
    fprintf (file, "Total TBAA resolved:\t%u\n",
  	   alias_stats.tbaa_resolved);
+   fprintf (file, "Total non-addressable structure type queries:\t%u\n",
+ 	   alias_stats.structnoaddress_queries);
+   fprintf (file, "Total non-addressable structure type resolved:\t%u\n",
+ 	   alias_stats.structnoaddress_resolved);
  }
    
  
Index: gcc/tree-ssa-loop-im.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-im.c,v
retrieving revision 2.3.2.8
diff -c -3 -p -r2.3.2.8 tree-ssa-loop-im.c
*** gcc/tree-ssa-loop-im.c	16 Dec 2004 01:20:35 -0000	2.3.2.8
--- gcc/tree-ssa-loop-im.c	18 Jan 2005 18:45:05 -0000
*************** for_each_index (tree *addr_p, bool (*cbc
*** 174,179 ****
--- 174,191 ----
  	case RESULT_DECL:
  	  return true;
  
+ 	case MEM_REF:
+ 	  idx = &MEM_REF_SYMBOL (*addr_p);
+ 	  if (*idx
+ 	      && !cbck (*addr_p, idx, data))
+ 	    return false;
+ 	  return true;
+ 	  idx = &MEM_REF_INDEX (*addr_p);
+ 	  if (*idx
+ 	      && !cbck (*addr_p, idx, data))
+ 	    return false;
+ 	  return true;
+ 
  	default:
      	  gcc_unreachable ();
  	}
Index: gcc/tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.c,v
retrieving revision 1.1.2.9.2.17
diff -c -3 -p -r1.1.2.9.2.17 tree-ssa-operands.c
*** gcc/tree-ssa-operands.c	15 Dec 2004 22:19:27 -0000	1.1.2.9.2.17
--- gcc/tree-ssa-operands.c	18 Jan 2005 18:45:06 -0000
*************** static void note_addressable (tree, stmt
*** 141,146 ****
--- 141,147 ----
  static void get_expr_operands (tree, tree *, int);
  static void get_asm_expr_operands (tree);
  static void get_indirect_ref_operands (tree, tree, int);
+ static void get_mem_ref_operands (tree, tree *, int);
  static void get_call_expr_operands (tree, tree);
  static inline void append_def (tree *);
  static inline void append_use (tree *);
*************** build_ssa_operands (tree stmt, stmt_ann_
*** 912,918 ****
  	if (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
  	  lhs = TREE_OPERAND (lhs, 0);
  
! 	if (TREE_CODE (lhs) != ARRAY_REF && TREE_CODE (lhs) != ARRAY_RANGE_REF
  	    && TREE_CODE (lhs) != COMPONENT_REF
  	    && TREE_CODE (lhs) != BIT_FIELD_REF
  	    && TREE_CODE (lhs) != REALPART_EXPR
--- 913,921 ----
  	if (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
  	  lhs = TREE_OPERAND (lhs, 0);
  
! 	if (TREE_CODE (lhs) != ARRAY_REF 
! 	    && TREE_CODE (lhs) != MEM_REF
! 	    && TREE_CODE (lhs) != ARRAY_RANGE_REF
  	    && TREE_CODE (lhs) != COMPONENT_REF
  	    && TREE_CODE (lhs) != BIT_FIELD_REF
  	    && TREE_CODE (lhs) != REALPART_EXPR
*************** get_expr_operands (tree stmt, tree *expr
*** 1092,1097 ****
--- 1095,1104 ----
        get_indirect_ref_operands (stmt, expr, flags);
        return;
  
+     case MEM_REF:
+       get_mem_ref_operands (stmt, expr_p, flags);
+       return;
+ 
      case ARRAY_REF:
      case ARRAY_RANGE_REF:
        /* Treat array references as references to the virtual variable
*************** get_expr_operands (tree stmt, tree *expr
*** 1167,1172 ****
--- 1174,1180 ----
  	if (TREE_CODE (op) == WITH_SIZE_EXPR)
  	  op = TREE_OPERAND (expr, 0);
  	if (TREE_CODE (op) == ARRAY_REF
+ 	    || TREE_CODE (op) == MEM_REF
  	    || TREE_CODE (op) == ARRAY_RANGE_REF
  	    || TREE_CODE (op) == COMPONENT_REF
  	    || TREE_CODE (op) == REALPART_EXPR
*************** get_indirect_ref_operands (tree stmt, tr
*** 1374,1380 ****
  
    /* Stores into INDIRECT_REF operands are never killing definitions.  */
    flags &= ~opf_kill_def;
! 
    if (SSA_VAR_P (ptr))
      {
        struct ptr_info_def *pi = NULL;
--- 1382,1388 ----
  
    /* Stores into INDIRECT_REF operands are never killing definitions.  */
    flags &= ~opf_kill_def;
!   
    if (SSA_VAR_P (ptr))
      {
        struct ptr_info_def *pi = NULL;
*************** get_indirect_ref_operands (tree stmt, tr
*** 1453,1458 ****
--- 1461,1525 ----
    get_expr_operands (stmt, pptr, opf_none);
  }
  
+ /* A subroutine of get_expr_operands to handle MEM_REF.  */
+ 
+ static void
+ get_mem_ref_operands (tree stmt, tree *expr_p, int flags)
+ {
+   stmt_ann_t s_ann  = stmt_ann (stmt);
+   tree expr = *expr_p;
+   tree ptr;
+ 
+   /* First record the real operands.  */
+   get_expr_operands (stmt, &MEM_REF_INDEX (expr), opf_none);
+ 
+   ptr = MEM_REF_SYMBOL (expr);
+ 
+   if (SSA_VAR_P (ptr))
+     {
+       struct ptr_info_def *pi = NULL;
+ 
+       /* If PTR has flow-sensitive points-to information, use it.  */
+       if (TREE_CODE (ptr) == SSA_NAME
+ 	  && (pi = SSA_NAME_PTR_INFO (ptr)) != NULL
+ 	  && pi->name_mem_tag)
+ 	{
+ 	  /* PTR has its own memory tag.  Use it.  */
+ 	  add_stmt_operand (&pi->name_mem_tag, s_ann, flags);
+ 	}
+       else
+ 	{
+ 	  /* If PTR is not an SSA_NAME or it doesn't have a name
+ 	     tag, use its type memory tag.  */
+ 	  var_ann_t v_ann;
+ 
+ 	  /* If we are emitting debugging dumps, display a warning if
+ 	     PTR is an SSA_NAME with no flow-sensitive alias
+ 	     information.  That means that we may need to compute
+ 	     aliasing again.  */
+ 	  if (dump_file
+ 	      && TREE_CODE (ptr) == SSA_NAME
+ 	      && pi == NULL)
+ 	    {
+ 	      fprintf (dump_file,
+ 		  "NOTE: no flow-sensitive alias info for ");
+ 	      print_generic_expr (dump_file, ptr, dump_flags);
+ 	      fprintf (dump_file, " in ");
+ 	      print_generic_stmt (dump_file, stmt, dump_flags);
+ 	    }
+ 
+ 	  if (TREE_CODE (ptr) == SSA_NAME)
+ 	    ptr = SSA_NAME_VAR (ptr);
+ 	  v_ann = var_ann (ptr);
+ 	  if (v_ann->type_mem_tag)
+ 	    add_stmt_operand (&v_ann->type_mem_tag, s_ann, flags);
+ 	}
+     }
+   /* Add a use operand for the base pointer */
+   get_expr_operands (stmt, &MEM_REF_SYMBOL (expr), opf_none);
+ 
+ }
+ 
  /* A subroutine of get_expr_operands to handle CALL_EXPR.  */
  
  static void
Index: gcc/tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-pre.c,v
retrieving revision 1.1.4.129.2.15
diff -c -3 -p -r1.1.4.129.2.15 tree-ssa-pre.c
*** gcc/tree-ssa-pre.c	15 Dec 2004 22:19:27 -0000	1.1.4.129.2.15
--- gcc/tree-ssa-pre.c	18 Jan 2005 18:45:06 -0000
*************** struct tree_opt_pass pass_fre =
*** 2176,2178 ****
--- 2176,2307 ----
    TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa, /* todo_flags_finish */
    0					/* letter */
  };
+ 
+ /* Return true if T is a copy statement between two ssa names.  */
+ 
+ static bool
+ is_copy_stmt (tree t)
+ {
+   
+   if (TREE_CODE (t) != MODIFY_EXPR)
+     return false;
+   if (TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME 
+       && TREE_CODE (TREE_OPERAND (t, 1)) == SSA_NAME)
+     return true;
+   return false;
+ }
+ 
+ /* Starting from START, walk copy statements till we hit a statement with a
+    VUSE or a non-copy statement.  */
+ 
+ static tree 
+ follow_copies_till_vuse (tree start)
+ {
+   if (NUM_VUSES (VUSE_OPS (stmt_ann (start))) != 0)
+     return start;
+   if (is_copy_stmt (start))
+     return follow_copies_till_vuse (SSA_NAME_DEF_STMT (TREE_OPERAND (start, 1)));
+   return NULL;
+ }
+ 
+ /* Gate and execute functions for eliminate useless stores.	
+    The goal here is to recognize the pattern *x = ... *x, and eliminate the
+    store because the value hasn't changed.  Store copy/const prop won't
+    do this because making *more* loads (IE propagating *x) is not a win, so it
+    ignores them.  
+    This pass is currently geared completely towards static variable store
+    elimination.
+    */
+ 
+ static void
+ do_eustores (void)
+ {
+   basic_block bb;
+   /* For each basic block
+        For each statement (STMT) in the block
+          if STMT is a stores of the pattern *x = y
+            follow the chain of definitions for y, until we hit a non-copy
+ 	   statement or a statement with a vuse. 
+ 	     if the statement we arrive at is a vuse of the operand we killed,
+ 	     accessed through the same memory operation, then we have a
+ 	     useless store (because it is *x = ... = *x).
+   */
+ 	  
+   FOR_EACH_BB (bb)
+     {
+       block_stmt_iterator bsi;
+       for (bsi = bsi_start (bb);
+ 	   !bsi_end_p (bsi);)
+ 	{
+ 	  tree stmt = bsi_stmt (bsi);
+ 	  stmt_ann_t ann = stmt_ann (stmt);
+ 	  tree startat;
+ 	  tree kill;	  
+ 	  tree found;
+ 	  
+ 	  
+ 	  if (NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) != 1
+ 	      || TREE_CODE (stmt) != MODIFY_EXPR
+ 	      || TREE_CODE (TREE_OPERAND (stmt, 1)) != SSA_NAME)
+ 	    {
+ 	      bsi_next (&bsi);
+ 	      continue;
+ 	    }
+ 	  kill = V_MUST_DEF_KILL (V_MUST_DEF_OPS (ann), 0); 
+ 	  startat = TREE_OPERAND (stmt, 1);
+ 	  startat = SSA_NAME_DEF_STMT (startat);
+ 	  found = follow_copies_till_vuse (startat);
+ 	  if (found)
+ 	    {	   
+ 	      stmt_ann_t foundann = stmt_ann (found);
+ 	      if (NUM_VUSES (VUSE_OPS (foundann)) != 1
+ 		  || VUSE_OP (VUSE_OPS (foundann), 0) != kill
+ 		  || !operand_equal_p (TREE_OPERAND (found, 1), TREE_OPERAND (stmt, 0), 0))
+ 		{
+ 		  bsi_next (&bsi);
+ 		  continue;
+ 		}
+ 	      if (dump_file)
+ 		{
+ 		  fprintf (dump_file, "Eliminating useless store ");
+ 		  print_generic_stmt (dump_file, stmt, 0);
+ 		}
+ 	      bitmap_set_bit (vars_to_rename, 
+ 	      var_ann (TREE_OPERAND (stmt, 0))->uid);
+ 	      
+ 	      bsi_remove (&bsi);
+ 	    }
+ 	  else
+ 	    {
+ 	      bsi_next (&bsi);
+ 	      continue;
+ 	    }
+ 	}
+ 
+     }
+ }
+ 
+ static bool
+ gate_eustores(void)
+ {
+   return flag_unit_at_a_time != 0; 
+ }
+ 
+ struct tree_opt_pass pass_eliminate_useless_stores =
+ {
+   "eustores",				/* name */
+   gate_eustores,				/* gate */
+   NULL, NULL,				/* IPA analysis */
+   do_eustores,				/* execute */
+   NULL, NULL,				/* IPA modification */
+   NULL,					/* sub */
+   NULL,					/* next */
+   0,					/* static_pass_number */
+   0,				/* tv_id */
+   PROP_cfg | PROP_ssa | PROP_alias,	/* properties_required */
+   0,					/* properties_provided */
+   0,					/* properties_destroyed */
+   0,					/* todo_flags_start */
+   TODO_rename_vars | TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa, /* todo_flags_finish */
+   0					/* letter */
+ };
Index: gcc/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.263.2.80.2.17
diff -c -3 -p -r1.263.2.80.2.17 tree.c
*** gcc/tree.c	9 Jan 2005 14:17:55 -0000	1.263.2.80.2.17
--- gcc/tree.c	18 Jan 2005 18:45:08 -0000
*************** build4_stat (enum tree_code code, tree t
*** 2674,2679 ****
--- 2674,2680 ----
    return t;
  }
  
+ 
  /* Backup definition for non-gcc build compilers.  */
  
  tree
Index: gcc/tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.def,v
retrieving revision 1.52.2.24.2.13
diff -c -3 -p -r1.52.2.24.2.13 tree.def
*** gcc/tree.def	9 Jan 2005 14:17:57 -0000	1.52.2.24.2.13
--- gcc/tree.def	18 Jan 2005 18:45:08 -0000
*************** DEFTREECODE (WITH_SIZE_EXPR, "with_size_
*** 921,926 ****
--- 921,933 ----
     generated by the builtin targetm.vectorize.mask_for_load_builtin_decl.  */
  DEFTREECODE (REALIGN_LOAD_EXPR, "realign_load", tcc_expression, 3)
  
+ /* Array like memory addressing for pointers.  Operands are SYMBOL
+    (static or global variable),INDEX (register), STEP (integer
+    constant)  Corresponding address is SYMBOL + (INDEX * TYPE_SIZE_UNIT
+    (TREE_TYPE (SYMBOL))).  */
+ 
+ DEFTREECODE (MEM_REF, "mem_ref", tcc_reference, 2)
+ 
  /*
  Local variables:
  mode:c
Index: gcc/tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.169.2.21
diff -c -3 -p -r1.342.2.169.2.21 tree.h
*** gcc/tree.h	9 Jan 2005 14:17:58 -0000	1.342.2.169.2.21
--- gcc/tree.h	18 Jan 2005 18:45:10 -0000
*************** struct tree_vec GTY(())
*** 1172,1180 ****
  #define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I)
  #define TREE_COMPLEXITY(NODE) (EXPR_CHECK (NODE)->exp.complexity)
  
! /* In INDIRECT_REF, ALIGN_INDIRECT_REF, MISALIGNED_INDIRECT_REF.  */
! #define REF_ORIGINAL(NODE) TREE_CHAIN (TREE_CHECK3 (NODE, 	\
! 	INDIRECT_REF, ALIGN_INDIRECT_REF, MISALIGNED_INDIRECT_REF))
  
  /* In a LOOP_EXPR node.  */
  #define LOOP_EXPR_BODY(NODE) TREE_OPERAND_CHECK_CODE (NODE, LOOP_EXPR, 0)
--- 1172,1180 ----
  #define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I)
  #define TREE_COMPLEXITY(NODE) (EXPR_CHECK (NODE)->exp.complexity)
  
! /* In INDIRECT_REF, ALIGN_INDIRECT_REF, MISALIGNED_INDIRECT_REF, MEM_REF.  */
! #define REF_ORIGINAL(NODE) TREE_CHAIN (TREE_CHECK4 (NODE, 	\
! 	INDIRECT_REF, ALIGN_INDIRECT_REF, MISALIGNED_INDIRECT_REF, MEM_REF))
  
  /* In a LOOP_EXPR node.  */
  #define LOOP_EXPR_BODY(NODE) TREE_OPERAND_CHECK_CODE (NODE, LOOP_EXPR, 0)
*************** struct tree_vec GTY(())
*** 1241,1246 ****
--- 1241,1250 ----
  #define CASE_HIGH(NODE)         	TREE_OPERAND ((NODE), 1)
  #define CASE_LABEL(NODE)		TREE_OPERAND ((NODE), 2)
  
+ /* The operands of a MEM_REF.  */
+ #define MEM_REF_SYMBOL(NODE) (TREE_OPERAND (MEM_REF_CHECK (NODE), 0))
+ #define MEM_REF_INDEX(NODE) (TREE_OPERAND (MEM_REF_CHECK (NODE), 1))
+ 
  /* The operands of a BIND_EXPR.  */
  #define BIND_EXPR_VARS(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 0))
  #define BIND_EXPR_BODY(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 1))
*************** struct tree_binfo GTY (())
*** 2162,2171 ****
  
  /* Nonzero in a FUNCTION_DECL means this function should be treated
     as if it were a malloc, meaning it returns a pointer that is
!    not an alias.  */
  #define DECL_IS_MALLOC(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.malloc_flag)
  
  /* Nonzero in a FUNCTION_DECL means this function should be treated
     as "pure" function (like const function, but may read global memory).  */
  #define DECL_IS_PURE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.pure_flag)
  
--- 2166,2180 ----
  
  /* Nonzero in a FUNCTION_DECL means this function should be treated
     as if it were a malloc, meaning it returns a pointer that is
!    not an alias.  It also means that even though it returns a void* 
!    pointer, the value returned does not cause the type to escape.  */
  #define DECL_IS_MALLOC(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.malloc_flag)
  
  /* Nonzero in a FUNCTION_DECL means this function should be treated
+    as if it were a free, meaning it takes a pointer to a void* but the cast for this pararmeter does not cause the type to escape.  */
+ #define DECL_IS_FREE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.free_flag)
+ 
+ /* Nonzero in a FUNCTION_DECL means this function should be treated
     as "pure" function (like const function, but may read global memory).  */
  #define DECL_IS_PURE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.pure_flag)
  
*************** struct tree_decl GTY(())
*** 2361,2371 ****
    unsigned lang_flag_5 : 1;
    unsigned lang_flag_6 : 1;
    unsigned lang_flag_7 : 1;
! 
    unsigned possibly_inlined : 1;
    unsigned preserve_flag: 1;
    unsigned gimple_formal_temp : 1;
!   /* 13 unused bits.  */
  
    union tree_decl_u1 {
      /* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is
--- 2370,2381 ----
    unsigned lang_flag_5 : 1;
    unsigned lang_flag_6 : 1;
    unsigned lang_flag_7 : 1;
!   
    unsigned possibly_inlined : 1;
    unsigned preserve_flag: 1;
    unsigned gimple_formal_temp : 1;
!   unsigned free_flag : 1;
!   /* 11 unused bits.  */
  
    union tree_decl_u1 {
      /* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is
*************** extern rtx emit_line_note (location_t);
*** 3674,3679 ****
--- 3684,3691 ----
  #define ECF_ALWAYS_RETURN	512
  /* Create libcall block around the call.  */
  #define ECF_LIBCALL_BLOCK	1024
+ /* Nonzero if this is a call to free or a related function.  */
+ #define ECF_FREE		2048
  
  extern int flags_from_decl_or_type (tree);
  extern int call_expr_flags (tree);
*************** extern tree walk_tree_without_duplicates
*** 3794,3800 ****
  /* In tree-dump.c */
  
  /* Different tree dump places.  When you add new tree dump places,
!    extend the DUMP_FILES array in tree-dump.c.  */
  enum tree_dump_index
  {
    TDI_none,			/* No dump */
--- 3806,3812 ----
  /* In tree-dump.c */
  
  /* Different tree dump places.  When you add new tree dump places,
! /   extend the DUMP_FILES array in tree-dump.c.  */
  enum tree_dump_index
  {
    TDI_none,			/* No dump */
*************** extern bool in_gimple_form;
*** 3925,3931 ****
  extern bool thread_through_all_blocks (void);
  
  /* In tree-gimple.c.  */
- extern tree get_base_var (tree t);
  extern tree get_base_address (tree t);
  
  #endif  /* GCC_TREE_H  */
--- 3937,3937 ----
  

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