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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ipa-reference.c] - Blame information for rev 849

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

Line No. Rev Author Line
1 684 jeremybenn
/* Callgraph based analysis of static variables.
2
   Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
   Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify it under
9
the terms of the GNU General Public License as published by the Free
10
Software Foundation; either version 3, or (at your option) any later
11
version.
12
 
13
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14
WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with GCC; see the file COPYING3.  If not see
20
<http://www.gnu.org/licenses/>.  */
21
 
22
/* This file gathers information about how variables whose scope is
23
   confined to the compilation unit are used.
24
 
25
   The transitive call site specific clobber effects are computed
26
   for the variables whose scope is contained within this compilation
27
   unit.
28
 
29
   First each function and static variable initialization is analyzed
30
   to determine which local static variables are either read, written,
31
   or have their address taken.  Any local static that has its address
32
   taken is removed from consideration.  Once the local read and
33
   writes are determined, a transitive closure of this information is
34
   performed over the call graph to determine the worst case set of
35
   side effects of each call.  In later parts of the compiler, these
36
   local and global sets are examined to make the call clobbering less
37
   traumatic, promote some statics to registers, and improve aliasing
38
   information.  */
39
 
40
#include "config.h"
41
#include "system.h"
42
#include "coretypes.h"
43
#include "tm.h"
44
#include "tree.h"
45
#include "tree-flow.h"
46
#include "tree-inline.h"
47
#include "tree-pass.h"
48
#include "langhooks.h"
49
#include "pointer-set.h"
50
#include "splay-tree.h"
51
#include "ggc.h"
52
#include "ipa-utils.h"
53
#include "ipa-reference.h"
54
#include "gimple.h"
55
#include "cgraph.h"
56
#include "output.h"
57
#include "flags.h"
58
#include "timevar.h"
59
#include "diagnostic.h"
60
#include "langhooks.h"
61
#include "data-streamer.h"
62
#include "lto-streamer.h"
63
 
64
static void remove_node_data (struct cgraph_node *node,
65
                              void *data ATTRIBUTE_UNUSED);
66
static void duplicate_node_data (struct cgraph_node *src,
67
                                 struct cgraph_node *dst,
68
                                 void *data ATTRIBUTE_UNUSED);
69
 
70
/* The static variables defined within the compilation unit that are
71
   loaded or stored directly by function that owns this structure.  */
72
 
73
struct ipa_reference_local_vars_info_d
74
{
75
  bitmap statics_read;
76
  bitmap statics_written;
77
};
78
 
79
/* Statics that are read and written by some set of functions. The
80
   local ones are based on the loads and stores local to the function.
81
   The global ones are based on the local info as well as the
82
   transitive closure of the functions that are called. */
83
 
84
struct ipa_reference_global_vars_info_d
85
{
86
  bitmap statics_read;
87
  bitmap statics_written;
88
};
89
 
90
/* Information we save about every function after ipa-reference is completed.  */
91
 
92
struct ipa_reference_optimization_summary_d
93
{
94
  bitmap statics_not_read;
95
  bitmap statics_not_written;
96
};
97
 
98
typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
99
typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
100
typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
101
 
102
struct ipa_reference_vars_info_d
103
{
104
  struct ipa_reference_local_vars_info_d local;
105
  struct ipa_reference_global_vars_info_d global;
106
};
107
 
108
typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
109
 
110
/* This splay tree contains all of the static variables that are
111
   being considered by the compilation level alias analysis.  */
112
static splay_tree reference_vars_to_consider;
113
 
114
/* A bit is set for every module static we are considering.  This is
115
   ored into the local info when asm code is found that clobbers all
116
   memory. */
117
static bitmap all_module_statics;
118
 
119
/* Obstack holding bitmaps of local analysis (live from analysis to
120
   propagation)  */
121
static bitmap_obstack local_info_obstack;
122
/* Obstack holding global analysis live forever.  */
123
static bitmap_obstack optimization_summary_obstack;
124
 
125
/* Holders of ipa cgraph hooks: */
126
static struct cgraph_2node_hook_list *node_duplication_hook_holder;
127
static struct cgraph_node_hook_list *node_removal_hook_holder;
128
 
129
/* Vector where the reference var infos are actually stored. */
130
DEF_VEC_P (ipa_reference_vars_info_t);
131
DEF_VEC_ALLOC_P (ipa_reference_vars_info_t, heap);
132
static VEC (ipa_reference_vars_info_t, heap) *ipa_reference_vars_vector;
133
DEF_VEC_P (ipa_reference_optimization_summary_t);
134
DEF_VEC_ALLOC_P (ipa_reference_optimization_summary_t, heap);
135
static VEC (ipa_reference_optimization_summary_t, heap) *ipa_reference_opt_sum_vector;
136
 
