OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [ipa-cp.c] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* Interprocedural constant propagation
2
   Copyright (C) 2005 Free Software Foundation, Inc.
3
   Contributed by Razya Ladelsky <RAZYA@il.ibm.com>
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 2, or (at your option) any later
10
version.
11
 
12
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GCC; see the file COPYING.  If not, write to the Free
19
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301, USA.  */
21
 
22
/* Interprocedural constant propagation.
23
   The aim of interprocedural constant propagation (IPCP) is to find which
24
   function's argument has the same constant value in each invocation throughout
25
   the whole program. For example, for an application consisting of two files,
26
   foo1.c, foo2.c:
27
 
28
   foo1.c contains :
29
 
30
   int f (int x)
31
   {
32
     g (x);
33
   }
34
   void main (void)
35
   {
36
     f (3);
37
     h (3);
38
   }
39
 
40
   foo2.c contains :
41
 
42
   int h (int y)
43
   {
44
     g (y);
45
   }
46
   int g (int y)
47
   {
48
     printf ("value is %d",y);
49
   }
50
 
51
   The IPCP algorithm will find that g's formal argument y
52
   is always called with the value 3.
53
 
54
   The algorithm used is based on "Interprocedural Constant Propagation",
55
   by Challahan David, Keith D Cooper, Ken Kennedy, Linda Torczon, Comp86,
56
   pg 152-161
57
 
58
   The optimization is divided into three stages:
59
 
60
   First stage - intraprocedural analysis
61
   =======================================
62
   This phase computes jump_function and modify information.
63
 
64
   A jump function for a callsite represents the values passed as actual
65
   arguments
66
   of the callsite. There are three types of values :
67
   Formal - the caller's formal parameter is passed as an actual argument.
68
   Constant - a constant is passed as a an actual argument.
69
   Unknown - neither of the above.
70
 
71
   In order to compute the jump functions, we need the modify information for
72
   the formal parameters of methods.
73
 
74
   The jump function info, ipa_jump_func, is defined in ipa_edge
75
   structure (defined in ipa_prop.h and pointed to by cgraph_node->aux)
76
   The modify info, ipa_modify, is defined in ipa_node structure
77
   (defined in ipa_prop.h and pointed to by cgraph_edge->aux).
78
 
79
   -ipcp_init_stage() is the first stage driver.
80
 
81
   Second stage - interprocedural analysis
82
   ========================================
83
   This phase does the interprocedural constant propagation.
84
   It computes for all formal parameters in the program
85
   their cval value that may be:
86
   TOP - unknown.
87
   BOTTOM - non constant.
88
   CONSTANT_TYPE - constant value.
89
 
90
   Cval of formal f will have a constant value if all callsites to this
91
   function have the same constant value passed to f.
92
 
93
   The cval info, ipcp_formal, is defined in ipa_node structure
94
   (defined in ipa_prop.h and pointed to by cgraph_edge->aux).
95
 
96
   -ipcp_iterate_stage() is the second stage driver.
97
 
98
   Third phase - transformation of methods code
99
   ============================================
100
   Propagates the constant-valued formals into the function.
101
   For each method mt, whose parameters are consts, we create a clone/version.
102
 
103
   We use two ways to annotate the versioned function with the constant
104
   formal information:
105
   1. We insert an assignment statement 'parameter = const' at the beginning
106
   of the cloned method.
107
   2. For read-only formals whose address is not taken, we replace all uses
108
   of the formal with the constant (we provide versioning with an
109
   ipa_replace_map struct representing the trees we want to replace).
110
 
111
   We also need to modify some callsites to call to the cloned methods instead
112
   of the original ones. For a callsite passing an argument found to be a
113
   constant by IPCP, there are two different cases to handle:
114
   1. A constant is passed as an argument.
115
   2. A parameter (of the caller) passed as an argument (pass through argument).
116
 
117
   In the first case, the callsite in the original caller should be redirected
118
   to call the cloned callee.
119
   In the second case, both the caller and the callee have clones
120
   and the callsite of the cloned caller would be redirected to call to
121
   the cloned callee.
122
 
123
   The callgraph is updated accordingly.
124
 
125
   This update is done in two stages:
126
   First all cloned methods are created during a traversal of the callgraph,
127
   during which all callsites are redirected to call the cloned method.
128
   Then the callsites are traversed and updated as described above.
129
 
130
   -ipcp_insert_stage() is the third phase driver.
131
 
132
*/
133
 
134
#include "config.h"
135
#include "system.h"
136
#include "coretypes.h"
137
#include "tree.h"
138
#include "target.h"
139
#include "cgraph.h"
140
#include "ipa-prop.h"
141
#include "tree-flow.h"
142
#include "tree-pass.h"
143
#include "flags.h"
144
#include "timevar.h"
145
#include "diagnostic.h"
146
 
147
/* Get orig node field of ipa_node associated with method MT.  */
148
static inline struct cgraph_node *
149
ipcp_method_orig_node (struct cgraph_node *mt)
150
{
151
  return IPA_NODE_REF (mt)->ipcp_orig_node;
152
}
153
 
154
/* Return true if NODE is a cloned/versioned method.  */
155
static inline bool
156
ipcp_method_is_cloned (struct cgraph_node *node)
157
{
158
  return (ipcp_method_orig_node (node) != NULL);
159
}
160
 
161
/* Set ORIG_NODE in ipa_node associated with method NODE.  */
162
static inline void
163
ipcp_method_set_orig_node (struct cgraph_node *node,
164
                           struct cgraph_node *orig_node)
