public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Razya Ladelsky <RAZYA@il.ibm.com>
To: gcc-patches@gcc.gnu.org
Cc: stevenb@suse.de, hubicka@ucw.cz,
	Mircea Namolaru <NAMOLARU@il.ibm.com>,
	Ayal Zaks <ZAKS@il.ibm.com>
Subject: [tree-profiling-branch PATCH] Function cloning + IPCP extension  (RESUBMISSION)
Date: Sun, 10 Oct 2004 15:38:00 -0000	[thread overview]
Message-ID: <OF5CDC40B7.BBE1ECAB-ONC2256F29.0053D8D3-C2256F29.0053FD4F@il.ibm.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 608 bytes --]

Hello,

Attached is the patch modified according to the suggestions
we received.

This patch implements function cloning.
It also contains extension to IPCP (Interprocedural constant propagation) 
optimization http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00998.html for 
using function cloning.

Now in order to enable IPCP for a given application, we should use the 
command
gcc -fipa-cp -combine file1.c file2.c file3.c 
where file1.c, file2.c, file3.c are the files of the application.

Bootstrapped and regression tests successfully passed on POWER4.

Comments are welcome.

Thanks,
Razya and Revital.



[-- Attachment #2: ChangeLog5_10 --]
[-- Type: application/octet-stream, Size: 2098 bytes --]

2004-10-05  Razya Ladelsky  <razya@il.ibm.com>

	* ipa_prop.c: Update IPA constant propagation.
	* ipa_prop.h: Same.
	* cgraph.h:  Add interface for accessing existing data structures,
	Support for cloning.
	* Makefile.in (CGRAPH_H): Add dependency to varray.h.
        (ipa_prop.c): Change dependencies.
	* common.opt: Remove fipa-no-cloning flag.
	* cgraphunit.c (cgraph_optimize, cgraph_remove_unreachable_nodes):  
	Support for IPA constant propagation.
	(update_call_expr, cgraph_copy_node_for_versioning, 
	cgraph_function_versioning): New functions to support versioning.
	* cgraph.c: (cgraph_copy_node_callees, cgraph_copy_local_info): New
	functions to support versioning.
	* integrate.c: (copy_decl_for_versioning): New function. Copies decl tree
	node for the purpose of versioning.
	* integrate.h:   (copy_decl_for_versioning): New declaration.
        * langhooks-def.h: (lhd_tree_versioning_cannot_version_tree_fn): Declare.
        (LANG_HOOKS_TREE_VERSIONING_CANNOT_VERSION_TREE_FN): New definition.
	* langhooks.c: (lhd_tree_versioning_cannot_version_tree_fn):
	Check whether there are language-specific reasons for not
	creating a new version to a given function.
        * langhooks.h: (struct lang_hooks_for_tree_versioning,
	tree_versioning): New declaration.
        * gimplify.c: (create_function_name): New function.
	* tree-gimple.h: (create_function_name): New declaration.
	* tree-inline.c: (struct inline_data): New field to support versioning.
	(copy_arguments_for_versioning, version_body,
	copy_static_chain, function_versionable_p,
	tree_function_versioning): New functions to support tree
	function versioning.
	(remap_decl, copy_body_r):  Support function versioning.
	* tree-inline.h: (tree_versionable_function_p,
	tree_function_versioning): New declarations.
	* cp/cp-objcp-common.h: (LANG_HOOKS_TREE_VERSIONING_CA
	NNOT_VERSION_TREE_FN): New definition.
	* cp/cp-tree.h: (cp_cannot_version_tree_fn): New declaration.
	* cp/tree.c: (cp_cannot_version_tree_fn): Don't auto-version
	constructors/destructors and operators.

[-- Attachment #3: diff_5_10 --]
[-- Type: application/octet-stream, Size: 86534 bytes --]

Index: Makefile.in
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.179.2.18
diff -c -3 -p -r1.903.2.179.2.18 Makefile.in
*** Makefile.in	25 Sep 2004 23:17:22 -0000	1.903.2.179.2.18
--- Makefile.in	5 Oct 2004 08:35:53 -0000
*************** SCHED_INT_H = sched-int.h $(INSN_ATTR_H)
*** 703,709 ****
  INTEGRATE_H = integrate.h varray.h
  CFGLAYOUT_H = cfglayout.h $(BASIC_BLOCK_H)
  CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $(RTL_H)
! CGRAPH_H = cgraph.h bitmap.h tree.h $(HASHTAB_H)
  DF_H = df.h bitmap.h sbitmap.h $(BASIC_BLOCK_H)
  DDG_H = ddg.h sbitmap.h $(DF_H)
  GCC_H = gcc.h version.h
--- 703,709 ----
  INTEGRATE_H = integrate.h varray.h
  CFGLAYOUT_H = cfglayout.h $(BASIC_BLOCK_H)
  CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $(RTL_H)
! CGRAPH_H = cgraph.h bitmap.h tree.h varray.h $(HASHTAB_H)
  DF_H = df.h bitmap.h sbitmap.h $(BASIC_BLOCK_H)
  DDG_H = ddg.h sbitmap.h $(DF_H)
  GCC_H = gcc.h version.h
*************** simplify-rtx.o : simplify-rtx.c $(CONFIG
*** 1915,1923 ****
  cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h toplev.h $(FLAGS_H) $(GGC_H)  $(TARGET_H) $(CGRAPH_H) gt-cgraph.h \
     output.h intl.h
! ipa_prop.o : ipa_prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
!    langhooks.h toplev.h $(FLAGS_H) $(GGC_H)  $(TARGET_H) cgraph.h gt-cgraph.h \
!    output.h intl.h ipa_prop.h tree.h tree-iterator.h tree-gimple.h tree-inline.h
  cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h tree-inline.h toplev.h $(FLAGS_H) $(GGC_H)  $(TARGET_H) $(CGRAPH_H) intl.h \
     function.h $(TREE_GIMPLE_H) $(TREE_FLOW_H) ipa_prop.h
--- 1915,1923 ----
  cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h toplev.h $(FLAGS_H) $(GGC_H)  $(TARGET_H) $(CGRAPH_H) gt-cgraph.h \
     output.h intl.h
! ipa_prop.o : ipa_prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
!    langhooks.h $(GGC_H) $(CGRAPH_H) output.h ipa_prop.h tree-iterator.h \
!    tree-inline.h  
  cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h tree-inline.h toplev.h $(FLAGS_H) $(GGC_H)  $(TARGET_H) $(CGRAPH_H) intl.h \
     function.h $(TREE_GIMPLE_H) $(TREE_FLOW_H) ipa_prop.h
Index: cgraph.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.4.4.18.2.8
diff -c -3 -p -r1.4.4.18.2.8 cgraph.c
*** cgraph.c	25 Sep 2004 23:17:32 -0000	1.4.4.18.2.8
--- cgraph.c	5 Oct 2004 08:35:54 -0000
*************** cgraph_unnest_node (struct cgraph_node *
*** 706,709 ****
--- 706,737 ----
    *node2 = node->next_nested;
    node->origin = NULL;
  }
+ 
+ /* Copy collees of node FROM to node TO.  */
+ void
+ cgraph_copy_node_callees (struct cgraph_node *to,
+                           struct cgraph_node *from)
+ {
+   struct cgraph_edge *e;
+   
+   for (e = from->callees;e; e=e->next_callee)
+     cgraph_clone_edge (e, to, e->call_expr);
+   
+ }
+ 
+ 
+ void
+ cgraph_copy_local_info (struct cgraph_node *new_node, 
+ 			struct cgraph_node *orig_node)
+ {
+   new_node->local.self_insns = orig_node->local.self_insns;
+   new_node->local.local = orig_node->local.local;
+   new_node->local.finalized = orig_node->local.finalized;
+   new_node->local.disregard_inline_limits = 
+     orig_node->local.disregard_inline_limits;
+   new_node->local.inlinable = orig_node->local.inlinable;
+   new_node->local.redefined_extern_inline = 
+     orig_node->local.redefined_extern_inline;
+ }
+ 
  #include "gt-cgraph.h"
Index: cgraph.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cgraph.h,v
retrieving revision 1.1.4.16.2.7
diff -c -3 -p -r1.1.4.16.2.7 cgraph.h
*** cgraph.h	25 Sep 2004 23:17:32 -0000	1.1.4.16.2.7
--- cgraph.h	5 Oct 2004 08:35:54 -0000
*************** Software Foundation, 59 Temple Place - S
*** 24,29 ****
--- 24,30 ----
  #include "hashtab.h"
  #include "bitmap.h"
  #include "tree.h"
+ #include "varray.h"
  
  /* Information about the function collected locally.
     Available after function is analyzed.  */
*************** struct cgraph_varpool_node GTY(())
*** 232,237 ****
--- 233,245 ----
    bool output;
  };
  
+ /* Get first callee of node.  */
+ #define FIRST_CALLEE(node)               ((node)->callees)
+ /* Get next callee from edge.  */
+ #define NEXT_CALLEE(edge)                ((edge)->next_callee)
+ /* Returns whether edge is last callee.  */
+ #define CALLEE_NOT_LAST(edge)            ((edge) != NULL)
+ 
  extern GTY(()) struct cgraph_node *cgraph_nodes;
  extern GTY(()) int cgraph_n_nodes;
  extern GTY(()) int cgraph_max_uid;
*************** struct cgraph_rtl_info *cgraph_rtl_info 
*** 258,270 ****
  const char * cgraph_node_name (struct cgraph_node *);
  struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *, struct cgraph_node *, tree);
  struct cgraph_node * cgraph_clone_node (struct cgraph_node *);
! 
  struct cgraph_varpool_node *cgraph_varpool_node (tree decl);
  void cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *);
  void cgraph_varpool_finalize_decl (tree);
  bool cgraph_varpool_assemble_pending_decls (void);
  void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
! 
  bool cgraph_function_possibly_inlined_p (tree);
  void cgraph_unnest_node (struct cgraph_node *node);
  
--- 266,280 ----
  const char * cgraph_node_name (struct cgraph_node *);
  struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *, struct cgraph_node *, tree);
  struct cgraph_node * cgraph_clone_node (struct cgraph_node *);
! void cgraph_copy_node_callees (struct cgraph_node *,
!                                struct cgraph_node *);
  struct cgraph_varpool_node *cgraph_varpool_node (tree decl);
  void cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *);
  void cgraph_varpool_finalize_decl (tree);
  bool cgraph_varpool_assemble_pending_decls (void);
  void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
! void cgraph_copy_local_info (struct cgraph_node *,
!                              struct cgraph_node *);
  bool cgraph_function_possibly_inlined_p (tree);
  void cgraph_unnest_node (struct cgraph_node *node);
  
*************** void cgraph_build_static_cdtor (char whi
*** 286,291 ****
--- 296,308 ----
  void cgraph_reset_static_var_maps (void);
  bitmap get_global_statics_not_read (tree fn);
  bitmap get_global_statics_not_written(tree fn);
+ void update_call_expr (struct cgraph_node *, varray_type);
+ struct cgraph_node *cgraph_copy_node_for_versioning (struct cgraph_node *,
+                                                      tree, varray_type);
+ struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
+                                                 varray_type);
+ 
  void init_cgraph (void);
  
+ 
  #endif  /* GCC_CGRAPH_H  */
Index: cgraphunit.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.1.4.35.2.16
diff -c -3 -p -r1.1.4.35.2.16 cgraphunit.c
*** cgraphunit.c	25 Sep 2004 23:17:32 -0000	1.1.4.35.2.16
--- cgraphunit.c	5 Oct 2004 08:35:54 -0000
*************** record_call_1 (tree *tp, int *walk_subtr
*** 670,677 ****
  		       visited_nodes);
  	    *walk_subtrees = 0;
  	  }
-         if (flag_ipa_cp && decl == NULL_TREE)
-           flag_ipa_cp = 0;
  	break;
        }
  
--- 670,675 ----
*************** cgraph_reduced_inorder (struct cgraph_no
*** 1270,1279 ****
  }
  
  /* Perform reachability analysis and reclaim all unreachable nodes.
!    This function also remove unneeded bodies of extern inline functions
!    and thus needs to be done only after inlining decisions has been made.  */
  static bool
! cgraph_remove_unreachable_nodes (void)
  {
    struct cgraph_node *first = (void *) 1;
    struct cgraph_node *node;
--- 1268,1278 ----
  }
  
  /* Perform reachability analysis and reclaim all unreachable nodes.
!    If BEFORE_INLINING_P is true this function is called before inlining
!    decisions has been made.  If BEFORE_INLINING_P is false this function also 
!    removes unneeded bodies of extern inline functions.  */
  static bool