137
/* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
138
static inline ipa_reference_vars_info_t
139
get_reference_vars_info (struct cgraph_node *node)
140
{
141
  if (!ipa_reference_vars_vector
142
      || VEC_length (ipa_reference_vars_info_t,
143
                     ipa_reference_vars_vector) <= (unsigned int) node->uid)
144
    return NULL;
145
  return VEC_index (ipa_reference_vars_info_t, ipa_reference_vars_vector,
146
                    node->uid);
147
}
148
 
149
/* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
150
static inline ipa_reference_optimization_summary_t
151
get_reference_optimization_summary (struct cgraph_node *node)
152
{
153
  if (!ipa_reference_opt_sum_vector
154
      || (VEC_length (ipa_reference_optimization_summary_t,
155
                      ipa_reference_opt_sum_vector)
156
          <= (unsigned int) node->uid))
157
    return NULL;
158
  return VEC_index (ipa_reference_optimization_summary_t, ipa_reference_opt_sum_vector,
159
                    node->uid);
160
}
161
 
162
/* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
163
static inline void
164
set_reference_vars_info (struct cgraph_node *node,
165
                         ipa_reference_vars_info_t info)
166
{
167
  if (!ipa_reference_vars_vector
168
      || VEC_length (ipa_reference_vars_info_t,
169
                     ipa_reference_vars_vector) <= (unsigned int) node->uid)
170
    VEC_safe_grow_cleared (ipa_reference_vars_info_t, heap,
171
                           ipa_reference_vars_vector, node->uid + 1);
172
  VEC_replace (ipa_reference_vars_info_t, ipa_reference_vars_vector,
173
               node->uid, info);
174
}
175
 
176
/* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
177
static inline void
178
set_reference_optimization_summary (struct cgraph_node *node,
179
                                    ipa_reference_optimization_summary_t info)
180
{
181
  if (!ipa_reference_opt_sum_vector
182
      || (VEC_length (ipa_reference_optimization_summary_t,
183
                      ipa_reference_opt_sum_vector)
184
          <= (unsigned int) node->uid))
185
    VEC_safe_grow_cleared (ipa_reference_optimization_summary_t,
186
                           heap, ipa_reference_opt_sum_vector, node->uid + 1);
187
  VEC_replace (ipa_reference_optimization_summary_t,
188
               ipa_reference_opt_sum_vector, node->uid, info);
189
}
190
 
191
/* Return a bitmap indexed by_DECL_UID uid for the static variables
192
   that are not read during the execution of the function FN.  Returns
193
   NULL if no data is available.  */
194
 
195
bitmap
196
ipa_reference_get_not_read_global (struct cgraph_node *fn)
197
{
198
  ipa_reference_optimization_summary_t info;
199
 
200
  info = get_reference_optimization_summary (cgraph_function_node (fn, NULL));
201
  if (info)
202
    return info->statics_not_read;
203
  else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
204
    return all_module_statics;
205
  else
206
    return NULL;
207
}
208
 
209
/* Return a bitmap indexed by DECL_UID uid for the static variables
210
   that are not written during the execution of the function FN.  Note
211
   that variables written may or may not be read during the function
212
   call.  Returns NULL if no data is available.  */
213
 
214
bitmap
215
ipa_reference_get_not_written_global (struct cgraph_node *fn)
216
{
217
  ipa_reference_optimization_summary_t info;
218
 
219
  info = get_reference_optimization_summary (fn);
220
  if (info)
221
    return info->statics_not_written;
222
  else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
223
    return all_module_statics;
224
  else
225
    return NULL;
226
}
227
 
228
 
229
 
230
/* Add VAR to all_module_statics and the two
231
   reference_vars_to_consider* sets.  */
232
 
233
static inline void
234
add_static_var (tree var)
235
{
236
  int uid = DECL_UID (var);
237
  gcc_assert (TREE_CODE (var) == VAR_DECL);
238
  if (dump_file)
239
    splay_tree_insert (reference_vars_to_consider,
240
                       uid, (splay_tree_value)var);
241
  bitmap_set_bit (all_module_statics, uid);
242
}
243
 
244
/* Return true if the variable T is the right kind of static variable to
245
   perform compilation unit scope escape analysis.  */
246
 
247
static inline bool
248
is_proper_for_analysis (tree t)
249
{
250
  /* We handle only variables whose address is never taken.  */
251
  if (TREE_ADDRESSABLE (t))
252
    return false;
253
 
254
  /* If the variable has the "used" attribute, treat it as if it had a
255
     been touched by the devil.  */
256
  if (DECL_PRESERVE_P (t))
257
    return false;
258
 
259
  /* Do not want to do anything with volatile except mark any
260
     function that uses one to be not const or pure.  */
261
  if (TREE_THIS_VOLATILE (t))
262
    return false;
263
 
264
  /* We do not need to analyze readonly vars, we already know they do not
265
     alias.  */
266
  if (TREE_READONLY (t))
267
    return false;
268
 
269
  /* We cannot touch decls where the type needs constructing.  */
270
  if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t)))
271
    return false;
272
 
273
  /* This is a variable we care about.  Check if we have seen it
274
     before, and if not add it the set of variables we care about.  */
275
  if (all_module_statics
276
      && !bitmap_bit_p (all_module_statics, DECL_UID (t)))
277
    add_static_var (t);
278
 
279
  return true;
280
}
281
 
282
/* Lookup the tree node for the static variable that has UID and
283
   convert the name to a string for debugging.  */
284
 
285
static const char *
286
get_static_name (int index)
287
{
288
  splay_tree_node stn =
289
    splay_tree_lookup (reference_vars_to_consider, index);
290
  if (stn)
291
    return lang_hooks.decl_printable_name ((tree)(stn->value), 2);
292
  return NULL;
293
}
294
 
295
/* Or in all of the bits from every callee of X into X_GLOBAL, the caller's cycle,
296
   bit vector.  There are several cases to check to avoid the sparse
297
   bitmap oring.  */
298
 