165
{
166
  IPA_NODE_REF (node)->ipcp_orig_node = orig_node;
167
}
168
 
169
/* Create ipa_node and its data structures for NEW_NODE.
170
   Set ORIG_NODE as the orig_node field in ipa_node.  */
171
static void
172
ipcp_cloned_create (struct cgraph_node *orig_node,
173
                    struct cgraph_node *new_node)
174
{
175
  ipa_node_create (new_node);
176
  ipcp_method_set_orig_node (new_node, orig_node);
177
  ipa_method_formal_compute_count (new_node);
178
  ipa_method_compute_tree_map (new_node);
179
}
180
 
181
/* Return cval_type field of CVAL.  */
182
static inline enum cvalue_type
183
ipcp_cval_get_cvalue_type (struct ipcp_formal *cval)
184
{
185
  return cval->cval_type;
186
}
187
 
188
/* Return scale for MT.  */
189
static inline gcov_type
190
ipcp_method_get_scale (struct cgraph_node *mt)
191
{
192
  return IPA_NODE_REF (mt)->count_scale;
193
}
194
 
195
/* Set COUNT as scale for MT.  */
196
static inline void
197
ipcp_method_set_scale (struct cgraph_node *node, gcov_type count)
198
{
199
  IPA_NODE_REF (node)->count_scale = count;
200
}
201
 
202
/* Set TYPE as cval_type field of CVAL.  */
203
static inline void
204
ipcp_cval_set_cvalue_type (struct ipcp_formal *cval, enum cvalue_type type)
205
{
206
  cval->cval_type = type;
207
}
208
 
209
/* Return cvalue field of CVAL.  */
210
static inline union parameter_info *
211
ipcp_cval_get_cvalue (struct ipcp_formal *cval)
212
{
213
  return &(cval->cvalue);
214
}
215
 
216
/* Set VALUE as cvalue field  CVAL.  */
217
static inline void
218
ipcp_cval_set_cvalue (struct ipcp_formal *cval, union parameter_info *value,
219
                      enum cvalue_type type)
220
{
221
  if (type == CONST_VALUE || type == CONST_VALUE_REF)
222
    cval->cvalue.value =  value->value;
223
}
224
 
225
/* Return whether TYPE is a constant type.  */
226
static bool
227
ipcp_type_is_const (enum cvalue_type type)
228
{
229
  if (type == CONST_VALUE || type == CONST_VALUE_REF)
230
    return true;
231
  else
232
    return false;
233
}
234
 
235
/* Return true if CONST_VAL1 and CONST_VAL2 are equal.  */
236
static inline bool
237
ipcp_cval_equal_cvalues (union parameter_info *const_val1,
238
                         union parameter_info *const_val2,
239
                         enum cvalue_type type1, enum cvalue_type type2)
240
{
241
  gcc_assert (ipcp_type_is_const (type1) && ipcp_type_is_const (type2));
242
  if (type1 != type2)
243
    return false;
244
 
245
  if (operand_equal_p (const_val1->value, const_val2->value, 0))
246
    return true;
247
 
248
  return false;
249
}
250
 
251
/* Compute Meet arithmetics:
252
   Meet (BOTTOM, x) = BOTTOM
253
   Meet (TOP,x) = x
254
   Meet (const_a,const_b) = BOTTOM,  if const_a != const_b.
255
   MEET (const_a,const_b) = const_a, if const_a == const_b.*/
256
static void
257
ipcp_cval_meet (struct ipcp_formal *cval, struct ipcp_formal *cval1,
258
                struct ipcp_formal *cval2)
259
{
260
  if (ipcp_cval_get_cvalue_type (cval1) == BOTTOM
261
      || ipcp_cval_get_cvalue_type (cval2) == BOTTOM)
262
    {
263
      ipcp_cval_set_cvalue_type (cval, BOTTOM);
264
      return;
265
    }
266
  if (ipcp_cval_get_cvalue_type (cval1) == TOP)
267
    {
268
      ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval2));
269
      ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval2),
270
                            ipcp_cval_get_cvalue_type (cval2));
271
      return;
272
    }
273
  if (ipcp_cval_get_cvalue_type (cval2) == TOP)
274
    {
275
      ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval1));
276
      ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval1),
277
                            ipcp_cval_get_cvalue_type (cval1));
278
      return;
279
    }
280
  if (!ipcp_cval_equal_cvalues (ipcp_cval_get_cvalue (cval1),
281
                                ipcp_cval_get_cvalue (cval2),
282
                                ipcp_cval_get_cvalue_type (cval1),
283
                                ipcp_cval_get_cvalue_type (cval2)))
284
    {
285
      ipcp_cval_set_cvalue_type (cval, BOTTOM);
286
      return;
287
    }
288
  ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval1));
289
  ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval1),
290
                        ipcp_cval_get_cvalue_type (cval1));
291
}
292
 
293
/* Return cval structure for the formal at index INFO_TYPE in MT.  */
294
static inline struct ipcp_formal *
295
ipcp_method_cval (struct cgraph_node *mt, int info_type)
296
{
297
  return &(IPA_NODE_REF (mt)->ipcp_cval[info_type]);
298
}
299
 
300
/* Given the jump function (TYPE, INFO_TYPE), compute a new value of CVAL.
301
   If TYPE is FORMAL_IPA_TYPE, the cval of the corresponding formal is
302
   drawn from MT.  */