! cgraph_remove_unreachable_nodes (bool before_inlining_p)
  {
    struct cgraph_node *first = (void *) 1;
    struct cgraph_node *node;
*************** cgraph_remove_unreachable_nodes (void)
*** 1291,1298 ****
  #endif
    for (node = cgraph_nodes; node; node = node->next)
      if (node->needed && !node->global.inlined_to
! 	&& (!DECL_EXTERNAL (node->decl) || !node->analyzed))
        {
  	node->aux = first;
  	first = node;
        }
--- 1290,1300 ----
  #endif
    for (node = cgraph_nodes; node; node = node->next)
      if (node->needed && !node->global.inlined_to
! 	&& ((!DECL_EXTERNAL (node->decl)) 
!             || !node->analyzed
!             || before_inlining_p))
        {
+         node->reachable = true;
  	node->aux = first;
  	first = node;
        }
*************** cgraph_remove_unreachable_nodes (void)
*** 1312,1320 ****
  	if (!e->callee->aux
  	    && node->analyzed
  	    && (!e->inline_failed || !e->callee->analyzed
! 		|| !DECL_EXTERNAL (e->callee->decl)))
! 	  {
  	    e->callee->aux = first;
  	    first = e->callee;
  	  }
      }
--- 1314,1324 ----
  	if (!e->callee->aux
  	    && node->analyzed
  	    && (!e->inline_failed || !e->callee->analyzed
! 		|| (!DECL_EXTERNAL (e->callee->decl))
!                 || before_inlining_p))
!         {
  	    e->callee->aux = first;
+             e->callee->reachable = true;
  	    first = e->callee;
  	  }
      }
*************** cgraph_remove_unreachable_nodes (void)
*** 1341,1347 ****
  	    local_insns = 0;
  	  if (cgraph_dump_file)
  	    fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
! 	  if (!node->analyzed || !DECL_EXTERNAL (node->decl))
  	    cgraph_remove_node (node);
  	  else
  	    {
--- 1345,1352 ----
  	    local_insns = 0;
  	  if (cgraph_dump_file)
  	    fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
! 	  if (!node->analyzed || !DECL_EXTERNAL (node->decl)
!               || before_inlining_p)
  	    cgraph_remove_node (node);
  	  else
  	    {
*************** cgraph_decide_inlining (void)
*** 1960,1966 ****
    /* We will never output extern functions we didn't inline. 
       ??? Perhaps we can prevent accounting of growth of external
       inline functions.  */
!   cgraph_remove_unreachable_nodes ();
  
    if (cgraph_dump_file)
      fprintf (cgraph_dump_file,
--- 1965,1971 ----
    /* We will never output extern functions we didn't inline. 
       ??? Perhaps we can prevent accounting of growth of external
       inline functions.  */
!   cgraph_remove_unreachable_nodes (false);
  
    if (cgraph_dump_file)
      fprintf (cgraph_dump_file,
*************** cgraph_optimize (void)
*** 2785,2792 ****
  #endif
    if (!flag_unit_at_a_time)
      return;
!   if (flag_ipa_cp && flag_ipa_no_cloning)
      ipcp_driver ();
    timevar_push (TV_CGRAPHOPT);
    if (!quiet_flag)
      fprintf (stderr, "Performing intraprocedural optimizations\n");
--- 2790,2801 ----
  #endif
    if (!flag_unit_at_a_time)
      return;
!   if (flag_ipa_cp)
!   {
      ipcp_driver ();
+     /* Clean the callgraph.  */
+     cgraph_remove_unreachable_nodes (true);
+   }
    timevar_push (TV_CGRAPHOPT);
    if (!quiet_flag)
      fprintf (stderr, "Performing intraprocedural optimizations\n");
*************** init_cgraph (void)
*** 2932,2935 ****
--- 2941,3083 ----
    cgraph_dump_file = dump_begin (TDI_cgraph, NULL);
    memory_identifier = get_identifier("memory");
  }
+ 
+  
+ /* Update the CALL_EXPR in NEW_VERSION node callers edges.  */
+ 
+ void
+ update_call_expr (struct cgraph_node *new_version, 
+  		  varray_type redirect_callers)
+ {
+   struct cgraph_edge *e;
+   unsigned i;
+   
+   if (new_version == NULL)
+     abort ();
+   
+   for (i = 0; i < VARRAY_ACTIVE_SIZE (redirect_callers); i++)
+     {
+       e = VARRAY_GENERIC_PTR (redirect_callers, i);
+       
+       /* Update the call expr on the edges
+          to the new version. */ 
+       TREE_OPERAND (TREE_OPERAND (e->call_expr, 0), 0) = new_version->decl;
+     }
+   for (e = new_version->callers; e; e = e->next_caller)
+     { 
+       /* Update the call expr on the edges
+          of recursive calls. */
+       if (e->caller == new_version)
+         TREE_OPERAND (TREE_OPERAND (e->call_expr, 0), 0) = new_version->decl;            
+     }           
+ }
+ 
+ 
+ /* Create a new cgraph node which is the new version of 
+    OLD_VERSION node.  REDIRECT_CALLERS holds the callers
+    of OLD_VERSION which should be redirected to point to  
+    NEW_VERSION.  ALL the callees edges of OLD_VERSION 
+    are cloned to the new version node.  Return the new 
+    version node.  */
+ 
+ struct cgraph_node *
+ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
+  				 tree new_decl, varray_type redirect_callers)
+ {
+   struct cgraph_node *new_version;
+   struct cgraph_edge *e;
+   struct cgraph_edge *next_callee;
+   unsigned i;
+   
+   if (old_version == NULL)
+     abort ();
+   
+   new_version = cgraph_node (new_decl);
+   
+   new_version->needed = false; 
+   new_version->decl = new_decl;
+   memset (&new_version->local, 0, sizeof (new_version->local));
+   cgraph_copy_local_info (new_version,
+  			  old_version);
+   memset (&new_version->global, 0, sizeof (new_version->global));
+   new_version->global.insns = old_version->global.insns;
+   memset (&new_version->rtl, 0, sizeof (new_version->rtl));
+   new_version->analyzed = true;
+   
+   /* Clone the old node callees.  Recursive calls are
+      also cloned.  */ 
+   cgraph_copy_node_callees (new_version, old_version);
+   
+   
+   /* Fix recursive calls. 
+      If old_version has a recursive call after the 
+      previous cloning the new version will have an edge
+      pointing to the old version which is wrong;
+      so redirect it to point to the new version. */
+   for (e = new_version->callees ; e; e = next_callee)
+     {
+       next_callee = e->next_callee;
+       if (e->callee == old_version)
+         {
+           cgraph_redirect_edge_callee (e, new_version);
+         }
+        if (!next_callee)
+          break;
+     }
+   for (i = 0; i < VARRAY_ACTIVE_SIZE (redirect_callers); i++) 
+     {
+       e = VARRAY_GENERIC_PTR (redirect_callers, i); 
+       /* Redirect calls to the old version node
+  	 to point to it's new version.  */ 
+       cgraph_redirect_edge_callee (e, new_version);
+     }
+   
+   allocate_struct_function (new_decl);
+   cfun->function_end_locus = DECL_SOURCE_LOCATION (new_decl);
+   
+   return new_version;
+ }
+ 
+ /* Perform function versioning. 
+    Function versioning includes:
+    1) Generating a new cgraph node for the new version
+    and redirect it's edges respectively. 
+    2) Copying the old version tree to the new
+    version.  
+    The function gets REDIRECT_CALLERS varray, the 
+    edges to be redirected to the new version and
+    the old version's cgraph node.  It returns the new version's 
+    cgraph node.  */ 
+ 
+ struct cgraph_node *
+ cgraph_function_versioning (struct cgraph_node *old_version_node, 
+                             varray_type redirect_callers)
+ {
+   tree old_decl = old_version_node->decl;
+   struct cgraph_node *new_version_node = NULL;
+   tree new_decl;
+   
+   if (!tree_versionable_function_p (old_decl))
+     return NULL;
+   
+   /* Make a new FUNCTION_DECL tree node for the
+      new version. */
+   new_decl = copy_node (old_decl);
+   
+   /* Create the new version's call-graph node. 
+      and update the edges of the new node. */
+   new_version_node = 
+     cgraph_copy_node_for_versioning (old_version_node, new_decl,
+                                      redirect_callers);  
+   
+   /* Copy the old version's function tree to the new
+      version.  */
+   tree_function_versioning (old_decl, new_decl);
+   /* Update the call_expr on the edges
+      to the new version node. */
+   update_call_expr (new_version_node, redirect_callers);
+   return new_version_node;
+ }
+ 
+ 
  #include "gt-cgraphunit.h"
Index: common.opt
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/common.opt,v
retrieving revision 1.14.2.20.2.13
diff -c -3 -p -r1.14.2.20.2.13 common.opt
*** common.opt	18 Sep 2004 22:46:58 -0000	1.14.2.20.2.13
--- common.opt	5 Oct 2004 08:35:54 -0000
*************** fipa-cp
*** 888,897 ****
  Common Report Var(flag_ipa_cp)
  Perform IPA constant propagation
  
- fipa-no-cloning
- Common Report Var(flag_ipa_no_cloning)
- Perform IPA cp, without cloning of methods
- 
  funroll-loops
  Common Report Var(flag_unroll_loops)
  Perform loop unrolling when iteration count is known
--- 888,893 ----
Index: gimplify.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/gimplify.c,v
retrieving revision 1.1.2.141.2.13
diff -c -3 -p -r1.1.2.141.2.13 gimplify.c
*** gimplify.c	25 Sep 2004 23:17:49 -0000	1.1.2.141.2.13
--- gimplify.c	5 Oct 2004 08:35:55 -0000
*************** create_tmp_var_name (const char *prefix)
*** 315,320 ****
--- 315,344 ----
    return get_identifier (tmp_name);
  }
  
+ /* Create a new function name with PREFIX.  Returns an identifier.  */
+ tree
+ create_function_name (const char *prefix)
+ {
+   char *tmp_name;
+   unsigned i;
+   
+   if (prefix)
+     {
+       char *preftmp = ASTRDUP (prefix);
+ 
+       remove_suffix (preftmp, strlen (preftmp));
+       prefix = preftmp;
+     }
+   ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix ? prefix : "F", tmp_var_id_num++);
+   for (i=0; i < strlen (tmp_name); i++)
+   {
+      if (tmp_name[i] == '.')
+            tmp_name[i] = '_';
+   }
+ 
+   return get_identifier (tmp_name);
+ }
+ 
  
  /* Create a new temporary variable declaration of type TYPE.
     Does NOT push it into the current binding.  */
Index: integrate.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/integrate.c,v
retrieving revision 1.197.2.31.2.7
diff -c -3 -p -r1.197.2.31.2.7 integrate.c
*** integrate.c	9 Sep 2004 10:55:04 -0000	1.197.2.31.2.7
--- integrate.c	5 Oct 2004 08:35:55 -0000
*************** copy_decl_for_inlining (tree decl, tree 
*** 176,181 ****
--- 176,248 ----
  
    return copy;
  }
+ 
+ /* Copy NODE (which must be a DECL).  The DECL originally was in the FROM_FN,
+    but now it will be in the TO_FN. As apposed for to copy_decl_for_inlining ()
+    function; we do not give a special treatment to parm_decl and result_decl.  */ 
+ tree
+ copy_decl_for_versioning (tree decl, tree from_fn, tree to_fn)
+ {
+   tree copy;
+ 
+   /* Copy the declaration.  */
+   copy = copy_node (decl);
+       
+   /* The COPY is not abstract; it will be generated in TO_FN.  */
+   DECL_ABSTRACT (copy) = 0;
+   lang_hooks.dup_lang_specific_decl (copy);
+       
+   /* TREE_ADDRESSABLE isn't used to indicate that a label's
+      address has been taken; it's for internal bookkeeping in
+      expand_goto_internal.  */
+   if (TREE_CODE (copy) == LABEL_DECL)
+     {
+       TREE_ADDRESSABLE (copy) = 0;
+     }
+   
+   /* FIXME:  For the moment debug information for the copy
+      is not supported.  */ 
+   DECL_ARTIFICIAL (copy) = 1;
+   DECL_IGNORED_P (copy) = 1;
+   /* DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);  */
+   
+   if (TREE_STATIC (copy))
+     {
+       /* Set the DECL_ABSTRACT_ORIGIN of copy to point to the 
+          old version decl in case it is static so it can 
+          be retrieved when needed.  */
+       DECL_ABSTRACT_ORIGIN (copy) = decl;
+       /* FIXME: Again - debug information is not supported yet.  */
+       DECL_IGNORED_P (decl) = 1;
+     }
+    
+   /* The new variable/label has no RTL, yet.  */
+   if (!TREE_STATIC (copy) && !DECL_EXTERNAL (copy))
+     SET_DECL_RTL (copy, NULL_RTX);
+  
+   /* These args would always appear unused, if not for this.  */
+   TREE_USED (copy) = 1;
+   
+   /* Set the context for the new declaration.  */
+   if (!DECL_CONTEXT (decl))
+     /* Globals stay global.  */
+     ;
+   else if (TREE_STATIC (decl))
+     /* Function-scoped static variables should stay in the original
+        function.  */
+     ;
+   else if (DECL_CONTEXT (decl) != from_fn)
+     /* Things that weren't in the scope of the function we're inlining
+        from aren't in the scope we're inlining to, either.  */
+     ;
+   else
+     /* Ordinary automatic local variables are now in the scope of the
+        new function.  */
+     DECL_CONTEXT (copy) = to_fn;
+   
+   return copy;
+ }
+ 
  \f
  /* Unfortunately, we need a global copy of const_equiv map for communication
     with a function called from note_stores.  Be *very* careful that this
Index: integrate.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/integrate.h,v
retrieving revision 1.25.2.2.6.1
diff -c -3 -p -r1.25.2.2.6.1 integrate.h
*** integrate.h	22 Feb 2004 15:35:47 -0000	1.25.2.2.6.1
--- integrate.h	5 Oct 2004 08:35:55 -0000
*************** extern void allocate_initial_values (rtx
*** 136,142 ****
  /* Copy a declaration when one function is substituted inline into
     another.  */
  extern tree copy_decl_for_inlining (tree, tree, tree);