299
static void
300
propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
301
{
302
  struct cgraph_edge *e;
303
  for (e = x->callees; e; e = e->next_callee)
304
    {
305
      enum availability avail;
306
      struct cgraph_node *y = cgraph_function_node (e->callee, &avail);
307
 
308
      if (!y)
309
        continue;
310
      /* Only look into nodes we can propagate something.  */
311
      if (avail > AVAIL_OVERWRITABLE
312
          || (avail == AVAIL_OVERWRITABLE
313
              && (flags_from_decl_or_type (y->decl) & ECF_LEAF)))
314
        {
315
          int flags = flags_from_decl_or_type (y->decl);
316
          if (get_reference_vars_info (y))
317
            {
318
              ipa_reference_vars_info_t y_info
319
                = get_reference_vars_info (y);
320
              ipa_reference_global_vars_info_t y_global = &y_info->global;
321
 
322
              /* Calls in current cycle do not have global computed yet.  */
323
              if (!y_global->statics_read)
324
                continue;
325
 
326
              /* If function is declared const, it reads no memory even if it
327
                 seems so to local analysis.  */
328
              if (flags & ECF_CONST)
329
                continue;
330
 
331
              if (x_global->statics_read
332
                  != all_module_statics)
333
                {
334
                  if (y_global->statics_read
335
                      == all_module_statics)
336
                    {
337
                      BITMAP_FREE (x_global->statics_read);
338
                      x_global->statics_read
339
                        = all_module_statics;
340
                    }
341
                  /* Skip bitmaps that are pointer equal to node's bitmap
342
                     (no reason to spin within the cycle).  */
343
                  else if (x_global->statics_read
344
                           != y_global->statics_read)
345
                    bitmap_ior_into (x_global->statics_read,
346
                                     y_global->statics_read);
347
                }
348
 
349
              /* If function is declared pure, it has no stores even if it
350
                 seems so to local analysis; If we can not return from here,
351
                 we can safely ignore the call.  */
352
              if ((flags & ECF_PURE)
353
                  || cgraph_edge_cannot_lead_to_return (e))
354
                continue;
355
 
356
              if (x_global->statics_written
357
                  != all_module_statics)
358
                {
359
                  if (y_global->statics_written
360
                      == all_module_statics)
361
                    {
362
                      BITMAP_FREE (x_global->statics_written);
363
                      x_global->statics_written
364
                        = all_module_statics;
365
                    }
366
                  /* Skip bitmaps that are pointer equal to node's bitmap
367
                     (no reason to spin within the cycle).  */
368
                  else if (x_global->statics_written
369
                           != y_global->statics_written)
370
                    bitmap_ior_into (x_global->statics_written,
371
                                     y_global->statics_written);
372
                }
373
            }
374
          else
375
            gcc_unreachable ();
376
        }
377
    }
378
}
379
 
380
/* The init routine for analyzing global static variable usage.  See
381
   comments at top for description.  */
382
static void
383
ipa_init (void)
384
{
385
  static bool init_p = false;
386
 
387
  if (init_p)
388
    return;
389
 
390
  init_p = true;
391
 
392
  if (dump_file)
393
    reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
394
 
395
  bitmap_obstack_initialize (&local_info_obstack);
396
  bitmap_obstack_initialize (&optimization_summary_obstack);
397
  all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
398
 
399
  node_removal_hook_holder =
400
      cgraph_add_node_removal_hook (&remove_node_data, NULL);
401
  node_duplication_hook_holder =
402
      cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
403
}
404
 
405
 
406
/* Set up the persistent info for FN.  */
407
 
408
static ipa_reference_local_vars_info_t
409
init_function_info (struct cgraph_node *fn)
410
{
411
  ipa_reference_vars_info_t info
412
    = XCNEW (struct ipa_reference_vars_info_d);
413
 
414
  /* Add the info to the tree's annotation.  */
415
  set_reference_vars_info (fn, info);
416
 
417
  info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
418
  info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
419
 
420
  return &info->local;
421
}
422
 
423
 
424
/* This is the main routine for finding the reference patterns for
425
   global variables within a function FN.  */
426
 
427
static void
428
analyze_function (struct cgraph_node *fn)
429
{
430
  ipa_reference_local_vars_info_t local;
431
  struct ipa_ref *ref;
432
  int i;
433
  tree var;
434
 
435
  local = init_function_info (fn);
436
  for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++)
437
    {
438
      if (ref->refered_type != IPA_REF_VARPOOL)
439
        continue;
440
      var = ipa_ref_varpool_node (ref)->decl;
441
      if (ipa_ref_varpool_node (ref)->externally_visible
442
          || !ipa_ref_varpool_node (ref)->analyzed
443
          || !is_proper_for_analysis (var))
444
        continue;
445
      switch (ref->use)
446
        {
447
        case IPA_REF_LOAD:
448
          bitmap_set_bit (local->statics_read, DECL_UID (var));
449
          break;
450
        case IPA_REF_STORE:
451
          if (ipa_ref_cannot_lead_to_return (ref))
452
            break;
453
          bitmap_set_bit (local->statics_written, DECL_UID (var));
454
          break;
455
        case IPA_REF_ADDR:
456
          gcc_unreachable ();
457
          break;
458
        }
459
    }
460
 
461
  if (cgraph_node_cannot_return (fn))
462
    bitmap_clear (local->statics_written);
463
}
464
 
465
static bitmap
466
copy_global_bitmap (bitmap src)
467
{
468
  bitmap dst;
469
  if (!src)
470
    return NULL;
471
  if (src == all_module_statics)
472
    return all_module_statics;
473
  dst = BITMAP_ALLOC (&optimization_summary_obstack);
474
  bitmap_copy (dst, src);
475
  return dst;
476
}
477
 
478
 
479
/* Called when new clone is inserted to callgraph late.  */
480
 
481
static void
482
duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
483
                     void *data ATTRIBUTE_UNUSED)