303
static void
304
ipcp_cval_compute (struct ipcp_formal *cval, struct cgraph_node *mt,
305
                   enum jump_func_type type, union parameter_info *info_type)
306
{
307
  if (type == UNKNOWN_IPATYPE)
308
    ipcp_cval_set_cvalue_type (cval, BOTTOM);
309
  else if (type == CONST_IPATYPE)
310
    {
311
      ipcp_cval_set_cvalue_type (cval, CONST_VALUE);
312
      ipcp_cval_set_cvalue (cval, info_type, CONST_VALUE);
313
    }
314
  else if (type == CONST_IPATYPE_REF)
315
    {
316
      ipcp_cval_set_cvalue_type (cval, CONST_VALUE_REF);
317
      ipcp_cval_set_cvalue (cval, info_type, CONST_VALUE_REF);
318
    }
319
  else if (type == FORMAL_IPATYPE)
320
    {
321
      enum cvalue_type type =
322
        ipcp_cval_get_cvalue_type (ipcp_method_cval
323
                                   (mt, info_type->formal_id));
324
      ipcp_cval_set_cvalue_type (cval, type);
325
      ipcp_cval_set_cvalue (cval,
326
                            ipcp_cval_get_cvalue (ipcp_method_cval
327
                                                  (mt, info_type->formal_id)),
328
                            type);
329
    }
330
}
331
 
332
/* True when CVAL1 and CVAL2 values are not the same.  */
333
static bool
334
ipcp_cval_changed (struct ipcp_formal *cval1, struct ipcp_formal *cval2)
335
{
336
  if (ipcp_cval_get_cvalue_type (cval1) == ipcp_cval_get_cvalue_type (cval2))
337
    {
338
      if (ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE &&
339
          ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE_REF)
340
        return false;
341
      if (ipcp_cval_equal_cvalues (ipcp_cval_get_cvalue (cval1),
342
                                   ipcp_cval_get_cvalue (cval2),
343
                                   ipcp_cval_get_cvalue_type (cval1),
344
                                   ipcp_cval_get_cvalue_type (cval2)))
345
        return false;
346
    }
347
  return true;
348
}
349
 
350
/* Create cval structure for method MT.  */
351
static inline void
352
ipcp_formal_create (struct cgraph_node *mt)
353
{
354
  IPA_NODE_REF (mt)->ipcp_cval =
355
    xcalloc (ipa_method_formal_count (mt), sizeof (struct ipcp_formal));
356
}
357
 
358
/* Set cval structure of I-th formal of MT to CVAL.  */
359
static inline void
360
ipcp_method_cval_set (struct cgraph_node *mt, int i, struct ipcp_formal *cval)
361
{
362
  IPA_NODE_REF (mt)->ipcp_cval[i].cval_type = cval->cval_type;
363
  ipcp_cval_set_cvalue (ipcp_method_cval (mt, i),
364
                        ipcp_cval_get_cvalue (cval), cval->cval_type);
365
}
366
 
367
/* Set type of cval structure of formal I of MT to CVAL_TYPE1.  */
368
static inline void
369
ipcp_method_cval_set_cvalue_type (struct cgraph_node *mt, int i,
370
                                  enum cvalue_type cval_type1)
371
{
372
  IPA_NODE_REF (mt)->ipcp_cval[i].cval_type = cval_type1;
373
}
374
 
375
/* Print ipcp_cval data structures to F.  */
376
static void
377
ipcp_method_cval_print (FILE * f)
378
{
379
  struct cgraph_node *node;
380
  int i, count;
381
  tree cvalue;
382
 
383
  fprintf (f, "\nCVAL PRINT\n");
384
  for (node = cgraph_nodes; node; node = node->next)
385
    {
386
      fprintf (f, "Printing cvals %s:\n", cgraph_node_name (node));
387
      count = ipa_method_formal_count (node);
388
      for (i = 0; i < count; i++)
389
        {
390
          if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i))
391
              == CONST_VALUE
392
              || ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) ==
393
              CONST_VALUE_REF)
394
            {
395
              fprintf (f, " param [%d]: ", i);
396
              fprintf (f, "type is CONST ");
397
              cvalue =
398
                ipcp_cval_get_cvalue (ipcp_method_cval (node, i))->
399
                  value;
400
              print_generic_expr (f, cvalue, 0);
401
              fprintf (f, "\n");
402
            }
403
          else if (ipcp_method_cval (node, i)->cval_type == TOP)
404
            fprintf (f, "param [%d]: type is TOP  \n", i);
405
          else
406
            fprintf (f, "param [%d]: type is BOTTOM  \n", i);
407
        }
408
    }
409
}
410
 
411
/* Initialize ipcp_cval array of MT with TOP values.
412
   All cvals for a method's formal parameters are initialized to BOTTOM
413
   The currently supported types are integer types, real types and
414
   Fortran constants (i.e. references to constants defined as
415
   const_decls). All other types are not analyzed and therefore are
416
   assigned with BOTTOM.  */
417
static void
418
ipcp_method_cval_init (struct cgraph_node *mt)
419
{
420
  int i;
421
  tree parm_tree;
422
 
423
  ipcp_formal_create (mt);
424
  for (i = 0; i < ipa_method_formal_count (mt); i++)
425
    {
426
      parm_tree = ipa_method_get_tree (mt, i);
427
      if (INTEGRAL_TYPE_P (TREE_TYPE (parm_tree))
428
          || SCALAR_FLOAT_TYPE_P (TREE_TYPE (parm_tree))
429
          || POINTER_TYPE_P (TREE_TYPE (parm_tree)))
430
        ipcp_method_cval_set_cvalue_type (mt, i, TOP);
431
      else
432
        ipcp_method_cval_set_cvalue_type (mt, i, BOTTOM);
433
    }
434
}
435
 
