1169689Skan/* Interprocedural constant propagation
2169689Skan   Copyright (C) 2005 Free Software Foundation, Inc.
3169689Skan   Contributed by Razya Ladelsky <RAZYA@il.ibm.com>
4169689Skan
5169689SkanThis file is part of GCC.
6169689Skan
7169689SkanGCC is free software; you can redistribute it and/or modify it under
8169689Skanthe terms of the GNU General Public License as published by the Free
9169689SkanSoftware Foundation; either version 2, or (at your option) any later
10169689Skanversion.
11169689Skan
12169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
14169689SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15169689Skanfor more details.
16169689Skan
17169689SkanYou should have received a copy of the GNU General Public License
18169689Skanalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
21169689Skan
22169689Skan/* Interprocedural constant propagation.
23169689Skan   The aim of interprocedural constant propagation (IPCP) is to find which
24169689Skan   function's argument has the same constant value in each invocation throughout
25169689Skan   the whole program. For example, for an application consisting of two files,
26169689Skan   foo1.c, foo2.c:
27169689Skan
28169689Skan   foo1.c contains :
29169689Skan
30169689Skan   int f (int x)
31169689Skan   {
32169689Skan     g (x);
33169689Skan   }
34169689Skan   void main (void)
35169689Skan   {
36169689Skan     f (3);
37169689Skan     h (3);
38169689Skan   }
39169689Skan
40169689Skan   foo2.c contains :
41169689Skan
42169689Skan   int h (int y)
43169689Skan   {
44169689Skan     g (y);
45169689Skan   }
46169689Skan   int g (int y)
47169689Skan   {
48169689Skan     printf ("value is %d",y);
49169689Skan   }
50169689Skan
51169689Skan   The IPCP algorithm will find that g's formal argument y
52169689Skan   is always called with the value 3.
53169689Skan
54169689Skan   The algorithm used is based on "Interprocedural Constant Propagation",
55169689Skan   by Challahan David, Keith D Cooper, Ken Kennedy, Linda Torczon, Comp86,
56169689Skan   pg 152-161
57169689Skan
58169689Skan   The optimization is divided into three stages:
59169689Skan
60169689Skan   First stage - intraprocedural analysis
61169689Skan   =======================================
62169689Skan   This phase computes jump_function and modify information.
63169689Skan
64169689Skan   A jump function for a callsite represents the values passed as actual
65169689Skan   arguments
66169689Skan   of the callsite. There are three types of values :
67169689Skan   Formal - the caller's formal parameter is passed as an actual argument.
68169689Skan   Constant - a constant is passed as a an actual argument.
69169689Skan   Unknown - neither of the above.
70169689Skan
71169689Skan   In order to compute the jump functions, we need the modify information for
72169689Skan   the formal parameters of methods.
73169689Skan
74169689Skan   The jump function info, ipa_jump_func, is defined in ipa_edge
75169689Skan   structure (defined in ipa_prop.h and pointed to by cgraph_node->aux)
76169689Skan   The modify info, ipa_modify, is defined in ipa_node structure
77169689Skan   (defined in ipa_prop.h and pointed to by cgraph_edge->aux).
78169689Skan
79169689Skan   -ipcp_init_stage() is the first stage driver.
80169689Skan
81169689Skan   Second stage - interprocedural analysis
82169689Skan   ========================================
83169689Skan   This phase does the interprocedural constant propagation.
84169689Skan   It computes for all formal parameters in the program
85169689Skan   their cval value that may be:
86169689Skan   TOP - unknown.
87169689Skan   BOTTOM - non constant.
88169689Skan   CONSTANT_TYPE - constant value.
89169689Skan
90169689Skan   Cval of formal f will have a constant value if all callsites to this
91169689Skan   function have the same constant value passed to f.
92169689Skan
93169689Skan   The cval info, ipcp_formal, is defined in ipa_node structure
94169689Skan   (defined in ipa_prop.h and pointed to by cgraph_edge->aux).
95169689Skan
96169689Skan   -ipcp_iterate_stage() is the second stage driver.
97169689Skan
98169689Skan   Third phase - transformation of methods code
99169689Skan   ============================================
100169689Skan   Propagates the constant-valued formals into the function.
101169689Skan   For each method mt, whose parameters are consts, we create a clone/version.
102169689Skan
103169689Skan   We use two ways to annotate the versioned function with the constant
104169689Skan   formal information:
105169689Skan   1. We insert an assignment statement 'parameter = const' at the beginning
106169689Skan   of the cloned method.
107169689Skan   2. For read-only formals whose address is not taken, we replace all uses
108169689Skan   of the formal with the constant (we provide versioning with an
109169689Skan   ipa_replace_map struct representing the trees we want to replace).
110169689Skan
111169689Skan   We also need to modify some callsites to call to the cloned methods instead
112169689Skan   of the original ones. For a callsite passing an argument found to be a
113169689Skan   constant by IPCP, there are two different cases to handle:
114169689Skan   1. A constant is passed as an argument.
115169689Skan   2. A parameter (of the caller) passed as an argument (pass through argument).
116169689Skan
117169689Skan   In the first case, the callsite in the original caller should be redirected
118169689Skan   to call the cloned callee.
119169689Skan   In the second case, both the caller and the callee have clones
120169689Skan   and the callsite of the cloned caller would be redirected to call to
121169689Skan   the cloned callee.
122169689Skan
123169689Skan   The callgraph is updated accordingly.
124169689Skan
125169689Skan   This update is done in two stages:
126169689Skan   First all cloned methods are created during a traversal of the callgraph,
127169689Skan   during which all callsites are redirected to call the cloned method.
128169689Skan   Then the callsites are traversed and updated as described above.
129169689Skan
130169689Skan   -ipcp_insert_stage() is the third phase driver.
131169689Skan
132169689Skan*/
133169689Skan
134169689Skan#include "config.h"
135169689Skan#include "system.h"
136169689Skan#include "coretypes.h"
137169689Skan#include "tree.h"
138169689Skan#include "target.h"
139169689Skan#include "cgraph.h"
140169689Skan#include "ipa-prop.h"
141169689Skan#include "tree-flow.h"
142169689Skan#include "tree-pass.h"
143169689Skan#include "flags.h"
144169689Skan#include "timevar.h"
145169689Skan#include "diagnostic.h"
146169689Skan
147169689Skan/* Get orig node field of ipa_node associated with method MT.  */
148169689Skanstatic inline struct cgraph_node *
149169689Skanipcp_method_orig_node (struct cgraph_node *mt)
150169689Skan{
151169689Skan  return IPA_NODE_REF (mt)->ipcp_orig_node;
152169689Skan}
153169689Skan
154169689Skan/* Return true if NODE is a cloned/versioned method.  */
155169689Skanstatic inline bool
156169689Skanipcp_method_is_cloned (struct cgraph_node *node)
157169689Skan{
158169689Skan  return (ipcp_method_orig_node (node) != NULL);
159169689Skan}
160169689Skan
161169689Skan/* Set ORIG_NODE in ipa_node associated with method NODE.  */
162169689Skanstatic inline void
163169689Skanipcp_method_set_orig_node (struct cgraph_node *node,
164169689Skan			   struct cgraph_node *orig_node)
165169689Skan{
166169689Skan  IPA_NODE_REF (node)->ipcp_orig_node = orig_node;
167169689Skan}
168169689Skan
169169689Skan/* Create ipa_node and its data structures for NEW_NODE.
170169689Skan   Set ORIG_NODE as the orig_node field in ipa_node.  */
171169689Skanstatic void
172169689Skanipcp_cloned_create (struct cgraph_node *orig_node,
173169689Skan		    struct cgraph_node *new_node)
174169689Skan{
175169689Skan  ipa_node_create (new_node);
176169689Skan  ipcp_method_set_orig_node (new_node, orig_node);
177169689Skan  ipa_method_formal_compute_count (new_node);
178169689Skan  ipa_method_compute_tree_map (new_node);
179169689Skan}
180169689Skan
181169689Skan/* Return cval_type field of CVAL.  */
182169689Skanstatic inline enum cvalue_type
183169689Skanipcp_cval_get_cvalue_type (struct ipcp_formal *cval)
184169689Skan{
185169689Skan  return cval->cval_type;
186169689Skan}
187169689Skan
188169689Skan/* Return scale for MT.  */
189169689Skanstatic inline gcov_type
190169689Skanipcp_method_get_scale (struct cgraph_node *mt)
191169689Skan{
192169689Skan  return IPA_NODE_REF (mt)->count_scale;
193169689Skan}
194169689Skan
195169689Skan/* Set COUNT as scale for MT.  */
196169689Skanstatic inline void
197169689Skanipcp_method_set_scale (struct cgraph_node *node, gcov_type count)
198169689Skan{
199169689Skan  IPA_NODE_REF (node)->count_scale = count;
200169689Skan}
201169689Skan
202169689Skan/* Set TYPE as cval_type field of CVAL.  */
203169689Skanstatic inline void
204169689Skanipcp_cval_set_cvalue_type (struct ipcp_formal *cval, enum cvalue_type type)
205169689Skan{
206169689Skan  cval->cval_type = type;
207169689Skan}
208169689Skan
209169689Skan/* Return cvalue field of CVAL.  */
210169689Skanstatic inline union parameter_info *
211169689Skanipcp_cval_get_cvalue (struct ipcp_formal *cval)
212169689Skan{
213169689Skan  return &(cval->cvalue);
214169689Skan}
215169689Skan
216169689Skan/* Set VALUE as cvalue field  CVAL.  */
217169689Skanstatic inline void
218169689Skanipcp_cval_set_cvalue (struct ipcp_formal *cval, union parameter_info *value,
219169689Skan		      enum cvalue_type type)
220169689Skan{
221169689Skan  if (type == CONST_VALUE || type == CONST_VALUE_REF)
222169689Skan    cval->cvalue.value =  value->value;
223169689Skan}
224169689Skan
225169689Skan/* Return whether TYPE is a constant type.  */
226169689Skanstatic bool
227169689Skanipcp_type_is_const (enum cvalue_type type)
228169689Skan{
229169689Skan  if (type == CONST_VALUE || type == CONST_VALUE_REF)
230169689Skan    return true;
231169689Skan  else
232169689Skan    return false;
233169689Skan}
234169689Skan
235169689Skan/* Return true if CONST_VAL1 and CONST_VAL2 are equal.  */
236169689Skanstatic inline bool
237169689Skanipcp_cval_equal_cvalues (union parameter_info *const_val1,
238169689Skan			 union parameter_info *const_val2,
239169689Skan			 enum cvalue_type type1, enum cvalue_type type2)
240169689Skan{
241169689Skan  gcc_assert (ipcp_type_is_const (type1) && ipcp_type_is_const (type2));
242169689Skan  if (type1 != type2)
243169689Skan    return false;
244169689Skan
245169689Skan  if (operand_equal_p (const_val1->value, const_val2->value, 0))
246169689Skan    return true;
247169689Skan
248169689Skan  return false;
249169689Skan}
250169689Skan
251169689Skan/* Compute Meet arithmetics:
252169689Skan   Meet (BOTTOM, x) = BOTTOM
253169689Skan   Meet (TOP,x) = x
254169689Skan   Meet (const_a,const_b) = BOTTOM,  if const_a != const_b.
255169689Skan   MEET (const_a,const_b) = const_a, if const_a == const_b.*/
256169689Skanstatic void
257169689Skanipcp_cval_meet (struct ipcp_formal *cval, struct ipcp_formal *cval1,
258169689Skan		struct ipcp_formal *cval2)
259169689Skan{
260169689Skan  if (ipcp_cval_get_cvalue_type (cval1) == BOTTOM
261169689Skan      || ipcp_cval_get_cvalue_type (cval2) == BOTTOM)
262169689Skan    {
263169689Skan      ipcp_cval_set_cvalue_type (cval, BOTTOM);
264169689Skan      return;
265169689Skan    }
266169689Skan  if (ipcp_cval_get_cvalue_type (cval1) == TOP)
267169689Skan    {
268169689Skan      ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval2));
269169689Skan      ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval2),
270169689Skan			    ipcp_cval_get_cvalue_type (cval2));
271169689Skan      return;
272169689Skan    }
273169689Skan  if (ipcp_cval_get_cvalue_type (cval2) == TOP)
274169689Skan    {
275169689Skan      ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval1));
276169689Skan      ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval1),
277169689Skan			    ipcp_cval_get_cvalue_type (cval1));
278169689Skan      return;
279169689Skan    }
280169689Skan  if (!ipcp_cval_equal_cvalues (ipcp_cval_get_cvalue (cval1),
281169689Skan				ipcp_cval_get_cvalue (cval2),
282169689Skan				ipcp_cval_get_cvalue_type (cval1),
283169689Skan				ipcp_cval_get_cvalue_type (cval2)))
284169689Skan    {
285169689Skan      ipcp_cval_set_cvalue_type (cval, BOTTOM);
286169689Skan      return;
287169689Skan    }
288169689Skan  ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval1));
289169689Skan  ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval1),
290169689Skan			ipcp_cval_get_cvalue_type (cval1));
291169689Skan}
292169689Skan
293169689Skan/* Return cval structure for the formal at index INFO_TYPE in MT.  */
294169689Skanstatic inline struct ipcp_formal *
295169689Skanipcp_method_cval (struct cgraph_node *mt, int info_type)
296169689Skan{
297169689Skan  return &(IPA_NODE_REF (mt)->ipcp_cval[info_type]);
298169689Skan}
299169689Skan
300169689Skan/* Given the jump function (TYPE, INFO_TYPE), compute a new value of CVAL.
301169689Skan   If TYPE is FORMAL_IPA_TYPE, the cval of the corresponding formal is
302169689Skan   drawn from MT.  */
303169689Skanstatic void
304169689Skanipcp_cval_compute (struct ipcp_formal *cval, struct cgraph_node *mt,
305169689Skan		   enum jump_func_type type, union parameter_info *info_type)
306169689Skan{
307169689Skan  if (type == UNKNOWN_IPATYPE)
308169689Skan    ipcp_cval_set_cvalue_type (cval, BOTTOM);
309169689Skan  else if (type == CONST_IPATYPE)
310169689Skan    {
311169689Skan      ipcp_cval_set_cvalue_type (cval, CONST_VALUE);
312169689Skan      ipcp_cval_set_cvalue (cval, info_type, CONST_VALUE);
313169689Skan    }
314169689Skan  else if (type == CONST_IPATYPE_REF)
315169689Skan    {
316169689Skan      ipcp_cval_set_cvalue_type (cval, CONST_VALUE_REF);
317169689Skan      ipcp_cval_set_cvalue (cval, info_type, CONST_VALUE_REF);
318169689Skan    }
319169689Skan  else if (type == FORMAL_IPATYPE)
320169689Skan    {
321169689Skan      enum cvalue_type type =
322169689Skan	ipcp_cval_get_cvalue_type (ipcp_method_cval
323169689Skan				   (mt, info_type->formal_id));
324169689Skan      ipcp_cval_set_cvalue_type (cval, type);
325169689Skan      ipcp_cval_set_cvalue (cval,
326169689Skan			    ipcp_cval_get_cvalue (ipcp_method_cval
327169689Skan						  (mt, info_type->formal_id)),
328169689Skan			    type);
329169689Skan    }
330169689Skan}
331169689Skan
332169689Skan/* True when CVAL1 and CVAL2 values are not the same.  */
333169689Skanstatic bool
334169689Skanipcp_cval_changed (struct ipcp_formal *cval1, struct ipcp_formal *cval2)
335169689Skan{
336169689Skan  if (ipcp_cval_get_cvalue_type (cval1) == ipcp_cval_get_cvalue_type (cval2))
337169689Skan    {
338169689Skan      if (ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE &&
339169689Skan	  ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE_REF)
340169689Skan	return false;
341169689Skan      if (ipcp_cval_equal_cvalues (ipcp_cval_get_cvalue (cval1),
342169689Skan				   ipcp_cval_get_cvalue (cval2),
343169689Skan				   ipcp_cval_get_cvalue_type (cval1),
344169689Skan				   ipcp_cval_get_cvalue_type (cval2)))
345169689Skan	return false;
346169689Skan    }
347169689Skan  return true;
348169689Skan}
349169689Skan
350169689Skan/* Create cval structure for method MT.  */
351169689Skanstatic inline void
352169689Skanipcp_formal_create (struct cgraph_node *mt)
353169689Skan{
354169689Skan  IPA_NODE_REF (mt)->ipcp_cval =
355169689Skan    XCNEWVEC (struct ipcp_formal, ipa_method_formal_count (mt));
356169689Skan}
357169689Skan
358169689Skan/* Set cval structure of I-th formal of MT to CVAL.  */
359169689Skanstatic inline void
360169689Skanipcp_method_cval_set (struct cgraph_node *mt, int i, struct ipcp_formal *cval)
361169689Skan{
362169689Skan  IPA_NODE_REF (mt)->ipcp_cval[i].cval_type = cval->cval_type;
363169689Skan  ipcp_cval_set_cvalue (ipcp_method_cval (mt, i),
364169689Skan			ipcp_cval_get_cvalue (cval), cval->cval_type);
365169689Skan}
366169689Skan
367169689Skan/* Set type of cval structure of formal I of MT to CVAL_TYPE1.  */
368169689Skanstatic inline void
369169689Skanipcp_method_cval_set_cvalue_type (struct cgraph_node *mt, int i,
370169689Skan				  enum cvalue_type cval_type1)
371169689Skan{
372169689Skan  IPA_NODE_REF (mt)->ipcp_cval[i].cval_type = cval_type1;
373169689Skan}
374169689Skan
375169689Skan/* Print ipcp_cval data structures to F.  */
376169689Skanstatic void
377169689Skanipcp_method_cval_print (FILE * f)
378169689Skan{
379169689Skan  struct cgraph_node *node;
380169689Skan  int i, count;
381169689Skan  tree cvalue;
382169689Skan
383169689Skan  fprintf (f, "\nCVAL PRINT\n");
384169689Skan  for (node = cgraph_nodes; node; node = node->next)
385169689Skan    {
386169689Skan      fprintf (f, "Printing cvals %s:\n", cgraph_node_name (node));
387169689Skan      count = ipa_method_formal_count (node);
388169689Skan      for (i = 0; i < count; i++)
389169689Skan	{
390169689Skan	  if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i))
391169689Skan	      == CONST_VALUE
392169689Skan	      || ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) ==
393169689Skan	      CONST_VALUE_REF)
394169689Skan	    {
395169689Skan	      fprintf (f, " param [%d]: ", i);
396169689Skan	      fprintf (f, "type is CONST ");
397169689Skan	      cvalue =
398169689Skan		ipcp_cval_get_cvalue (ipcp_method_cval (node, i))->
399169689Skan		  value;
400169689Skan              print_generic_expr (f, cvalue, 0);
401169689Skan              fprintf (f, "\n");
402169689Skan	    }
403169689Skan	  else if (ipcp_method_cval (node, i)->cval_type == TOP)
404169689Skan	    fprintf (f, "param [%d]: type is TOP  \n", i);
405169689Skan	  else
406169689Skan	    fprintf (f, "param [%d]: type is BOTTOM  \n", i);
407169689Skan	}
408169689Skan    }
409169689Skan}
410169689Skan
411169689Skan/* Initialize ipcp_cval array of MT with TOP values.
412169689Skan   All cvals for a method's formal parameters are initialized to BOTTOM
413169689Skan   The currently supported types are integer types, real types and
414169689Skan   Fortran constants (i.e. references to constants defined as
415169689Skan   const_decls). All other types are not analyzed and therefore are
416169689Skan   assigned with BOTTOM.  */
417169689Skanstatic void
418169689Skanipcp_method_cval_init (struct cgraph_node *mt)
419169689Skan{
420169689Skan  int i;
421169689Skan  tree parm_tree;
422169689Skan
423169689Skan  ipcp_formal_create (mt);
424169689Skan  for (i = 0; i < ipa_method_formal_count (mt); i++)
425169689Skan    {
426169689Skan      parm_tree = ipa_method_get_tree (mt, i);
427169689Skan      if (INTEGRAL_TYPE_P (TREE_TYPE (parm_tree))
428169689Skan	  || SCALAR_FLOAT_TYPE_P (TREE_TYPE (parm_tree))
429169689Skan	  || POINTER_TYPE_P (TREE_TYPE (parm_tree)))
430169689Skan	ipcp_method_cval_set_cvalue_type (mt, i, TOP);
431169689Skan      else
432169689Skan	ipcp_method_cval_set_cvalue_type (mt, i, BOTTOM);
433169689Skan    }
434169689Skan}
435169689Skan
436169689Skan/* Create a new assignment statment and make
437169689Skan   it the first statement in the function FN
438169689Skan   tree.
439169689Skan   PARM1 is the lhs of the assignment and
440169689Skan   VAL is the rhs. */
441169689Skanstatic void
442169689Skanconstant_val_insert (tree fn, tree parm1, tree val)
443169689Skan{
444169689Skan  struct function *func;
445169689Skan  tree init_stmt;
446169689Skan  edge e_step;
447169689Skan  edge_iterator ei;
448169689Skan
449169689Skan  init_stmt = build2 (MODIFY_EXPR, void_type_node, parm1, val);
450169689Skan  func = DECL_STRUCT_FUNCTION (fn);
451169689Skan  cfun = func;
452169689Skan  current_function_decl = fn;
453169689Skan  if (ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->succs)
454169689Skan    FOR_EACH_EDGE (e_step, ei, ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->succs)
455169689Skan      bsi_insert_on_edge_immediate (e_step, init_stmt);
456169689Skan}
457169689Skan
458169689Skan/* build INTEGER_CST tree with type TREE_TYPE and
459169689Skan   value according to CVALUE. Return the tree.   */
460169689Skanstatic tree
461169689Skanbuild_const_val (union parameter_info *cvalue, enum cvalue_type type,
462169689Skan		 tree tree_type)
463169689Skan{
464169689Skan  tree const_val = NULL;
465169689Skan
466169689Skan  gcc_assert (ipcp_type_is_const (type));
467169689Skan  const_val = fold_convert (tree_type, cvalue->value);
468169689Skan  return const_val;
469169689Skan}
470169689Skan
471169689Skan/* Build the tree representing the constant and call
472169689Skan   constant_val_insert().  */
473169689Skanstatic void
474169689Skanipcp_propagate_const (struct cgraph_node *mt, int param,
475169689Skan		      union parameter_info *cvalue ,enum cvalue_type type)
476169689Skan{
477169689Skan  tree fndecl;
478169689Skan  tree const_val;
479169689Skan  tree parm_tree;
480169689Skan
481169689Skan  if (dump_file)
482169689Skan    fprintf (dump_file, "propagating const to %s\n", cgraph_node_name (mt));
483169689Skan  fndecl = mt->decl;
484169689Skan  parm_tree = ipa_method_get_tree (mt, param);
485169689Skan  const_val = build_const_val (cvalue, type, TREE_TYPE (parm_tree));
486169689Skan  constant_val_insert (fndecl, parm_tree, const_val);
487169689Skan}
488169689Skan
489169689Skan/* Compute the proper scale for NODE.  It is the ratio between
490169689Skan   the number of direct calls (represented on the incoming
491169689Skan   cgraph_edges) and sum of all invocations of NODE (represented
492169689Skan   as count in cgraph_node). */
493169689Skanstatic void
494169689Skanipcp_method_compute_scale (struct cgraph_node *node)
495169689Skan{
496169689Skan  gcov_type sum;
497169689Skan  struct cgraph_edge *cs;
498169689Skan
499169689Skan  sum = 0;
500169689Skan  /* Compute sum of all counts of callers. */
501169689Skan  for (cs = node->callers; cs != NULL; cs = cs->next_caller)
502169689Skan    sum += cs->count;
503169689Skan  if (node->count == 0)
504169689Skan    ipcp_method_set_scale (node, 0);
505169689Skan  else
506169689Skan    ipcp_method_set_scale (node, sum * REG_BR_PROB_BASE / node->count);
507169689Skan}
508169689Skan
509169689Skan/* Initialization and computation of IPCP data structures.
510169689Skan   It is an intraprocedural
511169689Skan   analysis of methods, which gathers information to be propagated
512169689Skan   later on.  */
513169689Skanstatic void
514169689Skanipcp_init_stage (void)
515169689Skan{
516169689Skan  struct cgraph_node *node;
517169689Skan  struct cgraph_edge *cs;
518169689Skan
519169689Skan  for (node = cgraph_nodes; node; node = node->next)
520169689Skan    {
521169689Skan      ipa_method_formal_compute_count (node);
522169689Skan      ipa_method_compute_tree_map (node);
523169689Skan      ipcp_method_cval_init (node);
524169689Skan      ipa_method_compute_modify (node);
525169689Skan      ipcp_method_compute_scale (node);
526169689Skan    }
527169689Skan  for (node = cgraph_nodes; node; node = node->next)
528169689Skan    {
529169689Skan      /* building jump functions  */
530169689Skan      for (cs = node->callees; cs; cs = cs->next_callee)
531169689Skan	{
532169689Skan	  ipa_callsite_compute_count (cs);
533169689Skan	  if (ipa_callsite_param_count (cs)
534169689Skan	      != ipa_method_formal_count (cs->callee))
535169689Skan	    {
536169689Skan	      /* Handle cases of functions with
537169689Skan	         a variable number of parameters.  */
538169689Skan	      ipa_callsite_param_count_set (cs, 0);
539169689Skan	      ipa_method_formal_count_set (cs->callee, 0);
540169689Skan	    }
541169689Skan	  else
542169689Skan	    ipa_callsite_compute_param (cs);
543169689Skan	}
544169689Skan    }
545169689Skan}
546169689Skan
547169689Skan/* Return true if there are some formal parameters whose value is TOP.
548169689Skan   Change their values to BOTTOM, since they weren't determined.  */
549169689Skanstatic bool
550169689Skanipcp_after_propagate (void)
551169689Skan{
552169689Skan  int i, count;
553169689Skan  struct cgraph_node *node;
554169689Skan  bool prop_again;
555169689Skan
556169689Skan  prop_again = false;
557169689Skan  for (node = cgraph_nodes; node; node = node->next)
558169689Skan    {
559169689Skan      count = ipa_method_formal_count (node);
560169689Skan      for (i = 0; i < count; i++)
561169689Skan	if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) == TOP)
562169689Skan	  {
563169689Skan	    prop_again = true;
564169689Skan	    ipcp_method_cval_set_cvalue_type (node, i, BOTTOM);
565169689Skan	  }
566169689Skan    }
567169689Skan  return prop_again;
568169689Skan}
569169689Skan
570169689Skan/* Interprocedural analysis. The algorithm propagates constants from
571169689Skan   the caller's parameters to the callee's arguments.  */
572169689Skanstatic void
573169689Skanipcp_propagate_stage (void)
574169689Skan{
575169689Skan  int i;
576169689Skan  struct ipcp_formal cval1 = { 0, {0} }, cval = { 0,{0} };
577169689Skan  struct ipcp_formal *cval2;
578169689Skan  struct cgraph_node *mt, *callee;
579169689Skan  struct cgraph_edge *cs;
580169689Skan  struct ipa_jump_func *jump_func;
581169689Skan  enum jump_func_type type;
582169689Skan  union parameter_info *info_type;
583169689Skan  ipa_methodlist_p wl;
584169689Skan  int count;
585169689Skan
586169689Skan  /* Initialize worklist to contain all methods.  */
587169689Skan  wl = ipa_methodlist_init ();
588169689Skan  while (ipa_methodlist_not_empty (wl))
589169689Skan    {
590169689Skan      mt = ipa_remove_method (&wl);
591169689Skan      for (cs = mt->callees; cs; cs = cs->next_callee)
592169689Skan	{
593169689Skan	  callee = ipa_callsite_callee (cs);
594169689Skan	  count = ipa_callsite_param_count (cs);
595169689Skan	  for (i = 0; i < count; i++)
596169689Skan	    {
597169689Skan	      jump_func = ipa_callsite_param (cs, i);
598169689Skan	      type = get_type (jump_func);
599169689Skan	      info_type = ipa_jf_get_info_type (jump_func);
600169689Skan	      ipcp_cval_compute (&cval1, mt, type, info_type);
601169689Skan	      cval2 = ipcp_method_cval (callee, i);
602169689Skan	      ipcp_cval_meet (&cval, &cval1, cval2);
603169689Skan	      if (ipcp_cval_changed (&cval, cval2))
604169689Skan		{
605169689Skan		  ipcp_method_cval_set (callee, i, &cval);
606169689Skan		  ipa_add_method (&wl, callee);
607169689Skan		}
608169689Skan	    }
609169689Skan	}
610169689Skan    }
611169689Skan}
612169689Skan
613169689Skan/* Call the constant propagation algorithm and re-call it if necessary
614169689Skan   (if there are undetermined values left).  */
615169689Skanstatic void
616169689Skanipcp_iterate_stage (void)
617169689Skan{
618169689Skan  ipcp_propagate_stage ();
619169689Skan  if (ipcp_after_propagate ())
620169689Skan    /* Some cvals have changed from TOP to BOTTOM.
621169689Skan       This change should be propagated.  */
622169689Skan    ipcp_propagate_stage ();
623169689Skan}
624169689Skan
625169689Skan/* Check conditions to forbid constant insertion to MT.  */
626169689Skanstatic bool
627169689Skanipcp_method_dont_insert_const (struct cgraph_node *mt)
628169689Skan{
629169689Skan  /* ??? Handle pending sizes case.  */
630169689Skan  if (DECL_UNINLINABLE (mt->decl))
631169689Skan    return true;
632169689Skan  return false;
633169689Skan}
634169689Skan
635169689Skan/* Print ipa_jump_func data structures to F.  */
636169689Skanstatic void
637169689Skanipcp_callsite_param_print (FILE * f)
638169689Skan{
639169689Skan  struct cgraph_node *node;
640169689Skan  int i, count;
641169689Skan  struct cgraph_edge *cs;
642169689Skan  struct ipa_jump_func *jump_func;
643169689Skan  enum jump_func_type type;
644169689Skan  tree info_type;
645169689Skan
646169689Skan  fprintf (f, "\nCALLSITE PARAM PRINT\n");
647169689Skan  for (node = cgraph_nodes; node; node = node->next)
648169689Skan    {
649169689Skan      for (cs = node->callees; cs; cs = cs->next_callee)
650169689Skan	{
651169689Skan	  fprintf (f, "callsite  %s ", cgraph_node_name (node));
652169689Skan	  fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee));
653169689Skan	  count = ipa_callsite_param_count (cs);
654169689Skan	  for (i = 0; i < count; i++)
655169689Skan	    {
656169689Skan	      jump_func = ipa_callsite_param (cs, i);
657169689Skan	      type = get_type (jump_func);
658169689Skan
659169689Skan	      fprintf (f, " param %d: ", i);
660169689Skan	      if (type == UNKNOWN_IPATYPE)
661169689Skan		fprintf (f, "UNKNOWN\n");
662169689Skan	      else if (type == CONST_IPATYPE || type == CONST_IPATYPE_REF)
663169689Skan		{
664169689Skan		  info_type =
665169689Skan		    ipa_jf_get_info_type (jump_func)->value;
666169689Skan                  fprintf (f, "CONST : ");
667169689Skan                  print_generic_expr (f, info_type, 0);
668169689Skan                  fprintf (f, "\n");
669169689Skan		}
670169689Skan	      else if (type == FORMAL_IPATYPE)
671169689Skan		{
672169689Skan		  fprintf (f, "FORMAL : ");
673169689Skan		  fprintf (f, "%d\n",
674169689Skan			   ipa_jf_get_info_type (jump_func)->formal_id);
675169689Skan		}
676169689Skan	    }
677169689Skan	}
678169689Skan    }
679169689Skan}
680169689Skan
681169689Skan/* Print count scale data structures.  */
682169689Skanstatic void
683169689Skanipcp_method_scale_print (FILE * f)
684169689Skan{
685169689Skan  struct cgraph_node *node;
686169689Skan
687169689Skan  for (node = cgraph_nodes; node; node = node->next)
688169689Skan    {
689169689Skan      fprintf (f, "printing scale for %s: ", cgraph_node_name (node));
690169689Skan      fprintf (f, "value is  " HOST_WIDE_INT_PRINT_DEC
691169689Skan	       "  \n", (HOST_WIDE_INT) ipcp_method_get_scale (node));
692169689Skan    }
693169689Skan}
694169689Skan
695169689Skan/* Print counts of all cgraph nodes.  */
696169689Skanstatic void
697169689Skanipcp_profile_mt_count_print (FILE * f)
698169689Skan{
699169689Skan  struct cgraph_node *node;
700169689Skan
701169689Skan  for (node = cgraph_nodes; node; node = node->next)
702169689Skan    {
703169689Skan      fprintf (f, "method %s: ", cgraph_node_name (node));
704169689Skan      fprintf (f, "count is  " HOST_WIDE_INT_PRINT_DEC
705169689Skan	       "  \n", (HOST_WIDE_INT) node->count);
706169689Skan    }
707169689Skan}
708169689Skan
709169689Skan/* Print counts of all cgraph edges.  */
710169689Skanstatic void
711169689Skanipcp_profile_cs_count_print (FILE * f)
712169689Skan{
713169689Skan  struct cgraph_node *node;
714169689Skan  struct cgraph_edge *cs;
715169689Skan
716169689Skan  for (node = cgraph_nodes; node; node = node->next)
717169689Skan    {
718169689Skan      for (cs = node->callees; cs; cs = cs->next_callee)
719169689Skan	{
720169689Skan	  fprintf (f, "%s -> %s ", cgraph_node_name (cs->caller),
721169689Skan		   cgraph_node_name (cs->callee));
722169689Skan	  fprintf (f, "count is  " HOST_WIDE_INT_PRINT_DEC "  \n",
723169689Skan		   (HOST_WIDE_INT) cs->count);
724169689Skan	}
725169689Skan    }
726169689Skan}
727169689Skan
728169689Skan/* Print all counts and probabilities of cfg edges of all methods.  */
729169689Skanstatic void
730169689Skanipcp_profile_edge_print (FILE * f)
731169689Skan{
732169689Skan  struct cgraph_node *node;
733169689Skan  basic_block bb;
734169689Skan  edge_iterator ei;
735169689Skan  edge e;
736169689Skan
737169689Skan  for (node = cgraph_nodes; node; node = node->next)
738169689Skan    {
739169689Skan      fprintf (f, "method %s: \n", cgraph_node_name (node));
740169689Skan      if (DECL_SAVED_TREE (node->decl))
741169689Skan	{
742169689Skan	  bb =
743169689Skan	    ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
744169689Skan	  fprintf (f, "ENTRY: ");
745169689Skan	  fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
746169689Skan		   " %d\n", (HOST_WIDE_INT) bb->count, bb->frequency);
747169689Skan
748169689Skan	  if (bb->succs)
749169689Skan	    FOR_EACH_EDGE (e, ei, bb->succs)
750169689Skan	    {
751169689Skan	      if (e->dest ==
752169689Skan		  EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION
753169689Skan					       (node->decl)))
754169689Skan		fprintf (f, "edge ENTRY -> EXIT,  Count");
755169689Skan	      else
756169689Skan		fprintf (f, "edge ENTRY -> %d,  Count", e->dest->index);
757169689Skan	      fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
758169689Skan		       " Prob %d\n", (HOST_WIDE_INT) e->count,
759169689Skan		       e->probability);
760169689Skan	    }
761169689Skan	  FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
762169689Skan	  {
763169689Skan	    fprintf (f, "bb[%d]: ", bb->index);
764169689Skan	    fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
765169689Skan		     " %d\n", (HOST_WIDE_INT) bb->count, bb->frequency);
766169689Skan	    FOR_EACH_EDGE (e, ei, bb->succs)
767169689Skan	    {
768169689Skan	      if (e->dest ==
769169689Skan		  EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION
770169689Skan					       (node->decl)))
771169689Skan		fprintf (f, "edge %d -> EXIT,  Count", e->src->index);
772169689Skan	      else
773169689Skan		fprintf (f, "edge %d -> %d,  Count", e->src->index,
774169689Skan			 e->dest->index);
775169689Skan	      fprintf (f, " " HOST_WIDE_INT_PRINT_DEC " Prob %d\n",
776169689Skan		       (HOST_WIDE_INT) e->count, e->probability);
777169689Skan	    }
778169689Skan	  }
779169689Skan	}
780169689Skan    }
781169689Skan}
782169689Skan
783169689Skan/* Print counts and frequencies for all basic blocks of all methods.  */
784169689Skanstatic void
785169689Skanipcp_profile_bb_print (FILE * f)
786169689Skan{
787169689Skan  basic_block bb;
788169689Skan  struct cgraph_node *node;
789169689Skan
790169689Skan  for (node = cgraph_nodes; node; node = node->next)
791169689Skan    {
792169689Skan      fprintf (f, "method %s: \n", cgraph_node_name (node));
793169689Skan      if (DECL_SAVED_TREE (node->decl))
794169689Skan	{
795169689Skan	  bb =
796169689Skan	    ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
797169689Skan	  fprintf (f, "ENTRY: Count");
798169689Skan	  fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
799169689Skan		   " Frquency  %d\n", (HOST_WIDE_INT) bb->count,
800169689Skan		   bb->frequency);
801169689Skan
802169689Skan	  FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
803169689Skan	  {
804169689Skan	    fprintf (f, "bb[%d]: Count", bb->index);
805169689Skan	    fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
806169689Skan		     " Frequency %d\n", (HOST_WIDE_INT) bb->count,
807169689Skan		     bb->frequency);
808169689Skan	  }
809169689Skan	  bb =
810169689Skan	    EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
811169689Skan	  fprintf (f, "EXIT: Count");
812169689Skan	  fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
813169689Skan		   " Frequency %d\n", (HOST_WIDE_INT) bb->count,
814169689Skan		   bb->frequency);
815169689Skan
816169689Skan	}
817169689Skan    }
818169689Skan}
819169689Skan
820169689Skan/* Print all IPCP data structures to F.  */
821169689Skanstatic void
822169689Skanipcp_structures_print (FILE * f)
823169689Skan{
824169689Skan  ipcp_method_cval_print (f);
825169689Skan  ipcp_method_scale_print (f);
826169689Skan  ipa_method_tree_print (f);
827169689Skan  ipa_method_modify_print (f);
828169689Skan  ipcp_callsite_param_print (f);
829169689Skan}
830169689Skan
831169689Skan/* Print profile info for all methods.  */
832169689Skanstatic void
833169689Skanipcp_profile_print (FILE * f)
834169689Skan{
835169689Skan  fprintf (f, "\nNODE COUNTS :\n");
836169689Skan  ipcp_profile_mt_count_print (f);
837169689Skan  fprintf (f, "\nCS COUNTS stage:\n");
838169689Skan  ipcp_profile_cs_count_print (f);
839169689Skan  fprintf (f, "\nBB COUNTS and FREQUENCIES :\n");
840169689Skan  ipcp_profile_bb_print (f);
841169689Skan  fprintf (f, "\nCFG EDGES COUNTS and PROBABILITIES :\n");
842169689Skan  ipcp_profile_edge_print (f);
843169689Skan}
844169689Skan
845169689Skan/* Build and initialize ipa_replace_map struct
846169689Skan   according to TYPE. This struct is read by versioning, which
847169689Skan   operates according to the flags sent.  PARM_TREE is the
848169689Skan   formal's tree found to be constant.  CVALUE represents the constant.  */
849169689Skanstatic struct ipa_replace_map *
850169689Skanipcp_replace_map_create (enum cvalue_type type, tree parm_tree,
851169689Skan			 union parameter_info *cvalue)
852169689Skan{
853169689Skan  struct ipa_replace_map *replace_map;
854169689Skan  tree const_val;
855169689Skan
856169689Skan  replace_map = XCNEW (struct ipa_replace_map);
857169689Skan  gcc_assert (ipcp_type_is_const (type));
858169689Skan  if (type == CONST_VALUE_REF )
859169689Skan    {
860169689Skan      const_val =
861169689Skan	build_const_val (cvalue, type, TREE_TYPE (TREE_TYPE (parm_tree)));
862169689Skan      replace_map->old_tree = parm_tree;
863169689Skan      replace_map->new_tree = const_val;
864169689Skan      replace_map->replace_p = true;
865169689Skan      replace_map->ref_p = true;
866169689Skan    }
867169689Skan  else if (TREE_READONLY (parm_tree) && !TREE_ADDRESSABLE (parm_tree))
868169689Skan    {
869169689Skan      const_val = build_const_val (cvalue, type, TREE_TYPE (parm_tree));
870169689Skan      replace_map->old_tree = parm_tree;
871169689Skan      replace_map->new_tree = const_val;
872169689Skan      replace_map->replace_p = true;
873169689Skan      replace_map->ref_p = false;
874169689Skan    }
875169689Skan  else
876169689Skan    {
877169689Skan      replace_map->old_tree = NULL;
878169689Skan      replace_map->new_tree = NULL;
879169689Skan      replace_map->replace_p = false;
880169689Skan      replace_map->ref_p = false;
881169689Skan    }
882169689Skan
883169689Skan  return replace_map;
884169689Skan}
885169689Skan
886169689Skan/* Return true if this callsite should be redirected to
887169689Skan   the orig callee (instead of the cloned one).  */
888169689Skanstatic bool
889169689Skanipcp_redirect (struct cgraph_edge *cs)
890169689Skan{
891169689Skan  struct cgraph_node *caller, *callee, *orig_callee;
892169689Skan  int i, count;
893169689Skan  struct ipa_jump_func *jump_func;
894169689Skan  enum jump_func_type type;
895169689Skan  enum cvalue_type cval_type;
896169689Skan
897169689Skan  caller = cs->caller;
898169689Skan  callee = cs->callee;
899169689Skan  orig_callee = ipcp_method_orig_node (callee);
900169689Skan  count = ipa_method_formal_count (orig_callee);
901169689Skan  for (i = 0; i < count; i++)
902169689Skan    {
903169689Skan      cval_type =
904169689Skan	ipcp_cval_get_cvalue_type (ipcp_method_cval (orig_callee, i));
905169689Skan      if (ipcp_type_is_const (cval_type))
906169689Skan	{
907169689Skan	  jump_func = ipa_callsite_param (cs, i);
908169689Skan	  type = get_type (jump_func);
909169689Skan	  if (type != CONST_IPATYPE
910169689Skan	      && type != CONST_IPATYPE_REF)
911169689Skan	    return true;
912169689Skan	}
913169689Skan    }
914169689Skan
915169689Skan  return false;
916169689Skan}
917169689Skan
918169689Skan/* Fix the callsites and the callgraph after function cloning was done.  */
919169689Skanstatic void
920169689Skanipcp_update_callgraph (void)
921169689Skan{
922169689Skan  struct cgraph_node *node, *orig_callee;
923169689Skan  struct cgraph_edge *cs;
924169689Skan
925169689Skan  for (node = cgraph_nodes; node; node = node->next)
926169689Skan    {
927169689Skan      /* want to fix only original nodes  */
928169689Skan      if (ipcp_method_is_cloned (node))
929169689Skan	continue;
930169689Skan      for (cs = node->callees; cs; cs = cs->next_callee)
931169689Skan	if (ipcp_method_is_cloned (cs->callee))
932169689Skan	  {
933169689Skan	    /* Callee is a cloned node  */
934169689Skan	    orig_callee = ipcp_method_orig_node (cs->callee);
935169689Skan	    if (ipcp_redirect (cs))
936169689Skan	      {
937169689Skan		cgraph_redirect_edge_callee (cs, orig_callee);
938169689Skan		TREE_OPERAND (TREE_OPERAND
939169689Skan			      (get_call_expr_in (cs->call_stmt), 0), 0) =
940169689Skan		  orig_callee->decl;
941169689Skan	      }
942169689Skan	  }
943169689Skan    }
944169689Skan}
945169689Skan
946169689Skan/* Update all cfg basic blocks in NODE according to SCALE.  */
947169689Skanstatic void
948169689Skanipcp_update_bb_counts (struct cgraph_node *node, gcov_type scale)
949169689Skan{
950169689Skan  basic_block bb;
951169689Skan
952169689Skan  FOR_ALL_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
953169689Skan    bb->count = bb->count * scale / REG_BR_PROB_BASE;
954169689Skan}
955169689Skan
956169689Skan/* Update all cfg edges in NODE according to SCALE.  */
957169689Skanstatic void
958169689Skanipcp_update_edges_counts (struct cgraph_node *node, gcov_type scale)
959169689Skan{
960169689Skan  basic_block bb;
961169689Skan  edge_iterator ei;
962169689Skan  edge e;
963169689Skan
964169689Skan  FOR_ALL_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
965169689Skan    FOR_EACH_EDGE (e, ei, bb->succs)
966169689Skan    e->count = e->count * scale / REG_BR_PROB_BASE;
967169689Skan}
968169689Skan
969169689Skan/* Update profiling info for versioned methods and the
970169689Skan   methods they were versioned from.  */
971169689Skanstatic void
972169689Skanipcp_update_profiling (void)
973169689Skan{
974169689Skan  struct cgraph_node *node, *orig_node;
975169689Skan  gcov_type scale, scale_complement;
976169689Skan  struct cgraph_edge *cs;
977169689Skan
978169689Skan  for (node = cgraph_nodes; node; node = node->next)
979169689Skan    {
980169689Skan      if (ipcp_method_is_cloned (node))
981169689Skan	{
982169689Skan	  orig_node = ipcp_method_orig_node (node);
983169689Skan	  scale = ipcp_method_get_scale (orig_node);
984169689Skan	  node->count = orig_node->count * scale / REG_BR_PROB_BASE;
985169689Skan	  scale_complement = REG_BR_PROB_BASE - scale;
986169689Skan	  orig_node->count =
987169689Skan	    orig_node->count * scale_complement / REG_BR_PROB_BASE;
988169689Skan	  for (cs = node->callees; cs; cs = cs->next_callee)
989169689Skan	    cs->count = cs->count * scale / REG_BR_PROB_BASE;
990169689Skan	  for (cs = orig_node->callees; cs; cs = cs->next_callee)
991169689Skan	    cs->count = cs->count * scale_complement / REG_BR_PROB_BASE;
992169689Skan	  ipcp_update_bb_counts (node, scale);
993169689Skan	  ipcp_update_bb_counts (orig_node, scale_complement);
994169689Skan	  ipcp_update_edges_counts (node, scale);
995169689Skan	  ipcp_update_edges_counts (orig_node, scale_complement);
996169689Skan	}
997169689Skan    }
998169689Skan}
999169689Skan
1000169689Skan/* Propagate the constant parameters found by ipcp_iterate_stage()
1001169689Skan   to the function's code.  */
1002169689Skanstatic void
1003169689Skanipcp_insert_stage (void)
1004169689Skan{
1005169689Skan  struct cgraph_node *node, *node1 = NULL;
1006169689Skan  int i, const_param;
1007169689Skan  union parameter_info *cvalue;
1008169689Skan  VEC(cgraph_edge_p,heap) *redirect_callers;
1009169689Skan  varray_type replace_trees;
1010169689Skan  struct cgraph_edge *cs;
1011169689Skan  int node_callers, count;
1012169689Skan  tree parm_tree;
1013169689Skan  enum cvalue_type type;
1014169689Skan  struct ipa_replace_map *replace_param;
1015169689Skan
1016169689Skan  for (node = cgraph_nodes; node; node = node->next)
1017169689Skan    {
1018169689Skan      /* Propagation of the constant is forbidden in
1019169689Skan         certain conditions.  */
1020169689Skan      if (ipcp_method_dont_insert_const (node))
1021169689Skan	continue;
1022169689Skan      const_param = 0;
1023169689Skan      count = ipa_method_formal_count (node);
1024169689Skan      for (i = 0; i < count; i++)
1025169689Skan	{
1026169689Skan	  type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i));
1027169689Skan	  if (ipcp_type_is_const (type))
1028169689Skan	    const_param++;
1029169689Skan	}
1030169689Skan      if (const_param == 0)
1031169689Skan	continue;
1032169689Skan      VARRAY_GENERIC_PTR_INIT (replace_trees, const_param, "replace_trees");
1033169689Skan      for (i = 0; i < count; i++)
1034169689Skan	{
1035169689Skan	  type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i));
1036169689Skan	  if (ipcp_type_is_const (type))
1037169689Skan	    {
1038169689Skan	      cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
1039169689Skan	      parm_tree = ipa_method_get_tree (node, i);
1040169689Skan	      replace_param =
1041169689Skan		ipcp_replace_map_create (type, parm_tree, cvalue);
1042169689Skan	      VARRAY_PUSH_GENERIC_PTR (replace_trees, replace_param);
1043169689Skan	    }
1044169689Skan	}
1045169689Skan      /* Compute how many callers node has.  */
1046169689Skan      node_callers = 0;
1047169689Skan      for (cs = node->callers; cs != NULL; cs = cs->next_caller)
1048169689Skan	node_callers++;
1049169689Skan      redirect_callers = VEC_alloc (cgraph_edge_p, heap, node_callers);
1050169689Skan      for (cs = node->callers; cs != NULL; cs = cs->next_caller)
1051169689Skan	VEC_quick_push (cgraph_edge_p, redirect_callers, cs);
1052169689Skan      /* Redirecting all the callers of the node to the
1053169689Skan         new versioned node.  */
1054169689Skan      node1 =
1055169689Skan	cgraph_function_versioning (node, redirect_callers, replace_trees);
1056169689Skan      VEC_free (cgraph_edge_p, heap, redirect_callers);
1057169689Skan      VARRAY_CLEAR (replace_trees);
1058169689Skan      if (node1 == NULL)
1059169689Skan	continue;
1060169689Skan      if (dump_file)
1061169689Skan	fprintf (dump_file, "versioned function %s\n",
1062169689Skan		 cgraph_node_name (node));
1063169689Skan      ipcp_cloned_create (node, node1);
1064169689Skan      for (i = 0; i < count; i++)
1065169689Skan	{
1066169689Skan	  type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i));
1067169689Skan	  if (ipcp_type_is_const (type))
1068169689Skan	    {
1069169689Skan	      cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
1070169689Skan	      parm_tree = ipa_method_get_tree (node, i);
1071169689Skan	      if (type != CONST_VALUE_REF
1072169689Skan		  && !TREE_READONLY (parm_tree))
1073169689Skan		ipcp_propagate_const (node1, i, cvalue, type);
1074169689Skan	    }
1075169689Skan	}
1076169689Skan    }
1077169689Skan  ipcp_update_callgraph ();
1078169689Skan  ipcp_update_profiling ();
1079169689Skan}
1080169689Skan
1081169689Skan/* The IPCP driver.  */
1082169689Skanunsigned int
1083169689Skanipcp_driver (void)
1084169689Skan{
1085169689Skan  if (dump_file)
1086169689Skan    fprintf (dump_file, "\nIPA constant propagation start:\n");
1087169689Skan  ipa_nodes_create ();
1088169689Skan  ipa_edges_create ();
1089169689Skan  /* 1. Call the init stage to initialize
1090169689Skan     the ipa_node and ipa_edge structures.  */
1091169689Skan  ipcp_init_stage ();
1092169689Skan  if (dump_file)
1093169689Skan    {
1094169689Skan      fprintf (dump_file, "\nIPA structures before propagation:\n");
1095169689Skan      ipcp_structures_print (dump_file);
1096169689Skan    }
1097169689Skan  /* 2. Do the interprocedural propagation.  */
1098169689Skan  ipcp_iterate_stage ();
1099169689Skan  if (dump_file)
1100169689Skan    {
1101169689Skan      fprintf (dump_file, "\nIPA structures after propagation:\n");
1102169689Skan      ipcp_structures_print (dump_file);
1103169689Skan      fprintf (dump_file, "\nProfiling info before insert stage:\n");
1104169689Skan      ipcp_profile_print (dump_file);
1105169689Skan    }
1106169689Skan  /* 3. Insert the constants found to the functions.  */
1107169689Skan  ipcp_insert_stage ();
1108169689Skan  if (dump_file)
1109169689Skan    {
1110169689Skan      fprintf (dump_file, "\nProfiling info after insert stage:\n");
1111169689Skan      ipcp_profile_print (dump_file);
1112169689Skan    }
1113169689Skan  /* Free all IPCP structures.  */
1114169689Skan  ipa_free ();
1115169689Skan  ipa_nodes_free ();
1116169689Skan  ipa_edges_free ();
1117169689Skan  if (dump_file)
1118169689Skan    fprintf (dump_file, "\nIPA constant propagation end\n");
1119169689Skan  cgraph_remove_unreachable_nodes (true, NULL);
1120169689Skan  return 0;
1121169689Skan}
1122169689Skan
1123169689Skan/* Gate for IPCP optimization.  */
1124169689Skanstatic bool
1125169689Skancgraph_gate_cp (void)
1126169689Skan{
1127169689Skan  return flag_ipa_cp;
1128169689Skan}
1129169689Skan
1130169689Skanstruct tree_opt_pass pass_ipa_cp = {
1131169689Skan  "cp",				/* name */
1132169689Skan  cgraph_gate_cp,		/* gate */
1133169689Skan  ipcp_driver,			/* execute */
1134169689Skan  NULL,				/* sub */
1135169689Skan  NULL,				/* next */
1136169689Skan  0,				/* static_pass_number */
1137169689Skan  TV_IPA_CONSTANT_PROP,		/* tv_id */
1138169689Skan  0,				/* properties_required */
1139169689Skan  PROP_trees,			/* properties_provided */
1140169689Skan  0,				/* properties_destroyed */
1141169689Skan  0,				/* todo_flags_start */
1142169689Skan  TODO_dump_cgraph | TODO_dump_func,	/* todo_flags_finish */
1143169689Skan  0				/* letter */
1144169689Skan};
1145