484
{
485
  ipa_reference_optimization_summary_t ginfo;
486
  ipa_reference_optimization_summary_t dst_ginfo;
487
 
488
  ginfo = get_reference_optimization_summary (src);
489
  if (!ginfo)
490
    return;
491
  dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
492
  set_reference_optimization_summary (dst, dst_ginfo);
493
  dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read);
494
  dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written);
495
}
496
 
497
/* Called when node is removed.  */
498
 
499
static void
500
remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
501
{
502
  ipa_reference_optimization_summary_t ginfo;
503
  ginfo = get_reference_optimization_summary (node);
504
  if (ginfo)
505
    {
506
      if (ginfo->statics_not_read
507
          && ginfo->statics_not_read != all_module_statics)
508
        BITMAP_FREE (ginfo->statics_not_read);
509
 
510
      if (ginfo->statics_not_written
511
          && ginfo->statics_not_written != all_module_statics)
512
        BITMAP_FREE (ginfo->statics_not_written);
513
      free (ginfo);
514
      set_reference_optimization_summary (node, NULL);
515
    }
516
}
517
 
518
/* Analyze each function in the cgraph to see which global or statics
519
   are read or written.  */
520
 
521
static void
522
generate_summary (void)
523
{
524
  struct cgraph_node *node;
525
  unsigned int index;
526
  bitmap_iterator bi;
527
  bitmap bm_temp;
528
 
529
  ipa_init ();
530
  bm_temp = BITMAP_ALLOC (&local_info_obstack);
531
 
532
  /* Process all of the functions next.  */
533
  for (node = cgraph_nodes; node; node = node->next)
534
    if (node->analyzed)
535
      analyze_function (node);
536
 
537
  if (dump_file)
538
    EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
539
      {
540
        fprintf (dump_file, "\nPromotable global:%s",
541
                 get_static_name (index));
542
      }
543
 
544
  BITMAP_FREE(bm_temp);
545
 
546
  if (dump_file)
547
    for (node = cgraph_nodes; node; node = node->next)
548
      if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
549
        {
550
          ipa_reference_local_vars_info_t l;
551
          unsigned int index;
552
          bitmap_iterator bi;
553
 
554
          l = &get_reference_vars_info (node)->local;
555
          fprintf (dump_file,
556
                   "\nFunction name:%s/%i:",
557
                   cgraph_node_name (node), node->uid);
558
          fprintf (dump_file, "\n  locals read: ");
559
          if (l->statics_read)
560
            EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
561
                                      0, index, bi)
562
              {
563
                fprintf (dump_file, "%s ",
564
                         get_static_name (index));
565
              }
566
          fprintf (dump_file, "\n  locals written: ");
567
          if (l->statics_written)
568
            EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
569
                                      0, index, bi)
570
              {
571
                fprintf(dump_file, "%s ",
572
                        get_static_name (index));
573
              }
574
        }
575
}
576
 
577
/* Set READ_ALL/WRITE_ALL based on decl flags of NODE.  */
578
 
579
static void
580
read_write_all_from_decl (struct cgraph_node *node, bool * read_all,
581
                          bool * write_all)