436
/* Create a new assignment statment and make
437
   it the first statement in the function FN
438
   tree.
439
   PARM1 is the lhs of the assignment and
440
   VAL is the rhs. */
441
static void
442
constant_val_insert (tree fn, tree parm1, tree val)
443
{
444
  struct function *func;
445
  tree init_stmt;
446
  edge e_step;
447
  edge_iterator ei;
448
 
449
  init_stmt = build2 (MODIFY_EXPR, void_type_node, parm1, val);
450
  func = DECL_STRUCT_FUNCTION (fn);
451
  cfun = func;
452
  current_function_decl = fn;
453
  if (ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->succs)
454
    FOR_EACH_EDGE (e_step, ei, ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->succs)
455
      bsi_insert_on_edge_immediate (e_step, init_stmt);
456
}
457
 
458
/* build INTEGER_CST tree with type TREE_TYPE and
459
   value according to CVALUE. Return the tree.   */
460
static tree
461
build_const_val (union parameter_info *cvalue, enum cvalue_type type,
462
                 tree tree_type)
463
{
464
  tree const_val = NULL;
465
 
466
  gcc_assert (ipcp_type_is_const (type));
467
  const_val = fold_convert (tree_type, cvalue->value);
468
  return const_val;
469
}
470
 
471
/* Build the tree representing the constant and call
472
   constant_val_insert().  */
473
static void
474
ipcp_propagate_const (struct cgraph_node *mt, int param,
475
                      union parameter_info *cvalue ,enum cvalue_type type)
476
{
477
  tree fndecl;
478
  tree const_val;
479
  tree parm_tree;
480
 
481
  if (dump_file)
482
    fprintf (dump_file, "propagating const to %s\n", cgraph_node_name (mt));
483
  fndecl = mt->decl;
484
  parm_tree = ipa_method_get_tree (mt, param);
485
  const_val = build_const_val (cvalue, type, TREE_TYPE (parm_tree));
486
  constant_val_insert (fndecl, parm_tree, const_val);
487
}
488
 
489
/* Compute the proper scale for NODE.  It is the ratio between
490
   the number of direct calls (represented on the incoming
491
   cgraph_edges) and sum of all invocations of NODE (represented
492
   as count in cgraph_node). */
493
static void
494
ipcp_method_compute_scale (struct cgraph_node *node)
495
{
496
  gcov_type sum;
497
  struct cgraph_edge *cs;
498
 
499
  sum = 0;
500
  /* Compute sum of all counts of callers. */
501
  for (cs = node->callers; cs != NULL; cs = cs->next_caller)
502
    sum += cs->count;
503
  if (node->count == 0)
504
    ipcp_method_set_scale (node, 0);
505
  else
506
    ipcp_method_set_scale (node, sum * REG_BR_PROB_BASE / node->count);
507
}
508
 
509
/* Initialization and computation of IPCP data structures.
510
   It is an intraprocedural
511
   analysis of methods, which gathers information to be propagated
512
   later on.  */
513
static void
514
ipcp_init_stage (void)
515
{
516
  struct cgraph_node *node;
517
  struct cgraph_edge *cs;
518
 
519
  for (node = cgraph_nodes; node; node = node->next)
520
    {
521
      ipa_method_formal_compute_count (node);
522
      ipa_method_compute_tree_map (node);
523
      ipcp_method_cval_init (node);
524
      ipa_method_compute_modify (node);
525
      ipcp_method_compute_scale (node);
526
    }
527
  for (node = cgraph_nodes; node; node = node->next)
528
    {
529
      /* building jump functions  */
530
      for (cs = node->callees; cs; cs = cs->next_callee)
531
        {
532
          ipa_callsite_compute_count (cs);
533
          if (ipa_callsite_param_count (cs)
534
              != ipa_method_formal_count (cs->callee))
535
            {
536
              /* Handle cases of functions with
537
                 a variable number of parameters.  */
538
              ipa_callsite_param_count_set (cs, 0);
539
              ipa_method_formal_count_set (cs->callee, 0);
540
            }
541
          else
542
            ipa_callsite_compute_param (cs);
543
        }
544
    }
545
}
546
 
547
/* Return true if there are some formal parameters whose value is TOP.
548
   Change their values to BOTTOM, since they weren't determined.  */
549
static bool
550
ipcp_after_propagate (void)
551
{
552
  int i, count;
553
  struct cgraph_node *node;
554
  bool prop_again;
555
 
556
  prop_again = false;
557
  for (node = cgraph_nodes; node; node = node->next)
558
    {
559
      count = ipa_method_formal_count (node);
560
      for (i = 0; i < count; i++)
561
        if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) == TOP)
562
          {
563
            prop_again = true;
564
            ipcp_method_cval_set_cvalue_type (node, i, BOTTOM);
565
          }
566
    }
567
  return prop_again;
568
}
569
 
570
/* Interprocedural analysis. The algorithm propagates constants from
571
   the caller's parameters to the callee's arguments.  */