! 
  /* Check whether there's any attribute in a function declaration that
     makes the function uninlinable.  Returns false if it finds any,
     true otherwise.  */
--- 136,142 ----
  /* Copy a declaration when one function is substituted inline into
     another.  */
  extern tree copy_decl_for_inlining (tree, tree, tree);
! extern tree copy_decl_for_versioning (tree, tree, tree);
  /* Check whether there's any attribute in a function declaration that
     makes the function uninlinable.  Returns false if it finds any,
     true otherwise.  */
Index: ipa_prop.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/Attic/ipa_prop.c,v
retrieving revision 1.1.2.3
diff -c -3 -p -r1.1.2.3 ipa_prop.c
*** ipa_prop.c	12 Sep 2004 16:39:17 -0000	1.1.2.3
--- ipa_prop.c	5 Oct 2004 08:35:56 -0000
***************
*** 1,6 ****
! /* Callgraph based intraprocedural optimizations.
!    Copyright (C) 2003, 2004 Free Software Foundation, Inc.
!    Contributed by Razya Ladelsky.
  
  This file is part of GCC.
  
--- 1,6 ----
! /* Interprocedural constant propagation
!    Copyright (C) 2004 Free Software Foundation, Inc.
!    Contributed by Razya Ladelsky <RAZYA@il.ibm.com>
  
  This file is part of GCC.
  
*************** Software Foundation, 59 Temple Place - S
*** 20,27 ****
  02111-1307, USA.  */
  
  /* Interprocedural constant propagation.
! The aim of IPA constant propagation is to find which function's argument
! has the same constant value in each invocation throughout the whole program.
  For example, for an application consisting of two files, foo1.c, foo2.c:
  
  foo1.c contains :
--- 20,27 ----
  02111-1307, USA.  */
  
  /* Interprocedural constant propagation.
! The aim of interprocedural constant propagation (IPCP) is to find which function's 
! argument has the same constant value in each invocation throughout the whole program.
  For example, for an application consisting of two files, foo1.c, foo2.c:
  
  foo1.c contains :
*************** int g (int y)
*** 47,142 ****
    printf ("value is %d",y);
  }
  
! The IPCP algorithm should find that g's formal argument y
  is always called with the value 3. 
  
  The optimization is divided into three stages:
  
  First stage - intraprocedural analysis  
  =======================================
  This phase computes jump_function and modify information. 
  
! Jump functions represent the value that is passes to each actual argument 
! by this callsite.
! there are three values :
!   Formal - the caller's formal parameter is passed as a parameter.
!   Constant - a constant is passed as a parameter.
    Unknown - neither of the above.
  
! Modify is true for a formal parameter if it is modified in its function.
! 
! In the case that the formal parameter passed in the callsite is 
! modified, the jump fumction value for this parameter turns to UNKOWN.
  
! The jump function structure, ipcp_jump_func, is defined in ipa_edge
  structure (defined in ipa_prop.h and pointed to by cgraph_node->aux)
  The modify info, ipcp_modify, is defined in ipa_node structure
  (defined in ipa_prop.h and pointed to by cgraph_edge->aux).
  
! The ipcp_tree_map (a mapping from the PARAM_DECL tree to the inner
! representation of formals) and ipcp_formal (explained below) structures
! are also pointed to by cgraph_node->aux and also initialized 
! in this phase.
! 
! -ipcp_stage1() is the first stage driver.
  
  Second stage - interprocedural analysis
  ========================================
! This phase solves the interprocedural constant propagation problem.
! The algorithm is based on a paper by Challahan David, 
! Keith D Cooper, Ken Kennedy, Linda Torczon, 
! Interprocedural Constant Propagation, Comp86.
! 
! Each formal has cval info (denoted as ipcp_formal) which represents its 
! value computed so far. 
! possible values : 
!   TOP - not known yet. 
!   BOTTOM - considered as not constant. 
!   CONSTANT_TYPE - has constant value.
  
- The algoritm computes for all formal parameters in the program 
- their cval value.
  Cval of formal f will have a constant value if all callsites to this 
! function have the same constant value passed to f 
! and will have BOTTOM value otherwise.
  
! This stage propagates the constant information from formal paranmeters
! to the actual parameters.
  
! -ipcp_stage2() is the second stage driver.
  
! Third phase 
! ============
  Propagates the constant-valued formals into the function.
  
! -ipcp_stage3() is the third phase driver.
     
  */
  
  #include "config.h"
  #include "system.h"
! #include "coretypes.h"
! #include "tm.h"
  #include "tree.h"
  #include "langhooks.h"
- #include "hashtab.h"
- #include "toplev.h"
- #include "flags.h"
  #include "ggc.h"
- #include "debug.h"
- #include "target.h"  
  #include "cgraph.h"
- #include "varray.h"
  #include "output.h"  
  #include "tree-iterator.h"
- #include "tree-gimple.h"
  #include "tree-inline.h"
  #include "ipa_prop.h"
  
  typedef struct cgraph_node *ipcp_method ;
  typedef  struct cgraph_edge *ipcp_callsite;
  
! struct ipcp_methodlist
  {
    ipcp_method method_p;
    struct ipcp_methodlist *next_method;
--- 47,144 ----
    printf ("value is %d",y);
  }
  
! The IPCP algorithm will find that g's formal argument y
  is always called with the value 3. 
  
+ The algorithm used is based on "Interprocedural Constant Propagation",
+ by Challahan David, Keith D Cooper, Ken Kennedy, Linda Torczon, Comp86, pg 152-161
+ 
  The optimization is divided into three stages:
  
  First stage - intraprocedural analysis  
  =======================================
  This phase computes jump_function and modify information. 
  
! A jump function for a callsite represents the values passed as actual arguments 
! of the callsite. There are three types of values :
!   Formal - the caller's formal parameter is passed as an actual argument.
!   Constant - a constant is passed as a an actual argument.
    Unknown - neither of the above.
  
! In order to compute the jump functions, we need the modify information for the formal
! parameters of methods.
  
! The jump function info, ipcp_jump_func, is defined in ipa_edge
  structure (defined in ipa_prop.h and pointed to by cgraph_node->aux)
  The modify info, ipcp_modify, is defined in ipa_node structure
  (defined in ipa_prop.h and pointed to by cgraph_edge->aux).
  
! -ipcp_init_stage() is the first stage driver.
  
  Second stage - interprocedural analysis
  ========================================
! This phase does the interprocedural constant propagation.
! It computes for all formal parameters in the program 
! their cval value that may be:
!   TOP - unknown. 
!   BOTTOM - non constant. 
!   CONSTANT_TYPE - constant value.
  
  Cval of formal f will have a constant value if all callsites to this 
! function have the same constant value passed to f. 
  
! The cval info, ipcp_formal, is defined in ipa_node structure
! (defined in ipa_prop.h and pointed to by cgraph_edge->aux). 
  
! -ipcp_iterate_stage() is the second stage driver.
  
! Third phase - transformation of methods code
! ============================================
  Propagates the constant-valued formals into the function.
+ For each method mt, whose parameters are consts, we create a clone.
+ 
+ We insert an assignment statement 'parameter = const' at the beginning 
+ of the cloned method.
  
! We also need to modify some callsites to call to the cloned methods instead 
! of the original ones. For a callsite passing an argument found to be a constant 
! by IPCP, there are two different cases to handle:
! 1. A constant is passed as an argument.
! 2. A parameter (of the caller) passed as an argument (pass through argument).
! 
! In the first case, the callsite in the original caller should be redirected 
! to call the cloned callee.
! In the second case, both the caller and the callee have clones
! and the callsite of the cloned caller would be redirected to call to 
! the cloned callee.
! 
! The callgraph is updated accordingly.
! 
! This update is done in two stages: 
! First all cloned methods are created during a traversal of the callgraph, 
! during which all callsites are redirected to call the cloned method.
! Then the callsites are traversed and updated as described above.
! 
! -ipcp_insert_stage() is the third phase driver.
     
  */
  
  #include "config.h"
  #include "system.h"
! #include "coretypes.h" 
  #include "tree.h"
  #include "langhooks.h"
  #include "ggc.h"
  #include "cgraph.h"
  #include "output.h"  
  #include "tree-iterator.h"
  #include "tree-inline.h"
  #include "ipa_prop.h"
  
  typedef struct cgraph_node *ipcp_method ;
  typedef  struct cgraph_edge *ipcp_callsite;
  