582
{
583
  tree decl = node->decl;
584
  int flags = flags_from_decl_or_type (decl);
585
  if ((flags & ECF_LEAF)
586
      && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
587
    ;
588
  else if (flags & ECF_CONST)
589
    ;
590
  else if ((flags & ECF_PURE)
591
           || cgraph_node_cannot_return (node))
592
    {
593
      *read_all = true;
594
      if (dump_file && (dump_flags & TDF_DETAILS))
595
         fprintf (dump_file, "   %s/%i -> read all\n",
596
                  cgraph_node_name (node), node->uid);
597
    }
598
  else
599
    {
600
       /* TODO: To be able to produce sane results, we should also handle
601
          common builtins, in particular throw.  */
602
      *read_all = true;
603
      *write_all = true;
604
      if (dump_file && (dump_flags & TDF_DETAILS))
605
         fprintf (dump_file, "   %s/%i -> read all, write all\n",
606
                  cgraph_node_name (node), node->uid);
607
    }
608
}
609
 
610
/* Produce the global information by preforming a transitive closure
611
   on the local information that was produced by ipa_analyze_function */
612
 
613
static unsigned int
614
propagate (void)
615
{
616
  struct cgraph_node *node;
617
  struct cgraph_node *w;
618
  struct cgraph_node **order =
619
    XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
620
  int order_pos;
621
  int i;
622
 
623
  if (dump_file)
624
    dump_cgraph (dump_file);
625
 
626
  ipa_discover_readonly_nonaddressable_vars ();
627
  generate_summary ();
628
 
629
  /* Propagate the local information thru the call graph to produce
630
     the global information.  All the nodes within a cycle will have
631
     the same info so we collapse cycles first.  Then we can do the
632
     propagation in one pass from the leaves to the roots.  */
633
  order_pos = ipa_reduced_postorder (order, true, true, NULL);
634
  if (dump_file)
635
    ipa_print_order (dump_file, "reduced", order, order_pos);
636
 
637
  for (i = 0; i < order_pos; i++ )
638
    {
639
      ipa_reference_vars_info_t node_info;
640
      ipa_reference_global_vars_info_t node_g;
641
      ipa_reference_local_vars_info_t node_l;
642
      struct cgraph_edge *e, *ie;
643
 
644
      bool read_all;
645
      bool write_all;
646
      struct ipa_dfs_info * w_info;
647
 
648
      node = order[i];
649
      if (node->alias)
650
        continue;
651
      node_info = get_reference_vars_info (node);
652
      gcc_assert (node_info);
653
 
654
 
655
      if (dump_file && (dump_flags & TDF_DETAILS))
656
        fprintf (dump_file, "Starting cycle with %s/%i\n",
657
                  cgraph_node_name (node), node->uid);
658
 
659
      node_l = &node_info->local;
660
      node_g = &node_info->global;
661
 
662
      read_all = false;
663
      write_all = false;
664
 
665
      /* When function is overwritable, we can not assume anything.  */
666
      if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
667
        read_write_all_from_decl (node, &read_all, &write_all);
668
 
669
      for (e = node->callees; e; e = e->next_callee)
670
        {
671
          enum availability avail;
672
          struct cgraph_node *callee = cgraph_function_node (e->callee, &avail);
673
          if (!callee || avail <= AVAIL_OVERWRITABLE)
674
            read_write_all_from_decl (callee, &read_all, &write_all);
675
        }
676
 
677
      for (ie = node->indirect_calls; ie; ie = ie->next_callee)
678
        if (!(ie->indirect_info->ecf_flags & ECF_CONST))
679
          {
680
            read_all = true;
681
            if (dump_file && (dump_flags & TDF_DETAILS))
682
               fprintf (dump_file, "   indirect call -> read all\n");
683
            if (!cgraph_edge_cannot_lead_to_return (ie)
684
                && !(ie->indirect_info->ecf_flags & ECF_PURE))
685
              {
686
                if (dump_file && (dump_flags & TDF_DETAILS))
687
                   fprintf (dump_file, "   indirect call -> write all\n");
688
                write_all = true;
689
              }
690
          }
691
 
692
 
693
      /* If any node in a cycle is read_all or write_all
694
         they all are. */
695
      w_info = (struct ipa_dfs_info *) node->aux;
696
      w = w_info->next_cycle;
697
      while (w && (!read_all || !write_all))
698
        {
699
          if (dump_file && (dump_flags & TDF_DETAILS))
700
            fprintf (dump_file, "  Visiting %s/%i\n",
701
                      cgraph_node_name (w), w->uid);
702
          /* When function is overwritable, we can not assume anything.  */
703
          if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE)
704
            read_write_all_from_decl (w, &read_all, &write_all);
705
 
706
          for (e = w->callees; e; e = e->next_callee)
707
            {
708
              enum availability avail;
709
              struct cgraph_node *callee = cgraph_function_node (e->callee, &avail);
710
 
711
              if (avail <= AVAIL_OVERWRITABLE)
712
                read_write_all_from_decl (callee, &read_all, &write_all);
713
            }
714
 
715
          for (ie = w->indirect_calls; ie; ie = ie->next_callee)
716
            if (!(ie->indirect_info->ecf_flags & ECF_CONST))
717
              {
718
                read_all = true;
719
                if (dump_file && (dump_flags & TDF_DETAILS))
720
                   fprintf (dump_file, "   indirect call -> read all\n");
721
                if (!cgraph_edge_cannot_lead_to_return (ie)
722
                    && !(ie->indirect_info->ecf_flags & ECF_PURE))
723
                  {
724
                    write_all = true;
725
                    if (dump_file && (dump_flags & TDF_DETAILS))
726
                       fprintf (dump_file, "   indirect call -> write all\n");
727
                  }
728
              }
729
 
730
          w_info = (struct ipa_dfs_info *) w->aux;
731
          w = w_info->next_cycle;
732
        }
733
 
734
 
735
      /* Initialized the bitmaps for the reduced nodes */
736
      if (read_all)
737
        node_g->statics_read = all_module_statics;
738
      else
739
        {
740
          node_g->statics_read = BITMAP_ALLOC (&local_info_obstack);
741
          bitmap_copy (node_g->statics_read,
742
                       node_l->statics_read);
743
        }
744
      if (write_all)
745
        node_g->statics_written = all_module_statics;
746
      else
747
        {
748
          node_g->statics_written = BITMAP_ALLOC (&local_info_obstack);
749
          bitmap_copy (node_g->statics_written,
750
                       node_l->statics_written);
751
        }
752
 
753
      propagate_bits (node_g, node);
754
      w_info = (struct ipa_dfs_info *) node->aux;
755
      w = w_info->next_cycle;
756
      while (w && (!read_all || !write_all))
757
        {
758
          ipa_reference_vars_info_t w_ri =
759
            get_reference_vars_info (w);
760
          ipa_reference_local_vars_info_t w_l = &w_ri->local;
761
          int flags = flags_from_decl_or_type (w->decl);
762
 
763
          /* These global bitmaps are initialized from the local info
764
             of all of the nodes in the region.  However there is no
765
             need to do any work if the bitmaps were set to
766
             all_module_statics.  */
767
          if (!read_all && !(flags & ECF_CONST))
768
            bitmap_ior_into (node_g->statics_read,
769
                             w_l->statics_read);
770
          if (!write_all
771
              && !(flags & ECF_PURE)
772
              && !cgraph_node_cannot_return (w))
773
            bitmap_ior_into (node_g->statics_written,
774
                             w_l->statics_written);
775
          propagate_bits (node_g, w);
776
          w_info = (struct ipa_dfs_info *) w->aux;
777
          w = w_info->next_cycle;
778
        }
779
 
780
      /* All nodes within a cycle have the same global info bitmaps.  */
781
      node_info->global = *node_g;
782
      w_info = (struct ipa_dfs_info *) node->aux;
783
      w = w_info->next_cycle;
784
      while (w)
785
        {
786
          ipa_reference_vars_info_t w_ri =
787
            get_reference_vars_info (w);
788
 
789
          w_ri->global = *node_g;
790
 
791
          w_info = (struct ipa_dfs_info *) w->aux;
792
          w = w_info->next_cycle;
793
        }
794
    }
795
 
796
  if (dump_file)
797
    {
798
      for (i = 0; i < order_pos; i++ )
799
        {
800
          ipa_reference_vars_info_t node_info;
801
          ipa_reference_global_vars_info_t node_g;
802
          ipa_reference_local_vars_info_t node_l;
803
          unsigned int index;
804
          bitmap_iterator bi;
805
          struct ipa_dfs_info * w_info;
806
 
807
          node = order[i];
808
          if (node->alias)
809
            continue;
810
          node_info = get_reference_vars_info (node);
811
          node_g = &node_info->global;
812
          node_l = &node_info->local;
813
          fprintf (dump_file,
814
                   "\nFunction name:%s/%i:",
815
                   cgraph_node_name (node), node->uid);
816
          fprintf (dump_file, "\n  locals read: ");
817
          if (node_l->statics_read)
818
            EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read,
819
                                      0, index, bi)
820
              {
821
                fprintf (dump_file, "%s ",
822
                         get_static_name (index));
823
              }
824
          fprintf (dump_file, "\n  locals written: ");
825
          if (node_l->statics_written)
826
            EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written,
827
                                      0, index, bi)
828
              {
829
                fprintf(dump_file, "%s ",
830
                        get_static_name (index));
831
              }
832
 
833
          w_info = (struct ipa_dfs_info *) node->aux;
834
          w = w_info->next_cycle;
835
          while (w)
836
            {
837
              ipa_reference_vars_info_t w_ri =
838
                get_reference_vars_info (w);
839
              ipa_reference_local_vars_info_t w_l = &w_ri->local;
840
              fprintf (dump_file, "\n  next cycle: %s/%i ",
841
                       cgraph_node_name (w), w->uid);
842
              fprintf (dump_file, "\n    locals read: ");
843
              if (w_l->statics_read)
844
                EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read,
845
                                          0, index, bi)
846
                  {
847
                    fprintf (dump_file, "%s ",
848
                             get_static_name (index));
849
                  }
850
 
851
              fprintf (dump_file, "\n    locals written: ");
852
              if (w_l->statics_written)
853
                EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written,
854
                                          0, index, bi)