572
static void
573
ipcp_propagate_stage (void)
574
{
575
  int i;
576
  struct ipcp_formal cval1 = { 0, {0} }, cval = { 0,{0} };
577
  struct ipcp_formal *cval2;
578
  struct cgraph_node *mt, *callee;
579
  struct cgraph_edge *cs;
580
  struct ipa_jump_func *jump_func;
581
  enum jump_func_type type;
582
  union parameter_info *info_type;
583
  ipa_methodlist_p wl;
584
  int count;
585
 
586
  /* Initialize worklist to contain all methods.  */
587
  wl = ipa_methodlist_init ();
588
  while (ipa_methodlist_not_empty (wl))
589
    {
590
      mt = ipa_remove_method (&wl);
591
      for (cs = mt->callees; cs; cs = cs->next_callee)
592
        {
593
          callee = ipa_callsite_callee (cs);
594
          count = ipa_callsite_param_count (cs);
595
          for (i = 0; i < count; i++)
596
            {
597
              jump_func = ipa_callsite_param (cs, i);
598
              type = get_type (jump_func);
599
              info_type = ipa_jf_get_info_type (jump_func);
600
              ipcp_cval_compute (&cval1, mt, type, info_type);
601
              cval2 = ipcp_method_cval (callee, i);
602
              ipcp_cval_meet (&cval, &cval1, cval2);
603
              if (ipcp_cval_changed (&cval, cval2))
604
                {
605
                  ipcp_method_cval_set (callee, i, &cval);
606
                  ipa_add_method (&wl, callee);
607
                }
608
            }
609
        }
610
    }
611
}
612
 
613
/* Call the constant propagation algorithm and re-call it if necessary
614
   (if there are undetermined values left).  */
615
static void
616
ipcp_iterate_stage (void)
617
{
618
  ipcp_propagate_stage ();
619
  if (ipcp_after_propagate ())
620
    /* Some cvals have changed from TOP to BOTTOM.
621
       This change should be propagated.  */
622
    ipcp_propagate_stage ();
623
}
624
 
625
/* Check conditions to forbid constant insertion to MT.  */
626
static bool
627
ipcp_method_dont_insert_const (struct cgraph_node *mt)
628
{
629
  /* ??? Handle pending sizes case.  */
630
  if (DECL_UNINLINABLE (mt->decl))
631
    return true;
632
  return false;
633
}
634
 
635
/* Print ipa_jump_func data structures to F.  */
636
static void
637
ipcp_callsite_param_print (FILE * f)
638
{
639
  struct cgraph_node *node;
640
  int i, count;
641
  struct cgraph_edge *cs;
642
  struct ipa_jump_func *jump_func;
643
  enum jump_func_type type;
644
  tree info_type;
645
 
646
  fprintf (f, "\nCALLSITE PARAM PRINT\n");
647
  for (node = cgraph_nodes; node; node = node->next)
648
    {
649
      for (cs = node->callees; cs; cs = cs->next_callee)
650
        {
651
          fprintf (f, "callsite  %s ", cgraph_node_name (node));
652
          fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee));
653
          count = ipa_callsite_param_count (cs);
654
          for (i = 0; i < count; i++)
655
            {
656
              jump_func = ipa_callsite_param (cs, i);
657
              type = get_type (jump_func);
658
 
659
              fprintf (f, " param %d: ", i);
660
              if (type == UNKNOWN_IPATYPE)
661
                fprintf (f, "UNKNOWN\n");
662
              else if (type == CONST_IPATYPE || type == CONST_IPATYPE_REF)
663
                {
664
                  info_type =
665
                    ipa_jf_get_info_type (jump_func)->value;
666
                  fprintf (f, "CONST : ");
667
                  print_generic_expr (f, info_type, 0);
668
                  fprintf (f, "\n");
669
                }
670
              else if (type == FORMAL_IPATYPE)
671
                {
672
                  fprintf (f, "FORMAL : ");
673
                  fprintf (f, "%d\n",
674
                           ipa_jf_get_info_type (jump_func)->formal_id);
675
                }
676
            }
677
        }
678
    }
679
}
680
 
681
/* Print count scale data structures.  */
682
static void
683
ipcp_method_scale_print (FILE * f)
684
{
685
  struct cgraph_node *node;
686
 
687
  for (node = cgraph_nodes; node; node = node->next)
688
    {
689
      fprintf (f, "printing scale for %s: ", cgraph_node_name (node));
690
      fprintf (f, "value is  " HOST_WIDE_INT_PRINT_DEC
691
               "  \n", (HOST_WIDE_INT) ipcp_method_get_scale (node));
692
    }
693
}
694
 
695
/* Print counts of all cgraph nodes.  */
696
static void
697
ipcp_profile_mt_count_print (FILE * f)
698
{
699
  struct cgraph_node *node;
700
 
701
  for (node = cgraph_nodes; node; node = node->next)
702
    {
703
      fprintf (f, "method %s: ", cgraph_node_name (node));
704
      fprintf (f, "count is  " HOST_WIDE_INT_PRINT_DEC
705
               "  \n", (HOST_WIDE_INT) node->count);
706
    }
707
}
708
 
709
/* Print counts of all cgraph edges.  */
710
static void
711
ipcp_profile_cs_count_print (FILE * f)
712
{
713
  struct cgraph_node *node;
714
  struct cgraph_edge *cs;
715
 
716
  for (node = cgraph_nodes; node; node = node->next)
717
    {
718
      for (cs = node->callees; cs; cs = cs->next_callee)
719
        {
720
          fprintf (f, "%s -> %s ", cgraph_node_name (cs->caller),
721
                   cgraph_node_name (cs->callee));
722
          fprintf (f, "count is  " HOST_WIDE_INT_PRINT_DEC "  \n",
723
                   (HOST_WIDE_INT) cs->count);
724
        }
725
    }
726
}
727
 