! struct ipcp_methodlist GTY(())
  {
    ipcp_method method_p;
    struct ipcp_methodlist *next_method;
*************** struct ipcp_methodlist
*** 144,150 ****
  
  typedef struct ipcp_methodlist *ipcp_methodlist_p;
  
! /* WorlList Interface.  */
  static inline ipcp_methodlist_p ipcp_create_methodlist_node (void); 
  static inline bool ipcp_methodlist_not_empty (ipcp_methodlist_p);
  static inline ipcp_method ipcp_methodlist_method (ipcp_methodlist_p); 
--- 146,152 ----
  
  typedef struct ipcp_methodlist *ipcp_methodlist_p;
  
! /* ipcp_worlList Interface.  */
  static inline ipcp_methodlist_p ipcp_create_methodlist_node (void); 
  static inline bool ipcp_methodlist_not_empty (ipcp_methodlist_p);
  static inline ipcp_method ipcp_methodlist_method (ipcp_methodlist_p); 
*************** static void ipcp_callsite_compute_param 
*** 172,177 ****
--- 174,183 ----
  static void ipcp_callsite_compute_count (ipcp_callsite);
  
  /* ipcp_method interface.  */
+ static inline void ipa_node_create (ipcp_method);
+ static inline bool ipcp_method_is_cloned (ipcp_method);
+ static inline void ipcp_method_set_orig_node (ipcp_method, ipcp_method);
+ static inline ipcp_method ipcp_method_orig_node (ipcp_method);
  static inline void ipcp_formal_create (ipcp_method); 
  static inline int ipcp_method_formal_count (ipcp_method);
  static inline void ipcp_method_formal_count_set (ipcp_method, int); 
*************** static inline tree ipcp_method_get_tree 
*** 184,192 ****
  static inline void ipcp_method_tree_map_create (ipcp_method);
  static inline void ipcp_method_modify_create (ipcp_method); 
  static inline void ipcp_method_modify_set (ipcp_method, int, bool);
! static inline ipcp_callsite ipcp_cs_get_first (ipcp_method);
! static inline ipcp_callsite ipcp_cs_get_next (ipcp_callsite);
! static inline bool ipcp_cs_not_last (ipcp_callsite); 
  static int  ipcp_method_tree_map (ipcp_method, tree);
  static void ipcp_method_compute_tree_map (ipcp_method);
  static void ipcp_cval_meet (struct ipcp_formal *, struct ipcp_formal *,
--- 190,196 ----
  static inline void ipcp_method_tree_map_create (ipcp_method);
  static inline void ipcp_method_modify_create (ipcp_method); 
  static inline void ipcp_method_modify_set (ipcp_method, int, bool);
! static void ipa_cloned_create (ipcp_method orig_node, ipcp_method new_node);
  static int  ipcp_method_tree_map (ipcp_method, tree);
  static void ipcp_method_compute_tree_map (ipcp_method);
  static void ipcp_cval_meet (struct ipcp_formal *, struct ipcp_formal *,
*************** static inline ipcp_int *ipcp_cval_get_cv
*** 216,228 ****
  static inline enum Cvalue_type ipcp_cval_get_cvalue_type (struct ipcp_formal *);
  static inline bool ipcp_cval_equal_cvalues (ipcp_int *, ipcp_int *);
  
! static void ipcp_stage1 (void);
! static void ipcp_stage2 (void);
! static void ipcp_stage3 (void);
  static void ipcp_free (void);
  static void ipa_nodes_create (void);
  
! static bool ipcp_method_dont_propagate (ipcp_method);
  static tree ipcp_asm_walk_tree (tree *, int *, void *);
  static bool ipcp_method_contains_asm (ipcp_method);
  static void ipcp_walk_statements (ipcp_method, tree *);
--- 220,235 ----
  static inline enum Cvalue_type ipcp_cval_get_cvalue_type (struct ipcp_formal *);
  static inline bool ipcp_cval_equal_cvalues (ipcp_int *, ipcp_int *);
  
! static void ipcp_init_stage (void);
! static void ipcp_iterate_stage (void);
! static void ipcp_insert_stage (void);
! static void ipcp_update_callgraph (void);
! static bool ipcp_redirect (ipcp_callsite);
  static void ipcp_free (void);
  static void ipa_nodes_create (void);
+ static void ipa_edges_create (void);
  
! static bool ipcp_method_dont_insert_const (ipcp_method);
  static tree ipcp_asm_walk_tree (tree *, int *, void *);
  static bool ipcp_method_contains_asm (ipcp_method);
  static void ipcp_walk_statements (ipcp_method, tree *);
*************** static void ipcp_callsite_param_print (F
*** 238,273 ****
--- 245,286 ----
  
  /* WorlList Interface.  */
  
+ /* Creates the worklist for ipcp_iterate_stage().  */
  static inline ipcp_methodlist_p
  ipcp_create_methodlist_node (void) 
  {
    return ggc_alloc (sizeof (struct ipcp_methodlist));
  }
  
+ /* Checks that worklist is not empty.  */
  static inline bool
  ipcp_methodlist_not_empty (ipcp_methodlist_p wl)
  {
    return (wl != NULL);
  }
  
+ /* Gets method from worklist's node.  */
  static inline ipcp_method
  ipcp_methodlist_method (ipcp_methodlist_p wl) 
  {
    return wl->method_p;   
  }
  
+ /* Sets worklist's node to point to mt.  */
  static inline void
  ipcp_methodlist_method_set (ipcp_methodlist_p wl, ipcp_method mt)
  {
    wl->method_p = mt;
  }
  
+ /* Gets next worklist's node.  */
  static inline ipcp_methodlist_p
  ipcp_methodlist_next_method (ipcp_methodlist_p wl) 
  { 
    return wl->next_method;    
  }
  
+ /* Sets worklist node wl1 to point to  worklist node wl2.  */
  static inline void
  ipcp_methodlist_next_method_set (ipcp_methodlist_p wl1, ipcp_methodlist_p wl2) 
  { 
*************** ipcp_remove_method (ipcp_methodlist_p *w
*** 312,349 ****
    return ipcp_methodlist_method (first);
  }
  
! /* callsite interface.  */
  static inline int 
  ipcp_callsite_param_count (ipcp_callsite cs) 
  { 
    return ((struct ipa_edge *)cs->aux)->ipcp_param_num;
  }
  
  static inline void 
  ipcp_callsite_param_count_set (ipcp_callsite cs, int i) 
  {
    ((struct ipa_edge *)cs->aux)->ipcp_param_num = i;
  }
  
  static inline struct ipcp_jump_func *
  ipcp_callsite_param (ipcp_callsite cs, int i) 
  {
    return &(((struct ipa_edge *)cs->aux)->ipcp_param_map[i]);
  }
  
  static inline ipcp_method 
  ipcp_callsite_callee (ipcp_callsite cs)
  {
    return cs->callee;
  }
  
! 
  static inline void
  ipcp_callsite_param_set_type (ipcp_callsite cs, int i,  enum Jfunc_type type1) 
  {
    ((struct ipa_edge *)cs->aux)->ipcp_param_map[i].type = type1;
  }
  
  static inline void
  ipcp_callsite_param_set_info_type (ipcp_callsite cs, int i, 
  				   ipcp_int *info_type1) 
--- 325,368 ----
    return ipcp_methodlist_method (first);
  }
  
! /* ipcp_callsite interface.  */
! 
! /* Gets how many arguments the callsite has.  */
  static inline int 
  ipcp_callsite_param_count (ipcp_callsite cs) 
  { 
    return ((struct ipa_edge *)cs->aux)->ipcp_param_num;
  }
  
+ /* Sets how many arguments the callsite has.  */
  static inline void 
  ipcp_callsite_param_count_set (ipcp_callsite cs, int i) 
  {
    ((struct ipa_edge *)cs->aux)->ipcp_param_num = i;
  }
  
+ /* Gets the jump function for argument i of callsite cs.  */
  static inline struct ipcp_jump_func *
  ipcp_callsite_param (ipcp_callsite cs, int i) 
  {
    return &(((struct ipa_edge *)cs->aux)->ipcp_param_map[i]);
  }
  
+ /* Gets the callee of callsite cs.  */
  static inline ipcp_method 
  ipcp_callsite_callee (ipcp_callsite cs)
  {
    return cs->callee;
  }
  
! /* Sets the jump function's type for argument i of callsite cs.  */
  static inline void
  ipcp_callsite_param_set_type (ipcp_callsite cs, int i,  enum Jfunc_type type1) 
  {
    ((struct ipa_edge *)cs->aux)->ipcp_param_map[i].type = type1;
  }
  
+ /* Sets the jump function's info type for argument i of callsite cs.  */
  static inline void
  ipcp_callsite_param_set_info_type (ipcp_callsite cs, int i, 
  				   ipcp_int *info_type1) 
*************** ipcp_callsite_param_set_info_type (ipcp_
*** 351,356 ****
--- 370,376 ----
    ipcp_jf_set_info_type (ipcp_callsite_param (cs, i), info_type1);
  }
  
+ /* Allocates space for the jump functions.  */
  static inline void
  ipcp_callsite_param_map_create (ipcp_callsite cs) 
  {
*************** ipcp_callsite_param_map_create (ipcp_cal
*** 358,369 ****
--- 378,391 ----
      xcalloc (ipcp_callsite_param_count (cs), sizeof (struct ipcp_jump_func));   
  }
  
+ /* Returns the call expr tree realted to callsite cs.  */
  static inline tree
  ipcp_callsite_tree (ipcp_callsite cs) 
  {
    return cs->call_expr;
  }
  
+ /* Gets the caller of callsite cs.  */
  static inline ipcp_method 
  ipcp_callsite_caller (ipcp_callsite cs) 
  {
*************** ipcp_callsite_compute_param (ipcp_callsi
*** 445,450 ****
--- 467,501 ----
  
  /* ipcp_method interface.  */
  
+ /* Allocate and initialize ipa_node structure.  */
+ static inline void
+ ipa_node_create (ipcp_method node)
+ {
+    node->aux = xcalloc (1, sizeof (struct ipa_node));
+ }
+ 
+ /* Returns true if node is a cloned/versioned node.  */
+ static inline bool
+ ipcp_method_is_cloned (ipcp_method node)
+ {
+   return (ipcp_method_orig_node (node) != NULL);
+ }
+ 
+ /* Get orig node of method mt.  */
+ static inline ipcp_method
+ ipcp_method_orig_node (ipcp_method mt)
+ {
+   return ((struct ipa_node *)mt->aux)->ipcp_orig_node;
+ }
+ 
+ /* Sets orig node of method node.  */
+ static inline void
+ ipcp_method_set_orig_node (ipcp_method node, ipcp_method orig_node)
+ {
+   ((struct ipa_node *)node->aux)->ipcp_orig_node = orig_node;
+ }
+ 
+ /* Create cval structure for method mt.  */
  static inline void
  ipcp_formal_create (ipcp_method mt) 
  {
*************** ipcp_formal_create (ipcp_method mt) 
*** 452,469 ****
--- 503,523 ----
      xcalloc (ipcp_method_formal_count (mt), sizeof (struct ipcp_formal));
  }
  
+ /* Get number of formals of method mt.  */
  static inline int
  ipcp_method_formal_count (ipcp_method mt)
  {
    return ((struct ipa_node *)mt->aux)->ipcp_arg_num;
  }
  
+ /* Set number of formals of method mt.  */
  static inline void 
  ipcp_method_formal_count_set (ipcp_method mt, int i) 
  {
    ((struct ipa_node *)mt->aux)->ipcp_arg_num = i;
  }
  
+ /* Set cval structure of i-th formal of mt to cval.  */
  static inline void 
  ipcp_method_cval_set (ipcp_method mt, int i, struct ipcp_formal *cval)             
  {
*************** ipcp_method_cval_set (ipcp_method mt, in
*** 471,482 ****
--- 525,538 ----
    ipcp_cval_set_cvalue ( ipcp_method_cval (mt, i), ipcp_cval_get_cvalue (cval));     
  }
  
+ /* Get cval structure of i-th formal of mt.  */
  static inline struct ipcp_formal *
  ipcp_method_cval (ipcp_method mt, int info_type) 
  {
    return &(((struct ipa_node *)mt->aux)->ipcp_cval[info_type]);
  }
  
+ /* Set type of cval structure of formal i of mt to cval_type.  */
  static inline void 
  ipcp_method_cval_set_cvalue_type (ipcp_method mt, int i, 
  				  enum Cvalue_type cval_type)  
*************** ipcp_method_cval_set_cvalue_type (ipcp_m
*** 484,501 ****
--- 540,560 ----
    ((struct ipa_node *)mt->aux)->ipcp_cval[i].cvalue_type = cval_type;
  }
  
+ /* Returns whether i-th formal of mt is modified in mt.  */
  static inline bool 
  ipcp_method_is_modified (ipcp_method mt, int i)
  {
    return ((struct ipa_node *)mt->aux)->ipcp_mod[i].mod;
  }
  
+ /* Get param tree of i-th formal of mt.  */
  static inline tree 
  ipcp_method_get_tree (ipcp_method mt, int i)
  {
    return ((struct ipa_node *)mt->aux)->ipcp_param_tree[i].param_tree;
  }
  
+ /* Create tree map structure of mt.  */
  static inline void 
  ipcp_method_tree_map_create (ipcp_method mt)
  { 
*************** ipcp_method_tree_map_create (ipcp_method
*** 503,508 ****
--- 562,568 ----
      xcalloc (ipcp_method_formal_count (mt), sizeof (struct ipcp_tree_map));
  }
  
+ /* Create modify structure of mt.  */
  static inline void  
  ipcp_method_modify_create (ipcp_method mt) 
  { 
*************** ipcp_method_modify_create (ipcp_method m
*** 510,537 ****
      xcalloc (ipcp_method_formal_count (mt), sizeof (struct ipcp_modify));
  }
  
  static inline void  
  ipcp_method_modify_set (ipcp_method mt, int i, bool val)
  {
    ((struct ipa_node *)mt->aux)->ipcp_mod[i].mod = val;
  }
  
! static inline ipcp_callsite
! ipcp_cs_get_first (ipcp_method mt)
! {
!   return mt->callees;
! }
! 
! static inline ipcp_callsite
! ipcp_cs_get_next (ipcp_callsite cs)
  {
!   return cs->next_callee;
! }
  
- static inline bool 
- ipcp_cs_not_last (ipcp_callsite cs) 
- {
-   return (cs != NULL);
  }
  
  /* Returning the parameter index of the ptree.  */
--- 570,590 ----
      xcalloc (ipcp_method_formal_count (mt), sizeof (struct ipcp_modify));
  }
  
+ /* Set modify of i-th formal of mt.  */
  static inline void  
  ipcp_method_modify_set (ipcp_method mt, int i, bool val)
  {
    ((struct ipa_node *)mt->aux)->ipcp_mod[i].mod = val;
  }
  
! static void
! ipa_cloned_create (ipcp_method orig_node, ipcp_method new_node)
  {
!   ipa_node_create (new_node);
!   ipcp_method_set_orig_node (new_node, orig_node);
!   ipcp_method_formal_compute_count (new_node);
!   ipcp_method_compute_tree_map (new_node);
  
  }
  
  /* Returning the parameter index of the ptree.  */
*************** ipcp_modify_walk_tree (tree *tp, void *d
*** 702,714 ****
  	}
        break;
      case ADDR_EXPR:
        if( TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL )
          {
  	  i = ipcp_method_tree_map (mt, TREE_OPERAND (t, 0));
            ipcp_method_modify_set (mt, i, true);
          }
        break;
!     case ASM_EXPR:   
        for (j = 0; j < ipcp_method_formal_count (mt); j++)
  	{
  	  ipcp_method_modify_set (mt, j, true);
--- 755,770 ----
  	}
        break;
      case ADDR_EXPR:
+       /* If the parametr's address is taken, 
+          it could be modified.  */
        if( TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL )
          {
  	  i = ipcp_method_tree_map (mt, TREE_OPERAND (t, 0));
            ipcp_method_modify_set (mt, i, true);
          }
        break;
!     case ASM_EXPR:  
!       /* Asm code could modify any of the parameters.  */
        for (j = 0; j < ipcp_method_formal_count (mt); j++)
  	{
  	  ipcp_method_modify_set (mt, j, true);
*************** ipcp_method_compute_modify (ipcp_method 
*** 743,749 ****
  
    ipcp_method_modify_init (mt);
    decl = mt->decl;
!   if (!tree_inlinable_function_p (decl))
      {
        for (j = 0; j < ipcp_method_formal_count (mt); j++)
  	{
--- 799,807 ----
  
    ipcp_method_modify_init (mt);
    decl = mt->decl;
!   /* ??? Handle pending sizes case. Set all parameters 
!      of the method to be modified.  */  
!   if (DECL_UNINLINABLE (decl))
      {
        for (j = 0; j < ipcp_method_formal_count (mt); j++)
  	{
*************** ipcp_walk_statements (ipcp_method mt, tr
*** 784,803 ****
      }
  }
  
! /* jump function interface.  */
  
  static inline enum Jfunc_type
  get_type (struct ipcp_jump_func *jf)
  {
    return jf->type;
  }
  
  static inline ipcp_int *
  ipcp_jf_get_info_type (struct ipcp_jump_func *jf) 
  {
    return &(jf->info_type);
  }
  
  static inline void 
  ipcp_jf_set_info_type (struct ipcp_jump_func *jf, ipcp_int *info_type)
  {
--- 842,864 ----
      }
  }
  
! /* ipcp_jump_func interface.  */
  
+ /* Get type of jump function jf.  */
  static inline enum Jfunc_type
  get_type (struct ipcp_jump_func *jf)
  {
    return jf->type;
  }
  
+ /* Get info type of jump function jf.  */
  static inline ipcp_int *
  ipcp_jf_get_info_type (struct ipcp_jump_func *jf) 
  {
    return &(jf->info_type);
  }
  
+ /* Set info type of jump function jf.  */
  static inline void 
  ipcp_jf_set_info_type (struct ipcp_jump_func *jf, ipcp_int *info_type)
  {
*************** ipcp_jf_set_info_type (struct ipcp_jump_
*** 805,810 ****
--- 866,872 ----
    jf->info_type.high = info_type->high;
  }
  
+ /* Transform const_val to an ipcp_int type.  */
  static inline void 
  ipcp_int2ipcp_int (ipcp_int *info_type, int const_val)
  {
*************** ipcp_int2ipcp_int (ipcp_int *info_type, 
*** 812,817 ****
--- 874,880 ----
    info_type->high = 0;
  }
  
+ /* Returns low part of info_type as an int.  */
  static inline int
  ipcp_get_int (ipcp_int *info_type)
  {
*************** ipcp_get_int (ipcp_int *info_type)
*** 820,831 ****
--- 883,896 ----
  
  /* cval interface.  */
  
+ /* Sets type to cval.  */
  static inline void 
  ipcp_cval_set_cvalue_type (struct ipcp_formal *cval, enum Cvalue_type type)
  {
    cval->cvalue_type = type;
  }
  
+ /* Sets value to cval.  */
  static inline void
  ipcp_cval_set_cvalue (struct ipcp_formal *cval, ipcp_int *value) 
  {
*************** ipcp_cval_set_cvalue (struct ipcp_formal
*** 833,850 ****
--- 898,918 ----
    cval->cvalue.high = value->high;
  }
  
+ /* Returns value part of cval.  */
  static inline ipcp_int *
  ipcp_cval_get_cvalue (struct ipcp_formal *cval)
  {
    return &(cval->cvalue);
  }
  
+ /* Returns type part of cval.  */
  static inline enum Cvalue_type
  ipcp_cval_get_cvalue_type (struct ipcp_formal *cval)
  {
    return cval->cvalue_type;
  }
  
+ /* Returns true if const_val1 and const_val2 are equal.  */
  static inline bool 
  ipcp_cval_equal_cvalues (ipcp_int *const_val1, ipcp_int *const_val2)
  {
*************** ipcp_cval_equal_cvalues (ipcp_int *const
*** 858,864 ****
     it the first statemant in the function FN
     parse tree.
     PARM1 is the lhs of the assignment and
!    is the rhs. */
  static void 
  constant_val_insert (tree fn, tree parm1, tree val)
  {
--- 926,932 ----
     it the first statemant in the function FN
     parse tree.
     PARM1 is the lhs of the assignment and
!    val is the rhs. */
  static void 
  constant_val_insert (tree fn, tree parm1, tree val)
  {
*************** constant_val_insert (tree fn, tree parm1
*** 868,874 ****
    tree stmt_list_body;
    tree body;
    
!   tree rhs = convert (TREE_TYPE (parm1), val);
    if (rhs == error_mark_node)
      return;
    init_stmt = build (MODIFY_EXPR, TREE_TYPE (parm1), parm1, rhs);
--- 936,942 ----
    tree stmt_list_body;
    tree body;
    
!   tree rhs = fold_convert (TREE_TYPE (parm1), val);
    if (rhs == error_mark_node)
      return;
    init_stmt = build (MODIFY_EXPR, TREE_TYPE (parm1), parm1, rhs);
*************** ipcp_propagate_const (ipcp_method mt, in
*** 898,941 ****
    parm_tree = ipcp_method_get_tree (mt, param);
    const_val = build_int_cst_wide (NULL_TREE, cvalue->low, cvalue->high);   
    if (parm_tree != NULL)
!     if (const_val != NULL)
!       if(fndecl != NULL)
! 	constant_val_insert (fndecl, parm_tree, const_val);   
! }
! 
! /* Propagates the constant parameters found by ipcp_stage2()
!    to the function's code.  */
! static void 
! ipcp_stage3 (void)
! {
!   ipcp_method node;
!   int i;
!   ipcp_int *cvalue;
!  
!   for (node = cgraph_nodes; node; node = node->next)
!     {  
!       /* Propagation of the constant is forbidden in 
!          certain conditions.  */
!       if (ipcp_method_dont_propagate (node))
!         continue;
!       for(i=0; i < ipcp_method_formal_count (node); i++)
! 	{
! 	  if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) 
! 	      == CONST_VALUE) 
! 	    {
! 	      cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
!               ipcp_propagate_const (node, i, cvalue);                       
! 	    }
! 	}
!     }
  }
  
! /* Initialization and computation of IPA Constant
!    Propagation data structures. It is an IntraProcedural
     analysis of methods,which gathers information to be propagated
     later on.  */
  static void 
! ipcp_stage1 (void)
  {
     ipcp_method node;
     ipcp_callsite cs;
--- 966,981 ----
    parm_tree = ipcp_method_get_tree (mt, param);
    const_val = build_int_cst_wide (NULL_TREE, cvalue->low, cvalue->high);   
    if (parm_tree != NULL)
!     if(fndecl != NULL)
!       constant_val_insert (fndecl, parm_tree, const_val);   
  }
  
! /* Initialization and computation of IPCP data structures. 
!    It is an intraprocedural
     analysis of methods,which gathers information to be propagated
     later on.  */
  static void 
! ipcp_init_stage (void)
  {
     ipcp_method node;
     ipcp_callsite cs;
*************** ipcp_stage1 (void)
*** 950,962 ****
     for (node = cgraph_nodes; node; node = node->next)
       {
         /* building jump functions  */
!        for (cs = ipcp_cs_get_first (node); ipcp_cs_not_last (cs);
!             cs = ipcp_cs_get_next (cs))
           {
             ipcp_callsite_compute_count (cs);
             if (ipcp_callsite_param_count (cs) 
  	       != ipcp_method_formal_count (cs->callee))
               {
                 ipcp_callsite_param_count_set (cs, 0);
                 ipcp_method_formal_count_set (cs->callee, 0);
               }
--- 990,1004 ----
     for (node = cgraph_nodes; node; node = node->next)
       {
         /* building jump functions  */
!        for (cs =  FIRST_CALLEE (node); CALLEE_NOT_LAST (cs);
!             cs = NEXT_CALLEE (cs))
           {
             ipcp_callsite_compute_count (cs);
             if (ipcp_callsite_param_count (cs) 
  	       != ipcp_method_formal_count (cs->callee))
               {
+                /* Handles the cases of functions with 
+                   a variable number of parameters.  */
                 ipcp_callsite_param_count_set (cs, 0);
                 ipcp_method_formal_count_set (cs->callee, 0);
               }
*************** ipcp_stage1 (void)
*** 969,975 ****
  /* Interprocedural analysis. The algorithm propagates constants from
     the caller's parameters to the callee's arguments.  */
  static void 
! ipcp_stage2 (void)
  {
    int i;
    struct ipcp_formal cval1 = {0, {0, 0}}, cval = {0, {0, 0}};
--- 1011,1017 ----
  /* Interprocedural analysis. The algorithm propagates constants from
     the caller's parameters to the callee's arguments.  */
  static void 
! ipcp_iterate_stage (void)
  {
    int i;
    struct ipcp_formal cval1 = {0, {0, 0}}, cval = {0, {0, 0}};
*************** ipcp_stage2 (void)
*** 985,992 ****
    while (ipcp_methodlist_not_empty (wl))
      {
        mt = ipcp_remove_method (&wl);
!       for (cs = ipcp_cs_get_first (mt); ipcp_cs_not_last (cs); 
! 	   cs = ipcp_cs_get_next (cs))
  	{
  	  callee = ipcp_callsite_callee (cs);
  	  for (i = 0; i < ipcp_callsite_param_count (cs); i++)
--- 1027,1034 ----
    while (ipcp_methodlist_not_empty (wl))
      {
        mt = ipcp_remove_method (&wl);
!       for (cs = FIRST_CALLEE (mt); CALLEE_NOT_LAST (cs); 
! 	   cs = NEXT_CALLEE (cs))
  	{
  	  callee = ipcp_callsite_callee (cs);
  	  for (i = 0; i < ipcp_callsite_param_count (cs); i++)
*************** ipcp_stage2 (void)
*** 1008,1014 ****
      }
  }
  
! /* Allocate and initialize ipa_node structure.  */
  static void
  ipa_nodes_create (void)
  {
--- 1050,1110 ----
      }
  }
  
! /* Propagates the constant parameters found by ipcp_iterate_stage()
!    to the function's code.  */
! static void 
! ipcp_insert_stage (void)
! {
!   ipcp_method node, node1 = NULL;
!   int i, const_param;
!   ipcp_int *cvalue;
!   varray_type redirect_callers;
!   ipcp_callsite cs;
!   int node_callers;
!    
!   for (node = cgraph_nodes; node; node = node->next)
!     {  
!       /* Propagation of the constant is forbidden in 
!          certain conditions.  */
!       if (ipcp_method_dont_insert_const (node))
!         continue;
!       const_param=0;
!       for(i = 0; i < ipcp_method_formal_count (node); i++)
! 	{
! 	  if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) 
! 	      == CONST_VALUE) 
! 	    {
! 	      cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));             
!               if (const_param == 0)
!                 {
!                   /* Compute how many callers node has.  */
!                   node_callers = 0;
!                   for (cs = node->callers; cs != NULL;
!                        cs = cs->next_caller)
!                     node_callers++;  
!                   VARRAY_GENERIC_PTR_INIT (redirect_callers, node_callers, "redirect_callers");
!                   for (cs = node->callers; cs != NULL;
!                        cs = cs->next_caller)
!                     VARRAY_PUSH_GENERIC_PTR (redirect_callers, cs);
!                   /* Redirecting all the callers of the node to the 
!                      new versioned node.  */
!                   node1 = cgraph_function_versioning (node, redirect_callers); 
!                   VARRAY_CLEAR (redirect_callers);
!                   if (node1 == NULL)
!                     break;
!                   ipa_cloned_create (node, node1);
!                 }
!               ipcp_propagate_const (node1, i, cvalue);
!               const_param++;           
!              
! 	    }
! 	}
!     }
!   ipcp_update_callgraph ();
! }
! 
! /* Allocate and initialize ipa_node structure for all
!    nodes in callgraph.  */
  static void
  ipa_nodes_create (void)
  {
*************** ipa_nodes_create (void)
*** 1016,1026 ****
    
    for (node = cgraph_nodes; node; node = node->next)
       {
!        node->aux = xcalloc (1, sizeof (struct ipa_node));     
!        ((struct ipa_node *)node->aux)->ipcp_cval = NULL;
!        ((struct ipa_node *)node->aux)->ipcp_arg_num =0;
!        ((struct ipa_node *)node->aux)-> ipcp_param_tree = NULL;
!        ((struct ipa_node *)node->aux)->ipcp_mod = NULL;
       }
  }
  
--- 1112,1118 ----
    
    for (node = cgraph_nodes; node; node = node->next)
       {
!        ipa_node_create (node);
       }
  }
  
*************** ipa_edges_create (void)
*** 1033,1044 ****
    
    for (node = cgraph_nodes; node; node = node->next)
       {
!         for (cs = ipcp_cs_get_first (node); ipcp_cs_not_last (cs);
! 	     cs = ipcp_cs_get_next (cs))
  	  {
  	    cs->aux = xcalloc (1, sizeof (struct ipa_edge));
- 	    ((struct ipa_edge *)cs->aux)->ipcp_param_map = NULL;
- 	    ((struct ipa_edge *)cs->aux)->ipcp_param_num = 0;
  	  }
       
       }
--- 1125,1134 ----
    
    for (node = cgraph_nodes; node; node = node->next)
       {
!         for (cs = FIRST_CALLEE (node); CALLEE_NOT_LAST (cs);
! 	     cs = NEXT_CALLEE (cs))
  	  {
  	    cs->aux = xcalloc (1, sizeof (struct ipa_edge));
  	  }
       
       }
*************** ipa_edges_free (void)
*** 1066,1073 ****
    
    for (node = cgraph_nodes; node; node = node->next)
       {
!         for (cs = ipcp_cs_get_first (node); ipcp_cs_not_last (cs);
! 	     cs = ipcp_cs_get_next (cs))
  	  {
  	   
  	    free (cs->aux);
--- 1156,1163 ----
    
    for (node = cgraph_nodes; node; node = node->next)
       {
!         for (cs = FIRST_CALLEE (node); CALLEE_NOT_LAST (cs);
! 	     cs = NEXT_CALLEE (cs))
  	  {
  	   
  	    free (cs->aux);
*************** ipa_edges_free (void)
*** 1077,1083 ****
       }
  }
  
! /* The IPA constant propagation driver.  */
  void 
  ipcp_driver (void)
  {
--- 1167,1173 ----
       }
  }
  
! /* The IPCP driver.  */
  void 
  ipcp_driver (void)
  {
*************** ipcp_driver (void)
*** 1087,1105 ****
       fprintf (cgraph_dump_file, "\nIPA constant propagation start:\n");
    ipa_nodes_create ();
    ipa_edges_create ();
!   ipcp_stage1 ();
    if (cgraph_dump_file)
      {
        fprintf (cgraph_dump_file, "\nIPA structures before propagation:\n");
        ipcp_structures_print (cgraph_dump_file); 
      }
!   ipcp_stage2 ();
    if (cgraph_dump_file)
      {
        fprintf (cgraph_dump_file, "\nIPA structures after propagation:\n");
        ipcp_structures_print (cgraph_dump_file);      
      }
!   ipcp_stage3 ();  
    ipcp_free (); 
    ipa_nodes_free ();
    ipa_edges_free ();
--- 1177,1200 ----
       fprintf (cgraph_dump_file, "\nIPA constant propagation start:\n");
    ipa_nodes_create ();
    ipa_edges_create ();
!   /* 1. Call the init stage to initialize 
!      the ipa_node and ipa_edge structures.  */
!   ipcp_init_stage ();
    if (cgraph_dump_file)
      {
        fprintf (cgraph_dump_file, "\nIPA structures before propagation:\n");
        ipcp_structures_print (cgraph_dump_file); 
      }
!   /* 2. Do the interprocedural propagation.  */
!   ipcp_iterate_stage ();
    if (cgraph_dump_file)
      {
        fprintf (cgraph_dump_file, "\nIPA structures after propagation:\n");
        ipcp_structures_print (cgraph_dump_file);      
      }
!   /* 3. Insert the constants found to the functions.  */
!   ipcp_insert_stage ();
!   /* Free all IPCP structures.  */
    ipcp_free (); 
    ipa_nodes_free ();
    ipa_edges_free ();
*************** ipcp_driver (void)
*** 1107,1113 ****
      fprintf (cgraph_dump_file, "\nIPA constant propagation end\n");
  }
  
! /* Frees the ipcp_method's IPA data structures.  */
  static void 
  ipcp_free (void)
  {
--- 1202,1208 ----
      fprintf (cgraph_dump_file, "\nIPA constant propagation end\n");
  }
  
! /* Frees the ipcp_method's IPCP data structures.  */
  static void 
  ipcp_free (void)
  {
*************** ipcp_free (void)
*** 1116,1142 ****
  
    for (node = cgraph_nodes; node; node = node->next)
       {
!        free (((struct ipa_node *)node->aux)->ipcp_cval);
!        free (((struct ipa_node *)node->aux)->ipcp_param_tree);
!        free (((struct ipa_node *)node->aux)->ipcp_mod); 
!        for (cs = ipcp_cs_get_first (node); ipcp_cs_not_last (cs);
!             cs = ipcp_cs_get_next (cs))
!          free (((struct ipa_edge *)cs->aux)->ipcp_param_map);
       }
  }
  
! /* Check conditions to forbid constant propagation.  */
  static bool
! ipcp_method_dont_propagate (ipcp_method mt)
  {
!   if (!tree_inlinable_function_p (mt->decl))
      return true;
    if (ipcp_method_contains_asm (mt))
      return true;
    return false;
  }
  
! /* Called by walk_tree to find. Returns true if an asm expr was found  */
  static tree 
  ipcp_asm_walk_tree (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, 
  		    void *data ATTRIBUTE_UNUSED)
--- 1211,1248 ----
  
    for (node = cgraph_nodes; node; node = node->next)
       {
!        if (node->aux == NULL)
!          continue;
!        if (((struct ipa_node *)node->aux)->ipcp_cval)
!          free (((struct ipa_node *)node->aux)->ipcp_cval);      
!        if (((struct ipa_node *)node->aux)->ipcp_param_tree)
!          free (((struct ipa_node *)node->aux)->ipcp_param_tree);      
!        if (((struct ipa_node *)node->aux)->ipcp_mod)
!          free (((struct ipa_node *)node->aux)->ipcp_mod); 
!        for (cs = FIRST_CALLEE (node); CALLEE_NOT_LAST (cs);
!             cs = NEXT_CALLEE (cs))
!          {        
!            if (cs->aux)
!              if (((struct ipa_edge *)cs->aux)->ipcp_param_map)
!                free (((struct ipa_edge *)cs->aux)->ipcp_param_map);
!          }
       }
  }
  
! /* Check conditions to forbid constant insertion to the function.  */
  static bool
! ipcp_method_dont_insert_const (ipcp_method mt)
  {
!   /* ??? Handle pending sizes case.  */  
!   if (DECL_UNINLINABLE (mt->decl))
      return true;
+   /* Prevent propagation in the case of ASM calls.  */  
    if (ipcp_method_contains_asm (mt))
      return true;
    return false;
  }
  
! /* Called by walk_tree to find. Returns true if an asm expr was found.  */
  static tree 
  ipcp_asm_walk_tree (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, 
  		    void *data ATTRIBUTE_UNUSED)
*************** ipcp_method_contains_asm (ipcp_method mt
*** 1169,1177 ****
    return false;
  }
  
! /* Debuffing interface.  */
  
! /* Prints all IPA constant propagation data structures.  */
  static void 
  ipcp_structures_print (FILE *f)
  {
--- 1275,1283 ----
    return false;
  }
  
! /* Debugging interface.  */
  
! /* Prints all IPCP data structures.  */
  static void 
  ipcp_structures_print (FILE *f)
  {
*************** ipcp_structures_print (FILE *f)
*** 1181,1186 ****
--- 1287,1293 ----
    ipcp_callsite_param_print (f);
  }
  
+ /* Prints ipcp_cval data structures.  */
  static void 
  ipcp_method_cval_print (FILE *f)
  {
*************** ipcp_method_cval_print (FILE *f)
*** 1200,1207 ****
                 fprintf (f, " param [%d]: ", i);
  	       fprintf (f, "type is CONST ");
                 cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
! 	       fprintf (f, "value is  %d %d\n",(int)cvalue->high, 
!                         (int)cvalue->low);
  	     }
  	   else if (ipcp_method_cval (node, i)->cvalue_type == TOP)
  	     fprintf(f, "param [%d]: type is TOP  \n", i);           
--- 1307,1315 ----
                 fprintf (f, " param [%d]: ", i);
  	       fprintf (f, "type is CONST ");
                 cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
!                fprintf (f, "value is  "HOST_WIDE_INT_PRINT_DEC
!                         " "HOST_WIDE_INT_PRINT_DEC" \n", 
!                         cvalue->high, cvalue->low);
  	     }
  	   else if (ipcp_method_cval (node, i)->cvalue_type == TOP)
  	     fprintf(f, "param [%d]: type is TOP  \n", i);           
*************** ipcp_method_cval_print (FILE *f)
*** 1211,1216 ****
--- 1319,1325 ----
       }
  }
  
+ /* Prints ipcp_tree_map data structures.  */
  static void  
  ipcp_method_tree_print (FILE *f) 
  {
*************** ipcp_method_tree_print (FILE *f) 
*** 1238,1243 ****
--- 1347,1353 ----
      }
  }
  
+ /* Printf ipcp_modify data structures.  */
  static void  
  ipcp_method_modify_print (FILE *f) 
  {
*************** ipcp_method_modify_print (FILE *f) 
*** 1260,1266 ****
        
      }
  }
!  
  static void  
  ipcp_callsite_param_print (FILE *f)
  {
--- 1370,1376 ----
        
      }
  }
! /* Prints ipcp_jump_func data structures.  */ 
  static void  
  ipcp_callsite_param_print (FILE *f)
  {
*************** ipcp_callsite_param_print (FILE *f)
*** 1274,1281 ****
    fprintf(f, "\nCALLSITE PARAM PRINT\n");
    for (node = cgraph_nodes; node; node = node->next)
      {    
!       for (cs = ipcp_cs_get_first (node); ipcp_cs_not_last (cs);
!             cs = ipcp_cs_get_next (cs))
           {
             fprintf (f, "callsite  %s ", cgraph_node_name (node));
             fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee));
--- 1384,1391 ----
    fprintf(f, "\nCALLSITE PARAM PRINT\n");
    for (node = cgraph_nodes; node; node = node->next)
      {    
!       for (cs = FIRST_CALLEE (node); CALLEE_NOT_LAST (cs);
!             cs =  NEXT_CALLEE (cs))
           {
             fprintf (f, "callsite  %s ", cgraph_node_name (node));
             fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee));
*************** ipcp_callsite_param_print (FILE *f)
*** 1290,1297 ****
                else if (type == CONST_IPATYPE)
                  {
                    fprintf (f, "CONST : ");
!                   fprintf (f, "high: %d low: %d\n",(int)info_type->high, 
!                            (int)info_type->low);
                  }
                else if (type == FORMAL_IPATYPE)
                  {
--- 1400,1408 ----
                else if (type == CONST_IPATYPE)
                  {
                    fprintf (f, "CONST : ");
!                   fprintf (f, " "HOST_WIDE_INT_PRINT_DEC
!                            " "HOST_WIDE_INT_PRINT_DEC" \n", 
!                            info_type->high, info_type->low);
                  }
                else if (type == FORMAL_IPATYPE)
                  {
*************** ipcp_callsite_param_print (FILE *f)
*** 1302,1304 ****
--- 1413,1473 ----
           }
      }
  }
+ 
+ /* Fix the callsites and the callgraph after function cloning was done.  */
+ static void 
+ ipcp_update_callgraph (void)
+ {
+   ipcp_method node, orig_callee;
+   ipcp_callsite cs;
+ 
+    for (node = cgraph_nodes; node; node = node->next)
+      {
+        /* want to fix only original nodes  */
+        if (ipcp_method_is_cloned (node))
+          continue;
+        for (cs = FIRST_CALLEE (node);  CALLEE_NOT_LAST (cs);
+             cs =  NEXT_CALLEE (cs))
+          {
+            if (ipcp_method_is_cloned (cs->callee))
+              {
+                /* Callee is a cloned node  */
+                orig_callee = ipcp_method_orig_node (cs->callee);
+                if (ipcp_redirect (cs))
+                  {
+                    cgraph_redirect_edge_callee (cs, orig_callee);
+                    TREE_OPERAND (TREE_OPERAND (cs->call_expr, 0), 0) = orig_callee->decl;
+                  }
+              }
+          }
+      }
+ }
+ 
+ /* Retruns true if this callsite should be redirected to 
+    the orig callee (instead of the cloned one).  */
+ static bool
+ ipcp_redirect (ipcp_callsite  cs)
+ {
+   ipcp_method caller, callee, orig_callee;
+   int i;
+   struct ipcp_jump_func *jump_func;
+   enum Jfunc_type type;
+   
+   caller = cs->caller;
+   callee = cs->callee;
+   orig_callee =  ipcp_method_orig_node (callee);
+   
+   for (i = 0; i < ipcp_method_formal_count (orig_callee); i++)
+      {
+        if (ipcp_cval_get_cvalue_type (ipcp_method_cval (orig_callee, i)) 
+            == CONST_VALUE) 
+          {
+            jump_func = ipcp_callsite_param (cs, i);
+            type = get_type (jump_func);
+            if (type != CONST_IPATYPE)
+              return true;
+          }
+      }
+   return false;
+ }
+ 
Index: ipa_prop.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/Attic/ipa_prop.h,v
retrieving revision 1.1.2.1
diff -c -3 -p -r1.1.2.1 ipa_prop.h
*** ipa_prop.h	28 Aug 2004 17:26:34 -0000	1.1.2.1
--- ipa_prop.h	5 Oct 2004 08:35:56 -0000
***************
*** 1,6 ****
! /* Callgraph handling code.
!    Copyright (C) 2003, 2004 Free Software Foundation, Inc.
!    Contributed by Razya Ladelsky.
  
  This file is part of GCC.
  
--- 1,6 ----
! /* Interprocedural constant propagation
!    Copyright (C) 2004 Free Software Foundation, Inc.
!    Contributed by Razya Ladelsky <RAZYA@il.ibm.com>
  
  This file is part of GCC.
  
*************** struct ipcp_modify
*** 57,75 ****
  
  struct ipa_node
  {
    /* Array of cvals.  */
    struct ipcp_formal* GTY ((skip (""))) ipcp_cval;
-   int ipcp_arg_num;
    /* Mapping each parameter to its PARM_DECL tree.  */
    struct ipcp_tree_map* GTY ((skip (""))) ipcp_param_tree;
    /* Indicating which parameter is modified in its method.  */
    struct ipcp_modify* GTY ((skip (""))) ipcp_mod;
  };
  
  struct ipa_edge
  {
!   struct ipcp_jump_func* GTY ((skip (""))) ipcp_param_map;
    int ipcp_param_num;
  };
  void ipcp_driver (void);
  
--- 57,85 ----
  
  struct ipa_node
  {
+   /* Number of formal parameters of this method.  When set to 0,
+    this method's parameters would not be analyzed by the different 
+    stages of IPA CP.  */
+   int ipcp_arg_num;
    /* Array of cvals.  */
    struct ipcp_formal* GTY ((skip (""))) ipcp_cval;
    /* Mapping each parameter to its PARM_DECL tree.  */
    struct ipcp_tree_map* GTY ((skip (""))) ipcp_param_tree;
    /* Indicating which parameter is modified in its method.  */
    struct ipcp_modify* GTY ((skip (""))) ipcp_mod;
+    /* Only for cloned nodes this field would not be NULL, 
+   it points to the node that IPA cp cloned from.  */ 
+   struct cgraph_node *ipcp_orig_node;
  };
  
  struct ipa_edge
  {
!   /* Number of actual arguments in this callsite.  When set to 0,
!    this callsite's parameters would not be analyzed by the different 
!    stages of IPA CP.  */
    int ipcp_param_num;
+   /* Array of the callsite's jump function of each parameter.  */
+   struct ipcp_jump_func* GTY ((skip (""))) ipcp_param_map; 
  };
  void ipcp_driver (void);
  
Index: langhooks-def.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/langhooks-def.h,v
retrieving revision 1.34.2.29.2.7
diff -c -3 -p -r1.34.2.29.2.7 langhooks-def.h
*** langhooks-def.h	18 Sep 2004 22:47:14 -0000	1.34.2.29.2.7
--- langhooks-def.h	5 Oct 2004 08:35:56 -0000
*************** extern void lhd_tree_inlining_end_inlini
*** 84,90 ****
  extern tree lhd_tree_inlining_convert_parm_for_inlining (tree, tree, tree, int);
  extern void lhd_initialize_diagnostics (struct diagnostic_context *);
  extern tree lhd_callgraph_analyze_expr (tree *, int *, tree);
! 
  
  /* Declarations for tree gimplification hooks.  */
  extern int lhd_gimplify_expr (tree *, tree *, tree *);
--- 84,90 ----
  extern tree lhd_tree_inlining_convert_parm_for_inlining (tree, tree, tree, int);
  extern void lhd_initialize_diagnostics (struct diagnostic_context *);
  extern tree lhd_callgraph_analyze_expr (tree *, int *, tree);
! extern int lhd_tree_versioning_cannot_version_tree_fn (tree *);
  
  /* Declarations for tree gimplification hooks.  */
  extern int lhd_gimplify_expr (tree *, tree *, tree *);
*************** extern int lhd_gimplify_expr (tree *, tr
*** 170,175 ****
--- 170,184 ----
    LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
  }
  
+ /* Tree versioning hooks.  */
+ #define LANG_HOOKS_TREE_VERSIONING_CANNOT_VERSION_TREE_FN \
+   lhd_tree_versioning_cannot_version_tree_fn
+ 
+ #define LANG_HOOKS_TREE_VERSIONING_INITIALIZER { \
+ LANG_HOOKS_TREE_VERSIONING_CANNOT_VERSION_TREE_FN \
+ }
+ 
+ 
  #define LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR lhd_callgraph_analyze_expr
  #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION NULL
  
*************** extern tree lhd_make_node (enum tree_cod
*** 292,297 ****
--- 301,307 ----
    LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, \
    LANG_HOOKS_FUNCTION_INITIALIZER, \
    LANG_HOOKS_TREE_INLINING_INITIALIZER, \
+   LANG_HOOKS_TREE_VERSIONING_INITIALIZER, \
    LANG_HOOKS_CALLGRAPH_INITIALIZER, \
    LANG_HOOKS_TREE_DUMP_INITIALIZER, \
    LANG_HOOKS_DECLS, \
Index: langhooks.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/langhooks.c,v
retrieving revision 1.31.2.22.2.7
diff -c -3 -p -r1.31.2.22.2.7 langhooks.c
*** langhooks.c	18 Sep 2004 22:47:14 -0000	1.31.2.22.2.7
--- langhooks.c	5 Oct 2004 08:35:56 -0000
*************** lhd_tree_inlining_cannot_inline_tree_fn 
*** 317,322 ****
--- 317,332 ----
    return 0;
  }
  
+ /* lang_hooks.tree_versioning.cannot_version_tree_fn is called to
+    determine whether there are language-specific reasons for not
+    creating a new version to a given function.  */
+ 
+ int
+ lhd_tree_versioning_cannot_version_tree_fn (tree *fnp ATTRIBUTE_UNUSED)
+ {
+   return 0;
+ }
+ 
  /* lang_hooks.tree_inlining.disregard_inline_limits is called to
     determine whether a function should be considered for inlining even
     if it would exceed inlining limits.  */
Index: langhooks.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/langhooks.h,v
retrieving revision 1.42.2.30.2.6
diff -c -3 -p -r1.42.2.30.2.6 langhooks.h
*** langhooks.h	18 Sep 2004 22:47:14 -0000	1.42.2.30.2.6
--- langhooks.h	5 Oct 2004 08:35:56 -0000
*************** struct lang_hooks_for_tree_inlining
*** 47,52 ****
--- 47,59 ----
    tree (*convert_parm_for_inlining) (tree, tree, tree, int);
  };
  
+ 
+ struct lang_hooks_for_tree_versioning
+ {
+   int (*cannot_version_tree_fn) (tree *);
+ };
+ 
+ 
  struct lang_hooks_for_callgraph
  {
    /* The node passed is a language-specific tree node.  If its contents
*************** struct lang_hooks
*** 387,392 ****
--- 394,401 ----
    struct lang_hooks_for_functions function;
  
    struct lang_hooks_for_tree_inlining tree_inlining;
+   
+   struct lang_hooks_for_tree_versioning tree_versioning;  
  
    struct lang_hooks_for_callgraph callgraph;
  
Index: tree-gimple.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/tree-gimple.h,v
retrieving revision 2.1.2.4
diff -c -3 -p -r2.1.2.4 tree-gimple.h
*** tree-gimple.h	9 Sep 2004 10:55:42 -0000	2.1.2.4
--- tree-gimple.h	5 Oct 2004 08:35:56 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 28,33 ****
--- 28,34 ----
  extern tree create_tmp_var_raw (tree, const char *);
  extern tree create_tmp_var_name (const char *);
  extern tree create_tmp_var (tree, const char *);
+ extern tree create_function_name (const char *);
  extern tree get_initialized_tmp_var (tree, tree *, tree *);
  extern tree get_formal_tmp_var (tree, tree *);
  extern void declare_tmp_vars (tree, tree);
Index: tree-inline.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.26.2.83.2.12
diff -c -3 -p -r1.26.2.83.2.12 tree-inline.c
*** tree-inline.c	25 Sep 2004 23:17:57 -0000	1.26.2.83.2.12
--- tree-inline.c	5 Oct 2004 08:35:56 -0000
*************** typedef struct inline_data
*** 102,107 ****
--- 102,109 ----
    bool cloning_p;
    /* Similarly for saving function body.  */
    bool saving_p;
+   /* Versioning function is slightly different from inlining. */
+   bool versioning_p;
    /* Hash table used to prevent walk_tree from visiting the same node
       umpteen million times.  */
    htab_t tree_pruner;
*************** static tree mark_local_for_remap_r (tree
*** 138,143 ****
--- 140,149 ----
  static void unsave_expr_1 (tree);
  static tree unsave_r (tree *, int *, void *);
  static void declare_inline_vars (tree bind_expr, tree vars);
+ static tree copy_arguments_for_versioning (tree, inline_data *);
+ static tree version_body (tree, inline_data *);
+ static tree copy_static_chain (tree, inline_data *);
+ static bool function_versionable_p (tree);
  
  /* Insert a tree->tree mapping for ID.  Despite the name suggests
     that the trees should be variables, it is used for more than that.  */
*************** remap_decl (tree decl, inline_data *id)
*** 169,176 ****
    if (!n)
      {
        /* Make a copy of the variable or label.  */
!       tree t = copy_decl_for_inlining (decl, fn, VARRAY_TREE (id->fns, 0));
! 
        /* Remap types, if necessary.  */
        TREE_TYPE (t) = remap_type (TREE_TYPE (t), id);
        if (TREE_CODE (t) == TYPE_DECL)
--- 175,185 ----
    if (!n)
      {
        /* Make a copy of the variable or label.  */
!       tree t;
!       if (!id->versioning_p)
!         t = copy_decl_for_inlining (decl, fn, VARRAY_TREE (id->fns, 0));
!       else
!         t = copy_decl_for_versioning (decl, fn, VARRAY_TREE (id->fns, 0));
        /* Remap types, if necessary.  */
        TREE_TYPE (t) = remap_type (TREE_TYPE (t), id);
        if (TREE_CODE (t) == TYPE_DECL)
*************** copy_body_r (tree *tp, int *walk_subtree
*** 460,468 ****
      gcc_assert (DECL_EXTERNAL (*tp) || TREE_STATIC (*tp));
  #endif
  
!   /* If this is a RETURN_EXPR, change it into a MODIFY_EXPR and a
!      GOTO_EXPR with the RET_LABEL as its target.  */
!   if (TREE_CODE (*tp) == RETURN_EXPR && id->ret_label)
      {
        tree return_stmt = *tp;
        tree goto_stmt;
--- 469,479 ----
      gcc_assert (DECL_EXTERNAL (*tp) || TREE_STATIC (*tp));
  #endif
  
!   /* If this is a RETURN_STMT, change it into an EXPR_STMT and a
!      GOTO_STMT with the RET_LABEL as its target.  */
!   if (TREE_CODE (*tp) == RETURN_EXPR 
!       && id->ret_label
!       && !id->versioning_p)
      {
        tree return_stmt = *tp;
        tree goto_stmt;
*************** copy_body_r (tree *tp, int *walk_subtree
*** 562,568 ****
  		}
  	    }
  	}
!       else if (TREE_CODE (*tp) == INDIRECT_REF)
  	{
  	  /* Get rid of *& from inline substitutions that can happen when a
  	     pointer argument is an ADDR_EXPR.  */
--- 573,580 ----
  		}
  	    }
  	}
!       else if (TREE_CODE (*tp) == INDIRECT_REF
!                && !id->versioning_p)
  	{
  	  /* Get rid of *& from inline substitutions that can happen when a
  	     pointer argument is an ADDR_EXPR.  */
*************** copy_body_r (tree *tp, int *walk_subtree
*** 602,613 ****
  	    }
  	  else
  	    {
!               struct cgraph_edge *edge
! 		= cgraph_edge (id->current_node, old_node);
! 
! 	      if (edge)
! 	        cgraph_clone_edge (edge, id->node, *tp);
! 	    }
  	}
  
        TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id);
--- 614,639 ----
  	    }
  	  else
  	    {
!               struct cgraph_edge *edge;
!               
!               if (!id->versioning_p)
!                 {
!                   edge = cgraph_edge (id->current_node, old_node);
!                   if (edge)
!                     cgraph_clone_edge (edge, id->node, *tp);
!                 }
!             }
!           if (id->versioning_p)
!             {
!               /* Update the call_expr on the edges from the new versions
!                  to it's callees. */
!               struct cgraph_edge *edge;
!               tree callee;
!               callee = get_callee_fndecl (*tp);
!               edge = cgraph_edge (id->node, old_node);
!               if (edge)
!                 edge->call_expr = *tp;
!             }
  	}
  
        TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id);
*************** declare_inline_vars (tree bind_expr, tre
*** 2470,2472 ****
--- 2496,2655 ----
  
    add_var_to_bind_expr (bind_expr, vars);
  }
+ 
+ 
+ /* Return a copy of the function argument tree.  */
+ static tree 
+ copy_arguments_for_versioning (tree orig_parm, inline_data *id)
+ {
+   tree *arg_copy, *parg;
+   
+   arg_copy = &orig_parm;
+   for (parg = arg_copy; *parg; parg = &TREE_CHAIN (*parg))
+     {
+       tree new = remap_decl (*parg, id);
+       lang_hooks.dup_lang_specific_decl (new);
+       TREE_CHAIN (new) = TREE_CHAIN (*parg);
+       *parg = new;
+     }
+   return orig_parm;
+ }
+ 
+ 
+ /* return a copy of the function tree body.  */
+ static tree
+ version_body (tree body, inline_data *id)
+ {
+   tree new_body = body;
+   
+   walk_tree (&new_body, copy_body_r, id, NULL);
+   return new_body;
+ }
+ 
+ 
+ /* Return a copy of the function static chain.  */
+ static tree
+ copy_static_chain (tree static_chain, inline_data *id)
+ {
+   tree *chain_copy, *pvar;
+   
+   chain_copy = &static_chain;
+   for (pvar = chain_copy; *pvar; pvar = &TREE_CHAIN (*pvar))
+     {
+       tree new = remap_decl (*pvar, id);
+       lang_hooks.dup_lang_specific_decl (new);
+       TREE_CHAIN (new) = TREE_CHAIN (*pvar);
+       *pvar = new;
+     }
+   return static_chain;
+ }
+ 
+ bool
+ tree_versionable_function_p (tree fndecl)
+ {
+   return function_versionable_p (fndecl);
+ }
+ 
+ /* Return true if the function can have a new version.
+    This is a guard for the versioning functionality.  */
+ static bool
+ function_versionable_p (tree fndecl)
+ {
+   if (fndecl == NULL_TREE)
+     return false;
+   /* ??? There are cases where a function is
+      uninlinable but can have a new versions.  */
+   if (!tree_inlinable_function_p (fndecl))  
+     return false;
+   /* ??? Remove the following gaurd.  */
+   if (lang_hooks.tree_versioning.cannot_version_tree_fn (&fndecl))
+     return false;
+ 
+   return true;
+ }
+ 
+ 
+ /* Copy the function tree. 
+    OLD_DECL and NEW_DECL are FUNCTION_DECL tree nodes 
+    of the original function and the new copied function
+    respectively.  This cloning supports function 
+    versioning utility.  */
+ void
+ tree_function_versioning (tree old_decl, tree new_decl) 
+ {
+   struct cgraph_node *old_version_node;
+   struct cgraph_node *new_version_node;
+   inline_data id;
+   tree p;
+   
+   if (TREE_CODE (old_decl) != FUNCTION_DECL
+       || TREE_CODE (new_decl) != FUNCTION_DECL)
+     abort ();
+  
+   old_version_node = cgraph_node (old_decl);
+   new_version_node = cgraph_node (new_decl);
+   
+   /* FIXME: For the moment debug information for the new
+      version is not supported.  */
+   DECL_ARTIFICIAL (new_decl) = 1;
+   DECL_IGNORED_P (new_decl) = 1;
+   
+   /* Generate a new name for the new version. */
+   DECL_NAME (new_decl) = 
+     create_function_name (IDENTIFIER_POINTER (DECL_NAME (old_decl)));
+   /* Create a new SYMBOL_REF rtx for the new name. */
+   if (DECL_RTL (old_decl) != NULL)
+     {
+       SET_DECL_RTL (new_decl, copy_rtx (DECL_RTL (old_decl)));
+       XEXP (DECL_RTL (new_decl), 0) =
+         gen_rtx_SYMBOL_REF (GET_MODE (XEXP (DECL_RTL (old_decl), 0)),
+                             IDENTIFIER_POINTER (DECL_NAME (new_decl)));
+     }
+   
+   /* Prepare the data-structures for
+      coping the tree of the new version. */
+   
+   memset (&id, 0, sizeof (id));
+   /* The new version. */
+   id.node = new_version_node;
+   /* The old version. */
+   id.current_node =  cgraph_node (old_decl);
+   id.versioning_p = true;
+   id.decl_map = splay_tree_new (splay_tree_compare_pointers, 
+                                 NULL, NULL);
+   id.tree_pruner = htab_create (37, htab_hash_pointer,
+ 				htab_eq_pointer, NULL);
+   
+   VARRAY_TREE_INIT (id.fns, 1, "fns");
+   VARRAY_PUSH_TREE (id.fns, new_decl);
+   VARRAY_PUSH_TREE (id.fns, old_decl);
+   
+   /* Copy the function's static chain. */
+   p = DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl;
+   if (p)
+     {
+       DECL_STRUCT_FUNCTION (new_decl)->static_chain_decl =
+         copy_static_chain (DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl, &id);
+     }  
+   
+   /* Copy the function's arguments. */
+   if (DECL_ARGUMENTS (old_decl) != NULL_TREE)
+     {
+       DECL_ARGUMENTS (new_decl) = 
+         copy_arguments_for_versioning (DECL_ARGUMENTS (old_decl), &id);
+     }
+   /* Copy the Function's body. */
+   DECL_SAVED_TREE (new_decl) =
+     version_body (DECL_SAVED_TREE (old_decl), &id);
+   if (DECL_RESULT (old_decl) != NULL_TREE)
+     {
+       tree *res_decl = &DECL_RESULT (old_decl);
+       DECL_RESULT (new_decl) = remap_decl (*res_decl, &id);
+       lang_hooks.dup_lang_specific_decl (DECL_RESULT (new_decl));
+     }
+   
+   /* Clean up.  */
+   htab_delete (id.tree_pruner);
+   splay_tree_delete (id.decl_map);
+   return;
+ }
Index: tree-inline.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/tree-inline.h,v
retrieving revision 1.4.2.6.4.1
diff -c -3 -p -r1.4.2.6.4.1 tree-inline.h
*** tree-inline.h	2 Aug 2004 23:12:02 -0000	1.4.2.6.4.1
--- tree-inline.h	5 Oct 2004 08:35:56 -0000
*************** void clone_body (tree, tree, void *);
*** 31,36 ****
--- 31,38 ----
  tree save_body (tree, tree *, tree *);
  void remap_save_expr (tree *, void *, int *);
  int estimate_num_insns (tree expr);
+ bool tree_versionable_function_p (tree);
+ void tree_function_versioning (tree, tree);
  
  /* 0 if we should not perform inlining.
     1 if we should expand functions calls inline at the tree level.
Index: cp/cp-objcp-common.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/cp-objcp-common.h,v
retrieving revision 1.2.8.3
diff -c -3 -p -r1.2.8.3 cp-objcp-common.h
*** cp/cp-objcp-common.h	25 Sep 2004 23:18:37 -0000	1.2.8.3
--- cp/cp-objcp-common.h	5 Oct 2004 08:35:57 -0000
*************** extern tree objcp_tsubst_copy_and_build 
*** 138,143 ****
--- 138,148 ----
  #undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
  #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION expand_body
  
+ #undef LANG_HOOKS_TREE_VERSIONING_CANNOT_VERSION_TREE_FN
+ #define LANG_HOOKS_TREE_VERSIONING_CANNOT_VERSION_TREE_FN \
+    cp_cannot_version_tree_fn
+  
+ 
  #undef LANG_HOOKS_MAKE_TYPE
  #define LANG_HOOKS_MAKE_TYPE cxx_make_type
  #undef LANG_HOOKS_TYPE_FOR_MODE
Index: cp/cp-tree.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.719.2.51.2.12
diff -c -3 -p -r1.719.2.51.2.12 cp-tree.h
*** cp/cp-tree.h	25 Sep 2004 23:18:37 -0000	1.719.2.51.2.12
--- cp/cp-tree.h	5 Oct 2004 08:35:58 -0000
*************** extern linkage_kind decl_linkage        
*** 4203,4208 ****
--- 4203,4209 ----
  extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
  				      void*, void*);
  extern int cp_cannot_inline_tree_fn (tree*);
+ extern int cp_cannot_version_tree_fn (tree*);
  extern tree cp_add_pending_fn_decls (void*,tree);
  extern int cp_is_overload_p (tree);
  extern int cp_auto_var_in_fn_p (tree,tree);
Index: cp/tree.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.286.2.43.2.11
diff -c -3 -p -r1.286.2.43.2.11 tree.c
*** cp/tree.c	25 Sep 2004 23:18:41 -0000	1.286.2.43.2.11
--- cp/tree.c	5 Oct 2004 08:35:58 -0000
*************** cp_cannot_inline_tree_fn (tree* fnp)
*** 2057,2062 ****
--- 2057,2088 ----
    return 0;
  }
  
+ /* Decide whether there are language-specific reasons to not version a
+    function as a tree.  */
+ 
+ int 
+ cp_cannot_version_tree_fn (tree *fnp)
+ {
+   tree fn = *fnp;
+  
+   /* ??? Is there a way to version a
+      constructor?  */ 
+   if (DECL_COMPLETE_CONSTRUCTOR_P (fn))
+     return 1;
+   if (DECL_BASE_CONSTRUCTOR_P (fn))
+     return 1;
+   if (DECL_COMPLETE_DESTRUCTOR_P (fn))
+     return 1;
+   if (DECL_BASE_DESTRUCTOR_P (fn))
+     return 1;
+   if (DECL_OVERLOADED_OPERATOR_P (fn))
+     return 1;
+  
+   return 0;
+ }
+  
+ 
+ 
  /* Add any pending functions other than the current function (already
     handled by the caller), that thus cannot be inlined, to FNS_P, then
     return the latest function added to the array, PREV_FN.  */

             reply	other threads:[~2004-10-10 15:20 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-10-10 15:38 Razya Ladelsky [this message]
2004-10-10 17:10 ` Steven Bosscher
2004-10-10 21:25   ` Jan Hubicka
2004-10-10 23:00     ` IPA (was: Re: [tree-profiling-branch PATCH] Function cloning + IPCP extension (RESUBMISSION)) Steven Bosscher
2004-10-10 23:34       ` Jan Hubicka
2004-10-12 14:22         ` IPA Kenneth Zadeck
2004-10-12 14:41           ` IPA Jan Hubicka
     [not found]             ` <OF392747EC.15519132-ONC2256F2D.00576111-C2256F2D.005769AD@il.ibm.com>
2004-10-14 16:44               ` IPA Jan Hubicka
2004-10-14 17:22               ` IPA Kenneth Zadeck
     [not found]               ` <416EADEA.2030406@naturalbridge.com>
2004-10-14 17:24                 ` IPA Steven Bosscher
2004-10-14 21:25                   ` IPA Mark Mitchell
2004-10-15  3:39                 ` IPA Daniel Berlin
2004-10-12 14:18 ` [tree-profiling-branch PATCH] Function cloning + IPCP extension (RESUBMISSION) Jan Hubicka
2004-10-11 14:34 Razya Ladelsky
2004-10-11 16:13 ` Steven Bosscher
2004-10-14 16:34   ` Razya Ladelsky
2004-10-14 17:00     ` Jan Hubicka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=OF5CDC40B7.BBE1ECAB-ONC2256F29.0053D8D3-C2256F29.0053FD4F@il.ibm.com \
    --to=razya@il.ibm.com \
    --cc=NAMOLARU@il.ibm.com \
    --cc=ZAKS@il.ibm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=hubicka@ucw.cz \
    --cc=stevenb@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).