855
                  {
856
                    fprintf (dump_file, "%s ",
857
                             get_static_name (index));
858
                  }
859
 
860
              w_info = (struct ipa_dfs_info *) w->aux;
861
              w = w_info->next_cycle;
862
            }
863
          fprintf (dump_file, "\n  globals read: ");
864
          if (node_g->statics_read == all_module_statics)
865
            fprintf (dump_file, "ALL");
866
          else
867
            EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read,
868
                                      0, index, bi)
869
              {
870
                fprintf (dump_file, "%s ",
871
                         get_static_name (index));
872
              }
873
          fprintf (dump_file, "\n  globals written: ");
874
          if (node_g->statics_written == all_module_statics)
875
            fprintf (dump_file, "ALL");
876
          else
877
            EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written,
878
                                      0, index, bi)
879
              {
880
                fprintf (dump_file, "%s ",
881
                         get_static_name (index));
882
              }
883
        }
884
    }
885
 
886
  /* Cleanup. */
887
  for (node = cgraph_nodes; node; node = node->next)
888
    {
889
      ipa_reference_vars_info_t node_info;
890
      ipa_reference_global_vars_info_t node_g;
891
      ipa_reference_optimization_summary_t opt;
892
 
893
      if (!node->analyzed || node->alias)
894
        continue;
895
 
896
      node_info = get_reference_vars_info (node);
897
      if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
898
          || (flags_from_decl_or_type (node->decl) & ECF_LEAF))
899
        {
900
          node_g = &node_info->global;
901
 
902
          opt = XCNEW (struct ipa_reference_optimization_summary_d);
903
          set_reference_optimization_summary (node, opt);
904
 
905
          /* Create the complimentary sets.  */
906
 
907
          if (bitmap_empty_p (node_g->statics_read))
908
            opt->statics_not_read = all_module_statics;
909
          else
910
            {
911
              opt->statics_not_read
912
                 = BITMAP_ALLOC (&optimization_summary_obstack);
913
              if (node_g->statics_read != all_module_statics)
914
                bitmap_and_compl (opt->statics_not_read,
915
                                  all_module_statics,
916
                                  node_g->statics_read);
917
            }
918
 
919
          if (bitmap_empty_p (node_g->statics_written))
920
            opt->statics_not_written = all_module_statics;
921
          else
922
            {
923
              opt->statics_not_written
924
                = BITMAP_ALLOC (&optimization_summary_obstack);
925
              if (node_g->statics_written != all_module_statics)
926
                bitmap_and_compl (opt->statics_not_written,
927
                                  all_module_statics,
928
                                  node_g->statics_written);
929
            }
930
        }
931
      free (node_info);
932
   }
933
 
934
  ipa_free_postorder_info ();
935
  free (order);
936
 
937
  bitmap_obstack_release (&local_info_obstack);
938
  VEC_free (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector);
939
  ipa_reference_vars_vector = NULL;
940
  if (dump_file)
941
    splay_tree_delete (reference_vars_to_consider);
942
  reference_vars_to_consider = NULL;
943
  return 0;
944
}
945
 
946
/* Return true if we need to write summary of NODE. */
947
 