728
/* Print all counts and probabilities of cfg edges of all methods.  */
729
static void
730
ipcp_profile_edge_print (FILE * f)
731
{
732
  struct cgraph_node *node;
733
  basic_block bb;
734
  edge_iterator ei;
735
  edge e;
736
 
737
  for (node = cgraph_nodes; node; node = node->next)
738
    {
739
      fprintf (f, "method %s: \n", cgraph_node_name (node));
740
      if (DECL_SAVED_TREE (node->decl))
741
        {
742
          bb =
743
            ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
744
          fprintf (f, "ENTRY: ");
745
          fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
746
                   " %d\n", (HOST_WIDE_INT) bb->count, bb->frequency);
747
 
748
          if (bb->succs)
749
            FOR_EACH_EDGE (e, ei, bb->succs)
750
            {
751
              if (e->dest ==
752
                  EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION
753
                                               (node->decl)))
754
                fprintf (f, "edge ENTRY -> EXIT,  Count");
755
              else
756
                fprintf (f, "edge ENTRY -> %d,  Count", e->dest->index);
757
              fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
758
                       " Prob %d\n", (HOST_WIDE_INT) e->count,
759
                       e->probability);
760
            }
761
          FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
762
          {
763
            fprintf (f, "bb[%d]: ", bb->index);
764
            fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
765
                     " %d\n", (HOST_WIDE_INT) bb->count, bb->frequency);
766
            FOR_EACH_EDGE (e, ei, bb->succs)
767
            {
768
              if (e->dest ==
769
                  EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION
770
                                               (node->decl)))
771
                fprintf (f, "edge %d -> EXIT,  Count", e->src->index);
772
              else
773
                fprintf (f, "edge %d -> %d,  Count", e->src->index,
774
                         e->dest->index);
775
              fprintf (f, " " HOST_WIDE_INT_PRINT_DEC " Prob %d\n",
776
                       (HOST_WIDE_INT) e->count, e->probability);
777
            }
778
          }
779
        }
780
    }
781
}
782
 
783
/* Print counts and frequencies for all basic blocks of all methods.  */
784
static void
785
ipcp_profile_bb_print (FILE * f)
786
{
787
  basic_block bb;
788
  struct cgraph_node *node;
789
 
790
  for (node = cgraph_nodes; node; node = node->next)
791
    {
792
      fprintf (f, "method %s: \n", cgraph_node_name (node));
793
      if (DECL_SAVED_TREE (node->decl))
794
        {
795
          bb =
796
            ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
797
          fprintf (f, "ENTRY: Count");
798
          fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
799
                   " Frquency  %d\n", (HOST_WIDE_INT) bb->count,
800
                   bb->frequency);
801
 
802
          FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
803
          {
804
            fprintf (f, "bb[%d]: Count", bb->index);
805
            fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
806
                     " Frequency %d\n", (HOST_WIDE_INT) bb->count,
807
                     bb->frequency);
808
          }
809
          bb =
810
            EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl));
811
          fprintf (f, "EXIT: Count");
812
          fprintf (f, " " HOST_WIDE_INT_PRINT_DEC
813
                   " Frequency %d\n", (HOST_WIDE_INT) bb->count,
814
                   bb->frequency);
815
 
816
        }
817
    }
818
}
819
 
820
/* Print all IPCP data structures to F.  */
821
static void
822
ipcp_structures_print (FILE * f)
823
{
824
  ipcp_method_cval_print (f);
825
  ipcp_method_scale_print (f);
826
  ipa_method_tree_print (f);
827
  ipa_method_modify_print (f);
828
  ipcp_callsite_param_print (f);
829
}
830
 
831
/* Print profile info for all methods.  */
832
static void
833
ipcp_profile_print (FILE * f)
834
{
835
  fprintf (f, "\nNODE COUNTS :\n");
836
  ipcp_profile_mt_count_print (f);
837
  fprintf (f, "\nCS COUNTS stage:\n");
838
  ipcp_profile_cs_count_print (f);
839
  fprintf (f, "\nBB COUNTS and FREQUENCIES :\n");
840
  ipcp_profile_bb_print (f);
841
  fprintf (f, "\nCFG EDGES COUNTS and PROBABILITIES :\n");
842
  ipcp_profile_edge_print (f);
843
}
844
 
845
/* Build and initialize ipa_replace_map struct
846
   according to TYPE. This struct is read by versioning, which
847
   operates according to the flags sent.  PARM_TREE is the
848
   formal's tree found to be constant.  CVALUE represents the constant.  */
849
static struct ipa_replace_map *
850
ipcp_replace_map_create (enum cvalue_type type, tree parm_tree,
851
                         union parameter_info *cvalue)
852
{
853
  struct ipa_replace_map *replace_map;
854
  tree const_val;
855
 
856
  replace_map = xcalloc (1, sizeof (struct ipa_replace_map));
857
  gcc_assert (ipcp_type_is_const (type));
858
  if (type == CONST_VALUE_REF )
859
    {
860
      const_val =
861
        build_const_val (cvalue, type, TREE_TYPE (TREE_TYPE (parm_tree)));
862
      replace_map->old_tree = parm_tree;
863
      replace_map->new_tree = const_val;
864
      replace_map->replace_p = true;
865
      replace_map->ref_p = true;
866
    }
867
  else if (TREE_READONLY (parm_tree) && !TREE_ADDRESSABLE (parm_tree))
868
    {
869
      const_val = build_const_val (cvalue, type, TREE_TYPE (parm_tree));
870
      replace_map->old_tree = parm_tree;
871
      replace_map->new_tree = const_val;
872
      replace_map->replace_p = true;
873
      replace_map->ref_p = false;
874
    }
875
  else
876
    {
877
      replace_map->old_tree = NULL;
878
      replace_map->new_tree = NULL;
879
      replace_map->replace_p = false;
880
      replace_map->ref_p = false;
881
    }
882
 
883
  return replace_map;
884
}
885
 