948
static bool
949
write_node_summary_p (struct cgraph_node *node,
950
                      cgraph_node_set set,
951
                      varpool_node_set vset,
952
                      bitmap ltrans_statics)
953
{
954
  ipa_reference_optimization_summary_t info;
955
 
956
  /* See if we have (non-empty) info.  */
957
  if (!node->analyzed || node->global.inlined_to)
958
    return false;
959
  info = get_reference_optimization_summary (node);
960
  if (!info || (bitmap_empty_p (info->statics_not_read)
961
                && bitmap_empty_p (info->statics_not_written)))
962
    return false;
963
 
964
  /* See if we want to encode it.
965
     Encode also referenced functions since constant folding might turn it into
966
     a direct call.
967
 
968
     In future we might also want to include summaries of functions references
969
     by initializers of constant variables references in current unit.  */
970
  if (!reachable_from_this_partition_p (node, set)
971
      && !referenced_from_this_partition_p (&node->ref_list, set, vset))
972
    return false;
973
 
974
  /* See if the info has non-empty intersections with vars we want to encode.  */
975
  if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
976
      && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
977
    return false;
978
  return true;
979
}
980
 
981
/* Stream out BITS&LTRANS_STATICS as list of decls to OB.
982
   LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
983
   or -1.  When it is positive, just output -1 when
984
   BITS&LTRANS_STATICS == BITS&LTRANS_STATICS.  */
985
 
986
static void
987
stream_out_bitmap (struct lto_simple_output_block *ob,
988
                   bitmap bits, bitmap ltrans_statics,
989
                   int ltrans_statics_bitcount)
990
{
991
  int count = 0;
992
  unsigned int index;
993
  bitmap_iterator bi;
994
  if (bits == all_module_statics)
995
    {
996
      streamer_write_hwi_stream (ob->main_stream, -1);
997
      return;
998
    }
999
  EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
1000
    count ++;
1001
  if (count == ltrans_statics_bitcount)
1002
    {
1003
      streamer_write_hwi_stream (ob->main_stream, -1);
1004
      return;
1005
    }
1006
  streamer_write_hwi_stream (ob->main_stream, count);
1007
  if (!count)
1008
    return;
1009
  EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
1010
    {
1011
      tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
1012
      lto_output_var_decl_index(ob->decl_state, ob->main_stream, decl);
1013
    }
1014
}
1015
 
1016
/* Serialize the ipa info for lto.  */
1017
 
1018
static void
1019
ipa_reference_write_optimization_summary (cgraph_node_set set,
1020
                                          varpool_node_set vset)
1021
{
1022
  struct cgraph_node *node;
1023
  struct lto_simple_output_block *ob
1024
    = lto_create_simple_output_block (LTO_section_ipa_reference);
1025
  unsigned int count = 0;
1026
  int ltrans_statics_bitcount = 0;
1027
  lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
1028
  lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
1029
  bitmap ltrans_statics = BITMAP_ALLOC (NULL);
1030
  int i;
1031
 
1032
  reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
1033
 
1034
  /* See what variables we are interested in.  */
1035
  for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++)
1036
    {
1037
      struct varpool_node *vnode = lto_varpool_encoder_deref (varpool_encoder, i);
1038
      if (!vnode->externally_visible
1039
          && vnode->analyzed
1040
          && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl))
1041
          && referenced_from_this_partition_p (&vnode->ref_list, set, vset))
1042
        {
1043
          tree decl = vnode->decl;
1044
          bitmap_set_bit (ltrans_statics, DECL_UID (decl));
1045
          splay_tree_insert (reference_vars_to_consider,
1046
                             DECL_UID (decl), (splay_tree_value)decl);
1047
          ltrans_statics_bitcount ++;
1048
        }
1049
    }
1050
 
1051
 
1052
  if (ltrans_statics_bitcount)
1053
    for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
1054
      if (write_node_summary_p (lto_cgraph_encoder_deref (encoder, i),
1055
                                set, vset, ltrans_statics))
1056
          count++;
1057
 
1058
  streamer_write_uhwi_stream (ob->main_stream, count);
1059
  if (count)
1060
    stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1061
                       -1);
1062
 
1063
  /* Process all of the functions.  */
1064
  if (ltrans_statics_bitcount)
1065
    for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
1066
      {
1067
        node = lto_cgraph_encoder_deref (encoder, i);
1068
        if (write_node_summary_p (node, set, vset, ltrans_statics))
1069
          {
1070
            ipa_reference_optimization_summary_t info;
1071
            int node_ref;
1072
 
1073
            info = get_reference_optimization_summary (node);
1074
            node_ref = lto_cgraph_encoder_encode (encoder, node);
1075
            streamer_write_uhwi_stream (ob->main_stream, node_ref);
1076
 
1077
            stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1078
                               ltrans_statics_bitcount);
1079
            stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1080
                               ltrans_statics_bitcount);
1081
          }
1082
      }
1083
  BITMAP_FREE (ltrans_statics);
1084
  lto_destroy_simple_output_block (ob);
1085
  splay_tree_delete (reference_vars_to_consider);
1086
}
1087
 
1088
/* Deserialize the ipa info for lto.  */
1089
 