886
/* Return true if this callsite should be redirected to
887
   the orig callee (instead of the cloned one).  */
888
static bool
889
ipcp_redirect (struct cgraph_edge *cs)
890
{
891
  struct cgraph_node *caller, *callee, *orig_callee;
892
  int i, count;
893
  struct ipa_jump_func *jump_func;
894
  enum jump_func_type type;
895
  enum cvalue_type cval_type;
896
 
897
  caller = cs->caller;
898
  callee = cs->callee;
899
  orig_callee = ipcp_method_orig_node (callee);
900
  count = ipa_method_formal_count (orig_callee);
901
  for (i = 0; i < count; i++)
902
    {
903
      cval_type =
904
        ipcp_cval_get_cvalue_type (ipcp_method_cval (orig_callee, i));
905
      if (ipcp_type_is_const (cval_type))
906
        {
907
          jump_func = ipa_callsite_param (cs, i);
908
          type = get_type (jump_func);
909
          if (type != CONST_IPATYPE
910
              && type != CONST_IPATYPE_REF)
911
            return true;
912
        }
913
    }
914
 
915
  return false;
916
}
917
 
918
/* Fix the callsites and the callgraph after function cloning was done.  */
919
static void
920
ipcp_update_callgraph (void)
921
{
922
  struct cgraph_node *node, *orig_callee;
923
  struct cgraph_edge *cs;
924
 
925
  for (node = cgraph_nodes; node; node = node->next)
926
    {
927
      /* want to fix only original nodes  */
928
      if (ipcp_method_is_cloned (node))
929
        continue;
930
      for (cs = node->callees; cs; cs = cs->next_callee)
931
        if (ipcp_method_is_cloned (cs->callee))
932
          {
933
            /* Callee is a cloned node  */
934
            orig_callee = ipcp_method_orig_node (cs->callee);
935
            if (ipcp_redirect (cs))
936
              {
937
                cgraph_redirect_edge_callee (cs, orig_callee);
938
                TREE_OPERAND (TREE_OPERAND
939
                              (get_call_expr_in (cs->call_stmt), 0), 0) =
940
                  orig_callee->decl;
941
              }
942
          }
943
    }
944
}
945
 
946
/* Update all cfg basic blocks in NODE according to SCALE.  */
947
static void
948
ipcp_update_bb_counts (struct cgraph_node *node, gcov_type scale)
949
{
950
  basic_block bb;
951
 
952
  FOR_ALL_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
953
    bb->count = bb->count * scale / REG_BR_PROB_BASE;
954
}
955
 
956
/* Update all cfg edges in NODE according to SCALE.  */
957
static void
958
ipcp_update_edges_counts (struct cgraph_node *node, gcov_type scale)
959
{
960
  basic_block bb;
961
  edge_iterator ei;
962
  edge e;
963
 
964
  FOR_ALL_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
965
    FOR_EACH_EDGE (e, ei, bb->succs)
966
    e->count = e->count * scale / REG_BR_PROB_BASE;
967
}
968
 
969
/* Update profiling info for versioned methods and the
970
   methods they were versioned from.  */
971
static void
972
ipcp_update_profiling (void)
973
{
974
  struct cgraph_node *node, *orig_node;
975
  gcov_type scale, scale_complement;
976
  struct cgraph_edge *cs;
977
 
978
  for (node = cgraph_nodes; node; node = node->next)
979
    {
980
      if (ipcp_method_is_cloned (node))
981
        {
982
          orig_node = ipcp_method_orig_node (node);
983
          scale = ipcp_method_get_scale (orig_node);
984
          node->count = orig_node->count * scale / REG_BR_PROB_BASE;
985
          scale_complement = REG_BR_PROB_BASE - scale;
986
          orig_node->count =
987
            orig_node->count * scale_complement / REG_BR_PROB_BASE;
988
          for (cs = node->callees; cs; cs = cs->next_callee)
989
            cs->count = cs->count * scale / REG_BR_PROB_BASE;
990
          for (cs = orig_node->callees; cs; cs = cs->next_callee)
991
            cs->count = cs->count * scale_complement / REG_BR_PROB_BASE;
992
          ipcp_update_bb_counts (node, scale);
993
          ipcp_update_bb_counts (orig_node, scale_complement);
994
          ipcp_update_edges_counts (node, scale);
995
          ipcp_update_edges_counts (orig_node, scale_complement);
996
        }
997
    }
998
}
999
 
1000
/* Propagate the constant parameters found by ipcp_iterate_stage()
1001
   to the function's code.  */