1090
static void
1091
ipa_reference_read_optimization_summary (void)
1092
{
1093
  struct lto_file_decl_data ** file_data_vec
1094
    = lto_get_file_decl_data ();
1095
  struct lto_file_decl_data * file_data;
1096
  unsigned int j = 0;
1097
  bitmap_obstack_initialize (&optimization_summary_obstack);
1098
 
1099
  node_removal_hook_holder =
1100
      cgraph_add_node_removal_hook (&remove_node_data, NULL);
1101
  node_duplication_hook_holder =
1102
      cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
1103
  all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1104
 
1105
  while ((file_data = file_data_vec[j++]))
1106
    {
1107
      const char *data;
1108
      size_t len;
1109
      struct lto_input_block *ib
1110
        = lto_create_simple_input_block (file_data,
1111
                                         LTO_section_ipa_reference,
1112
                                         &data, &len);
1113
      if (ib)
1114
        {
1115
          unsigned int i;
1116
          unsigned int f_count = streamer_read_uhwi (ib);
1117
          int b_count;
1118
          if (!f_count)
1119
            continue;
1120
          b_count = streamer_read_hwi (ib);
1121
          if (dump_file)
1122
            fprintf (dump_file, "all module statics:");
1123
          for (i = 0; i < (unsigned int)b_count; i++)
1124
            {
1125
              unsigned int var_index = streamer_read_uhwi (ib);
1126
              tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1127
                                                             var_index);
1128
              bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1129
              if (dump_file)
1130
                fprintf (dump_file, " %s",
1131
                         lang_hooks.decl_printable_name (v_decl, 2));
1132
            }
1133
 
1134
          for (i = 0; i < f_count; i++)
1135
            {
1136
              unsigned int j, index;
1137
              struct cgraph_node *node;
1138
              ipa_reference_optimization_summary_t info;
1139
              int v_count;
1140
              lto_cgraph_encoder_t encoder;
1141
 
1142
              index = streamer_read_uhwi (ib);
1143
              encoder = file_data->cgraph_node_encoder;
1144
              node = lto_cgraph_encoder_deref (encoder, index);
1145
              info = XCNEW (struct ipa_reference_optimization_summary_d);
1146
              set_reference_optimization_summary (node, info);
1147
              info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1148
              info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1149
              if (dump_file)
1150
                fprintf (dump_file,
1151
                         "\nFunction name:%s/%i:\n  static not read:",
1152
                         cgraph_node_name (node), node->uid);
1153
 
1154
              /* Set the statics not read.  */
1155
              v_count = streamer_read_hwi (ib);
1156
              if (v_count == -1)
1157
                {
1158
                  info->statics_not_read = all_module_statics;
1159
                  if (dump_file)
1160
                    fprintf (dump_file, " all module statics");
1161
                }
1162
              else
1163
                for (j = 0; j < (unsigned int)v_count; j++)
1164
                  {
1165
                    unsigned int var_index = streamer_read_uhwi (ib);
1166
                    tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1167
                                                                   var_index);
1168
                    bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
1169
                    if (dump_file)
1170
                      fprintf (dump_file, " %s",
1171
                               lang_hooks.decl_printable_name (v_decl, 2));
1172
                  }
1173
 
1174
              if (dump_file)
1175
                fprintf (dump_file,
1176
                         "\n  static not written:");
1177
              /* Set the statics not written.  */
1178
              v_count = streamer_read_hwi (ib);
1179
              if (v_count == -1)
1180
                {
1181
                  info->statics_not_written = all_module_statics;
1182
                  if (dump_file)
1183
                    fprintf (dump_file, " all module statics");
1184
                }
1185
              else
1186
                for (j = 0; j < (unsigned int)v_count; j++)
1187
                  {
1188
                    unsigned int var_index = streamer_read_uhwi (ib);
1189
                    tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1190
                                                                   var_index);
1191
                    bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));
1192
                    if (dump_file)
1193
                      fprintf (dump_file, " %s",
1194
                               lang_hooks.decl_printable_name (v_decl, 2));
1195
                  }
1196
              if (dump_file)
1197
                fprintf (dump_file, "\n");
1198
            }
1199
 
1200
          lto_destroy_simple_input_block (file_data,
1201
                                          LTO_section_ipa_reference,
1202
                                          ib, data, len);
1203
        }
1204
      else
1205
        /* Fatal error here.  We do not want to support compiling ltrans units with
1206
           different version of compiler or different flags than the WPA unit, so
1207
           this should never happen.  */
1208
        fatal_error ("ipa reference summary is missing in ltrans unit");
1209
    }
1210
}
1211
 
1212
static bool
1213
gate_reference (void)
1214
{
1215
  return (flag_ipa_reference
1216
          /* Don't bother doing anything if the program has errors.  */
1217
          && !seen_error ());
1218
}
1219
 
1220
struct ipa_opt_pass_d pass_ipa_reference =
1221
{
1222
 {
1223
  IPA_PASS,
1224
  "static-var",                         /* name */
1225
  gate_reference,                       /* gate */
1226
  propagate,                            /* execute */
1227
  NULL,                                 /* sub */
1228
  NULL,                                 /* next */
1229
  0,                                     /* static_pass_number */
1230
  TV_IPA_REFERENCE,                     /* tv_id */
1231
  0,                                     /* properties_required */
1232
  0,                                     /* properties_provided */
1233
  0,                                     /* properties_destroyed */
1234
  0,                                     /* todo_flags_start */
1235
 
1236
 },
1237
 NULL,                                  /* generate_summary */
1238
 NULL,                                  /* write_summary */
1239
 NULL,                                  /* read_summary */
1240
 ipa_reference_write_optimization_summary,/* write_optimization_summary */
1241
 ipa_reference_read_optimization_summary,/* read_optimization_summary */
1242
 NULL,                                  /* stmt_fixup */
1243
 0,                                      /* TODOs */
1244
 NULL,                                  /* function_transform */
1245
 NULL                                   /* variable_transform */
1246
};

powered by: WebSVN 2.1.0

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