1002
static void
1003
ipcp_insert_stage (void)
1004
{
1005
  struct cgraph_node *node, *node1 = NULL;
1006
  int i, const_param;
1007
  union parameter_info *cvalue;
1008
  varray_type redirect_callers, replace_trees;
1009
  struct cgraph_edge *cs;
1010
  int node_callers, count;
1011
  tree parm_tree;
1012
  enum cvalue_type type;
1013
  struct ipa_replace_map *replace_param;
1014
 
1015
  for (node = cgraph_nodes; node; node = node->next)
1016
    {
1017
      /* Propagation of the constant is forbidden in
1018
         certain conditions.  */
1019
      if (ipcp_method_dont_insert_const (node))
1020
        continue;
1021
      const_param = 0;
1022
      count = ipa_method_formal_count (node);
1023
      for (i = 0; i < count; i++)
1024
        {
1025
          type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i));
1026
          if (ipcp_type_is_const (type))
1027
            const_param++;
1028
        }
1029
      if (const_param == 0)
1030
        continue;
1031
      VARRAY_GENERIC_PTR_INIT (replace_trees, const_param, "replace_trees");
1032
      for (i = 0; i < count; i++)
1033
        {
1034
          type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i));
1035
          if (ipcp_type_is_const (type))
1036
            {
1037
              cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
1038
              parm_tree = ipa_method_get_tree (node, i);
1039
              replace_param =
1040
                ipcp_replace_map_create (type, parm_tree, cvalue);
1041
              VARRAY_PUSH_GENERIC_PTR (replace_trees, replace_param);
1042
            }
1043
        }
1044
      /* Compute how many callers node has.  */
1045
      node_callers = 0;
1046
      for (cs = node->callers; cs != NULL; cs = cs->next_caller)
1047
        node_callers++;
1048
      VARRAY_GENERIC_PTR_INIT (redirect_callers, node_callers,
1049
                               "redirect_callers");
1050
      for (cs = node->callers; cs != NULL; cs = cs->next_caller)
1051
        VARRAY_PUSH_GENERIC_PTR (redirect_callers, cs);
1052
      /* Redirecting all the callers of the node to the
1053
         new versioned node.  */
1054
      node1 =
1055
        cgraph_function_versioning (node, redirect_callers, replace_trees);
1056
      VARRAY_CLEAR (redirect_callers);
1057
      VARRAY_CLEAR (replace_trees);
1058
      if (node1 == NULL)
1059
        continue;
1060
      if (dump_file)
1061
        fprintf (dump_file, "versioned function %s\n",
1062
                 cgraph_node_name (node));
1063
      ipcp_cloned_create (node, node1);
1064
      for (i = 0; i < count; i++)
1065
        {
1066
          type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i));
1067
          if (ipcp_type_is_const (type))
1068
            {
1069
              cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
1070
              parm_tree = ipa_method_get_tree (node, i);
1071
              if (type != CONST_VALUE_REF
1072
                  && !TREE_READONLY (parm_tree))
1073
                ipcp_propagate_const (node1, i, cvalue, type);
1074
            }
1075
        }
1076
    }
1077
  ipcp_update_callgraph ();
1078
  ipcp_update_profiling ();
1079
}
1080
 
1081
/* The IPCP driver.  */
1082
void
1083
ipcp_driver (void)
1084
{
1085
  if (dump_file)
1086
    fprintf (dump_file, "\nIPA constant propagation start:\n");
1087
  ipa_nodes_create ();
1088
  ipa_edges_create ();
1089
  /* 1. Call the init stage to initialize
1090
     the ipa_node and ipa_edge structures.  */
1091
  ipcp_init_stage ();
1092
  if (dump_file)
1093
    {
1094
      fprintf (dump_file, "\nIPA structures before propagation:\n");
1095
      ipcp_structures_print (dump_file);
1096
    }
1097
  /* 2. Do the interprocedural propagation.  */
1098
  ipcp_iterate_stage ();
1099
  if (dump_file)
1100
    {
1101
      fprintf (dump_file, "\nIPA structures after propagation:\n");
1102
      ipcp_structures_print (dump_file);
1103
      fprintf (dump_file, "\nProfiling info before insert stage:\n");
1104
      ipcp_profile_print (dump_file);
1105
    }
1106
  /* 3. Insert the constants found to the functions.  */
1107
  ipcp_insert_stage ();
1108
  if (dump_file)
1109
    {
1110
      fprintf (dump_file, "\nProfiling info after insert stage:\n");
1111
      ipcp_profile_print (dump_file);
1112
    }
1113
  /* Free all IPCP structures.  */
1114
  ipa_free ();
1115
  ipa_nodes_free ();
1116
  ipa_edges_free ();
1117
  if (dump_file)
1118
    fprintf (dump_file, "\nIPA constant propagation end\n");
1119
  cgraph_remove_unreachable_nodes (true, NULL);
1120
}
1121
 
1122
/* Gate for IPCP optimization.  */
1123
static bool
1124
cgraph_gate_cp (void)
1125
{
1126
  return flag_ipa_cp;
1127
}
1128
 
1129
struct tree_opt_pass pass_ipa_cp = {
1130
  "cp",                         /* name */
1131
  cgraph_gate_cp,               /* gate */
1132
  ipcp_driver,                  /* execute */
1133
  NULL,                         /* sub */
1134
  NULL,                         /* next */
1135
  0,                             /* static_pass_number */
1136
  TV_IPA_CONSTANT_PROP,         /* tv_id */
1137
  0,                             /* properties_required */
1138
  PROP_trees,                   /* properties_provided */
1139
  0,                             /* properties_destroyed */
1140
  0,                             /* todo_flags_start */
1141
  TODO_dump_cgraph | TODO_dump_func,    /* todo_flags_finish */
1142
 
1143
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.