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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ipa-reference.c] - Blame information for rev 309

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

Line No. Rev Author Line
1 280 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
   There are two categories of information produced by this pass:
26
 
27
   1) The addressable (TREE_ADDRESSABLE) bit and readonly
28
   (TREE_READONLY) bit associated with these variables is properly set
29
   based on scanning all of the code withing the compilation unit.
30
 
31
   2) The transitive call site specific clobber effects are computed
32
   for the variables whose scope is contained within this compilation
33
   unit.
34
 
35
   First each function and static variable initialization is analyzed
36
   to determine which local static variables are either read, written,
37
   or have their address taken.  Any local static that has its address
38
   taken is removed from consideration.  Once the local read and
39
   writes are determined, a transitive closure of this information is
40
   performed over the call graph to determine the worst case set of
41
   side effects of each call.  In later parts of the compiler, these
42
   local and global sets are examined to make the call clobbering less
43
   traumatic, promote some statics to registers, and improve aliasing
44
   information.
45
 
46
   Currently must be run after inlining decisions have been made since
47
   otherwise, the local sets will not contain information that is
48
   consistent with post inlined state.  The global sets are not prone
49
   to this problem since they are by definition transitive.  */
50
 
51
#include "config.h"
52
#include "system.h"
53
#include "coretypes.h"
54
#include "tm.h"
55
#include "tree.h"
56
#include "tree-flow.h"
57
#include "tree-inline.h"
58
#include "tree-pass.h"
59
#include "langhooks.h"
60
#include "pointer-set.h"
61
#include "splay-tree.h"
62
#include "ggc.h"
63
#include "ipa-utils.h"
64
#include "ipa-reference.h"
65
#include "gimple.h"
66
#include "cgraph.h"
67
#include "output.h"
68
#include "flags.h"
69
#include "timevar.h"
70
#include "diagnostic.h"
71
#include "langhooks.h"
72
#include "lto-streamer.h"
73
 
74
static void add_new_function (struct cgraph_node *node,
75
                              void *data ATTRIBUTE_UNUSED);
76
static void remove_node_data (struct cgraph_node *node,
77
                              void *data ATTRIBUTE_UNUSED);
78
static void duplicate_node_data (struct cgraph_node *src,
79
                                 struct cgraph_node *dst,
80
                                 void *data ATTRIBUTE_UNUSED);
81
 
82
/* The static variables defined within the compilation unit that are
83
   loaded or stored directly by function that owns this structure.  */
84
 
85
struct ipa_reference_local_vars_info_d
86
{
87
  bitmap statics_read;
88
  bitmap statics_written;
89
 
90
  /* Set when this function calls another function external to the
91
     compilation unit or if the function has a asm clobber of memory.
92
     In general, such calls are modeled as reading and writing all
93
     variables (both bits on) but sometime there are attributes on the
94
     called function so we can do better.  */
95
  bool calls_read_all;
96
  bool calls_write_all;
97
};
98
 
99
/* Statics that are read and written by some set of functions. The
100
   local ones are based on the loads and stores local to the function.
101
   The global ones are based on the local info as well as the
102
   transitive closure of the functions that are called.  The
103
   structures are separated to allow the global structures to be
104
   shared between several functions since every function within a
105
   strongly connected component will have the same information.  This
106
   sharing saves both time and space in the computation of the vectors
107
   as well as their translation from decl_uid form to ann_uid
108
   form.  */
109
 
110
struct ipa_reference_global_vars_info_d
111
{
112
  bitmap statics_read;
113
  bitmap statics_written;
114
  bitmap statics_not_read;
115
  bitmap statics_not_written;
116
};
117
 
118
typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
119
typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
120
struct ipa_reference_vars_info_d
121
{
122
  ipa_reference_local_vars_info_t local;
123
  ipa_reference_global_vars_info_t global;
124
};
125
 
126
typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
127
 
128
/* This splay tree contains all of the static variables that are
129
   being considered by the compilation level alias analysis.  For
130
   module_at_a_time compilation, this is the set of static but not
131
   public variables.  Any variables that either have their address
132
   taken or participate in otherwise unsavory operations are deleted
133
   from this list.  */
134
static GTY((param1_is(int), param2_is(tree)))
135
     splay_tree reference_vars_to_consider;
136
 
137
/* This bitmap is used to knock out the module static variables whose
138
   addresses have been taken and passed around.  */
139
static bitmap module_statics_escape;
140
 
141
/* This bitmap is used to knock out the module static variables that
142
   are not readonly.  */
143
static bitmap module_statics_written;
144
 
145
/* A bit is set for every module static we are considering.  This is
146
   ored into the local info when asm code is found that clobbers all
147
   memory. */
148
static bitmap all_module_statics;
149
 
150
static struct pointer_set_t *visited_nodes;
151
 
152
/* Obstack holding bitmaps of local analysis (live from analysis to
153
   propagation)  */
154
static bitmap_obstack local_info_obstack;
155
/* Obstack holding global analysis live forever.  */
156
static bitmap_obstack global_info_obstack;
157
 
158
/* Holders of ipa cgraph hooks: */
159
static struct cgraph_node_hook_list *function_insertion_hook_holder;
160
static struct cgraph_2node_hook_list *node_duplication_hook_holder;
161
static struct cgraph_node_hook_list *node_removal_hook_holder;
162
 
163
enum initialization_status_t
164
{
165
  UNINITIALIZED,
166
  RUNNING,
167
  FINISHED
168
};
169
 
170
tree memory_identifier_string;
171
 
172
/* Vector where the reference var infos are actually stored. */
173
DEF_VEC_P (ipa_reference_vars_info_t);
174
DEF_VEC_ALLOC_P (ipa_reference_vars_info_t, heap);
175
static VEC (ipa_reference_vars_info_t, heap) *ipa_reference_vars_vector;
176
 
177
/* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
178
static inline ipa_reference_vars_info_t
179
get_reference_vars_info (struct cgraph_node *node)
180
{
181
  if (!ipa_reference_vars_vector
182
      || VEC_length (ipa_reference_vars_info_t, ipa_reference_vars_vector) <= (unsigned int)node->uid)
183
    return NULL;
184
  return VEC_index (ipa_reference_vars_info_t, ipa_reference_vars_vector, node->uid);
185
}
186
 
187
/* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
188
static inline void
189
set_reference_vars_info (struct cgraph_node *node, ipa_reference_vars_info_t info)
190
{
191
  if (!ipa_reference_vars_vector
192
      || VEC_length (ipa_reference_vars_info_t, ipa_reference_vars_vector) <= (unsigned int)node->uid)
193
     VEC_safe_grow_cleared (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector, node->uid + 1);
194
  VEC_replace (ipa_reference_vars_info_t, ipa_reference_vars_vector, node->uid, info);
195
}
196
 
197
/* Get a bitmap that contains all of the locally referenced static
198
   variables for function FN.  */
199
static ipa_reference_local_vars_info_t
200
get_local_reference_vars_info (struct cgraph_node *fn)
201
{
202
  ipa_reference_vars_info_t info = get_reference_vars_info (fn);
203
 
204
  if (info)
205
    return info->local;
206
  else
207
    /* This phase was not run.  */
208
    return NULL;
209
}
210
 
211
/* Get a bitmap that contains all of the globally referenced static
212
   variables for function FN.  */
213
 
214
static ipa_reference_global_vars_info_t
215
get_global_reference_vars_info (struct cgraph_node *fn)
216
{
217
  ipa_reference_vars_info_t info = get_reference_vars_info (fn);
218
 
219
  if (info)
220
    return info->global;
221
  else
222
    /* This phase was not run.  */
223
    return NULL;
224
}
225
 
226
/* Return a bitmap indexed by VAR_DECL uid for the static variables
227
   that are read during the execution of the function FN.  Returns
228
   NULL if no data is available.  */
229
 
230
bitmap
231
ipa_reference_get_read_global (struct cgraph_node *fn)
232
{
233
  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
234
  if (g)
235
    return g->statics_read;
236
  else
237
    return NULL;
238
}
239
 
240
/* Return a bitmap indexed by VAR_DECL uid for the static variables
241
   that are written during the execution of the function FN.  Note
242
   that variables written may or may not be read during the function
243
   call.  Returns NULL if no data is available.  */
244
 
245
bitmap
246
ipa_reference_get_written_global (struct cgraph_node *fn)
247
{
248
  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
249
  if (g)
250
    return g->statics_written;
251
  else
252
    return NULL;
253
}
254
 
255
/* Return a bitmap indexed by_DECL_UID uid for the static variables
256
   that are not read during the execution of the function FN.  Returns
257
   NULL if no data is available.  */
258
 
259
bitmap
260
ipa_reference_get_not_read_global (struct cgraph_node *fn)
261
{
262
  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
263
  if (g)
264
    return g->statics_not_read;
265
  else
266
    return NULL;
267
}
268
 
269
/* Return a bitmap indexed by DECL_UID uid for the static variables
270
   that are not written during the execution of the function FN.  Note
271
   that variables written may or may not be read during the function
272
   call.  Returns NULL if no data is available.  */
273
 
274
bitmap
275
ipa_reference_get_not_written_global (struct cgraph_node *fn)
276
{
277
  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
278
  if (g)
279
    return g->statics_not_written;
280
  else
281
    return NULL;
282
}
283
 
284
 
285
 
286
/* Add VAR to all_module_statics and the two
287
   reference_vars_to_consider* sets.  */
288
 
289
static inline void
290
add_static_var (tree var)
291
{
292
  int uid = DECL_UID (var);
293
  gcc_assert (TREE_CODE (var) == VAR_DECL);
294
  if (!bitmap_bit_p (all_module_statics, uid))
295
    {
296
      splay_tree_insert (reference_vars_to_consider,
297
                         uid, (splay_tree_value)var);
298
      bitmap_set_bit (all_module_statics, uid);
299
    }
300
}
301
 
302
/* Return true if the variable T is the right kind of static variable to
303
   perform compilation unit scope escape analysis.  */
304
 
305
static inline bool
306
has_proper_scope_for_analysis (tree t)
307
{
308
  /* If the variable has the "used" attribute, treat it as if it had a
309
     been touched by the devil.  */
310
  if (DECL_PRESERVE_P (t))
311
    return false;
312
 
313
  /* Do not want to do anything with volatile except mark any
314
     function that uses one to be not const or pure.  */
315
  if (TREE_THIS_VOLATILE (t))
316
    return false;
317
 
318
  /* Do not care about a local automatic that is not static.  */
319
  if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
320
    return false;
321
 
322
  /* FIXME: for LTO we should include PUBLIC vars too.  This is bit difficult
323
     as summarie would need unsharing.  */
324
  if (DECL_EXTERNAL (t) || TREE_PUBLIC (t))
325
    return false;
326
 
327
  /* We cannot touch decls where the type needs constructing.  */
328
  if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t)))
329
    return false;
330
 
331
  /* This is a variable we care about.  Check if we have seen it
332
     before, and if not add it the set of variables we care about.  */
333
  if (!bitmap_bit_p (all_module_statics, DECL_UID (t)))
334
    add_static_var (t);
335
 
336
  return true;
337
}
338
 
339
/* Mark tree T as having address taken.  */
340
 
341
static void
342
mark_address_taken (tree x)
343
{
344
  if (TREE_CODE (x) == VAR_DECL
345
      && module_statics_escape && has_proper_scope_for_analysis (x))
346
    bitmap_set_bit (module_statics_escape, DECL_UID (x));
347
}
348
 
349
/* Wrapper around mark_address_taken for the stmt walker.  */
350
 
351
static bool
352
mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
353
              void *data ATTRIBUTE_UNUSED)
354
{
355
  while (handled_component_p (addr))
356
    addr = TREE_OPERAND (addr, 0);
357
  mark_address_taken (addr);
358
  return false;
359
}
360
 
361
/* Mark load of T.  */
362
 
363
static bool
364
mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
365
{
366
  ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data;
367
  if (TREE_CODE (t) == VAR_DECL
368
      && has_proper_scope_for_analysis (t))
369
    bitmap_set_bit (local->statics_read, DECL_UID (t));
370
  return false;
371
}
372
 
373
/* Mark store of T.  */
374
 
375
static bool
376
mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
377
{
378
  ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data;
379
  if (TREE_CODE (t) == VAR_DECL
380
      && has_proper_scope_for_analysis (t))
381
    {
382
      if (local)
383
        bitmap_set_bit (local->statics_written, DECL_UID (t));
384
      /* Mark the write so we can tell which statics are
385
         readonly.  */
386
      if (module_statics_written)
387
        bitmap_set_bit (module_statics_written, DECL_UID (t));
388
    }
389
  return false;
390
}
391
 
392
/* Look for memory clobber and set read_all/write_all if present.  */
393
 
394
static void
395
check_asm_memory_clobber (ipa_reference_local_vars_info_t local, gimple stmt)
396
{
397
  size_t i;
398
  tree op;
399
 
400
  for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
401
    {
402
      op = gimple_asm_clobber_op (stmt, i);
403
      if (simple_cst_equal(TREE_VALUE (op), memory_identifier_string) == 1)
404
        {
405
          /* Abandon all hope, ye who enter here. */
406
          local->calls_read_all = true;
407
          local->calls_write_all = true;
408
        }
409
    }
410
}
411
 
412
/* Look for external calls and set read_all/write_all correspondingly.  */
413
 
414
static void
415
check_call (ipa_reference_local_vars_info_t local, gimple stmt)
416
{
417
  int flags = gimple_call_flags (stmt);
418
  tree callee_t = gimple_call_fndecl (stmt);
419
 
420
  /* Process indirect calls.  All direct calles are handled at propagation
421
     time.  */
422
  if (!callee_t)
423
    {
424
      if (flags & ECF_CONST)
425
        ;
426
      else if (flags & ECF_PURE)
427
        local->calls_read_all = true;
428
      else
429
        {
430
          local->calls_read_all = true;
431
          /* When function does not reutrn, it is safe to ignore anythign it writes
432
             to, because the effect will never happen.  */
433
          if ((flags & (ECF_NOTHROW | ECF_NORETURN))
434
              != (ECF_NOTHROW | ECF_NORETURN))
435
            local->calls_write_all = true;
436
        }
437
    }
438
}
439
 
440
/* TP is the part of the tree currently under the microscope.
441
   WALK_SUBTREES is part of the walk_tree api but is unused here.
442
   DATA is cgraph_node of the function being walked.  */
443
 
444
static tree
445
scan_stmt_for_static_refs (gimple_stmt_iterator *gsip,
446
                           struct cgraph_node *fn)
447
{
448
  gimple stmt = gsi_stmt (*gsip);
449
  ipa_reference_local_vars_info_t local = NULL;
450
 
451
  if (is_gimple_debug (stmt))
452
    return NULL;
453
 
454
  if (fn)
455
    local = get_reference_vars_info (fn)->local;
456
 
457
  /* Look for direct loads and stores.  */
458
  walk_stmt_load_store_addr_ops (stmt, local, mark_load, mark_store,
459
                                 mark_address);
460
 
461
  if (is_gimple_call (stmt))
462
    check_call (local, stmt);
463
  else if (gimple_code (stmt) == GIMPLE_ASM)
464
    check_asm_memory_clobber (local, stmt);
465
 
466
  return NULL;
467
}
468
 
469
/* Call-back to scan variable initializers for static references.
470
   Called using walk_tree.  */
471
 
472
static tree
473
scan_initializer_for_static_refs (tree *tp, int *walk_subtrees,
474
                                  void *data ATTRIBUTE_UNUSED)
475
{
476
  tree t = *tp;
477
 
478
  if (TREE_CODE (t) == ADDR_EXPR)
479
    {
480
      mark_address_taken (get_base_var (t));
481
      *walk_subtrees = 0;
482
    }
483
  /* Save some cycles by not walking types and declaration as we
484
     won't find anything useful there anyway.  */
485
  else if (IS_TYPE_OR_DECL_P (*tp))
486
    *walk_subtrees = 0;
487
 
488
  return NULL;
489
}
490
 
491
/* Lookup the tree node for the static variable that has UID.  */
492
static tree
493
get_static_decl (int index)
494
{
495
  splay_tree_node stn =
496
    splay_tree_lookup (reference_vars_to_consider, index);
497
  if (stn)
498
    return (tree)stn->value;
499
  return NULL;
500
}
501
 
502
/* Lookup the tree node for the static variable that has UID and
503
   convert the name to a string for debugging.  */
504
 
505
static const char *
506
get_static_name (int index)
507
{
508
  splay_tree_node stn =
509
    splay_tree_lookup (reference_vars_to_consider, index);
510
  if (stn)
511
    return lang_hooks.decl_printable_name ((tree)(stn->value), 2);
512
  return NULL;
513
}
514
 
515
/* Or in all of the bits from every callee of X into X_GLOBAL, the caller's cycle,
516
   bit vector.  There are several cases to check to avoid the sparse
517
   bitmap oring.  */
518
 
519
static void
520
propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
521
{
522
  struct cgraph_edge *e;
523
  for (e = x->callees; e; e = e->next_callee)
524
    {
525
      struct cgraph_node *y = e->callee;
526
 
527
      /* Only look into nodes we can propagate something.  */
528
      if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE)
529
        {
530
          if (get_reference_vars_info (y))
531
            {
532
              ipa_reference_vars_info_t y_info
533
                = get_reference_vars_info (y);
534
              ipa_reference_global_vars_info_t y_global = y_info->global;
535
 
536
              /* Calls in current cycle do not have global computed yet.  */
537
              if (!y_info->global)
538
                continue;
539
 
540
              if (x_global->statics_read
541
                  != all_module_statics)
542
                {
543
                  if (y_global->statics_read
544
                      == all_module_statics)
545
                    {
546
                      BITMAP_FREE (x_global->statics_read);
547
                      x_global->statics_read
548
                        = all_module_statics;
549
                    }
550
                  /* Skip bitmaps that are pointer equal to node's bitmap
551
                     (no reason to spin within the cycle).  */
552
                  else if (x_global->statics_read
553
                           != y_global->statics_read)
554
                    bitmap_ior_into (x_global->statics_read,
555
                                     y_global->statics_read);
556
                }
557
 
558
              if (x_global->statics_written
559
                  != all_module_statics)
560
                {
561
                  if (y_global->statics_written
562
                      == all_module_statics)
563
                    {
564
                      BITMAP_FREE (x_global->statics_written);
565
                      x_global->statics_written
566
                        = all_module_statics;
567
                    }
568
                  /* Skip bitmaps that are pointer equal to node's bitmap
569
                     (no reason to spin within the cycle).  */
570
                  else if (x_global->statics_written
571
                           != y_global->statics_written)
572
                    bitmap_ior_into (x_global->statics_written,
573
                                     y_global->statics_written);
574
                }
575
            }
576
          else
577
            gcc_unreachable ();
578
        }
579
    }
580
}
581
 
582
/* The init routine for analyzing global static variable usage.  See
583
   comments at top for description.  */
584
static void
585
ipa_init (void)
586
{
587
  static bool init_p = false;
588
 
589
  if (init_p)
590
    return;
591
 
592
  init_p = true;
593
 
594
  memory_identifier_string = build_string(7, "memory");
595
 
596
  reference_vars_to_consider =
597
    splay_tree_new_ggc (splay_tree_compare_ints);
598
 
599
  bitmap_obstack_initialize (&local_info_obstack);
600
  bitmap_obstack_initialize (&global_info_obstack);
601
  module_statics_escape = BITMAP_ALLOC (&local_info_obstack);
602
  module_statics_written = BITMAP_ALLOC (&local_info_obstack);
603
  all_module_statics = BITMAP_ALLOC (&global_info_obstack);
604
 
605
  /* There are some shared nodes, in particular the initializers on
606
     static declarations.  We do not need to scan them more than once
607
     since all we would be interested in are the addressof
608
     operations.  */
609
  visited_nodes = pointer_set_create ();
610
 
611
  function_insertion_hook_holder =
612
      cgraph_add_function_insertion_hook (&add_new_function, NULL);
613
  node_removal_hook_holder =
614
      cgraph_add_node_removal_hook (&remove_node_data, NULL);
615
  node_duplication_hook_holder =
616
      cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
617
}
618
 
619
/* Check out the rhs of a static or global initialization VNODE to see
620
   if any of them contain addressof operations.  Note that some of
621
   these variables may  not even be referenced in the code in this
622
   compilation unit but their right hand sides may contain references
623
   to variables defined within this unit.  */
624
 
625
static void
626
analyze_variable (struct varpool_node *vnode)
627
{
628
  struct walk_stmt_info wi;
629
  tree global = vnode->decl;
630
 
631
  memset (&wi, 0, sizeof (wi));
632
  wi.pset = visited_nodes;
633
  walk_tree (&DECL_INITIAL (global), scan_initializer_for_static_refs,
634
             &wi, wi.pset);
635
}
636
 
637
 
638
/* Set up the persistent info for FN.  */
639
 
640
static ipa_reference_local_vars_info_t
641
init_function_info (struct cgraph_node *fn)
642
{
643
  ipa_reference_vars_info_t info
644
    = XCNEW (struct ipa_reference_vars_info_d);
645
  ipa_reference_local_vars_info_t l
646
    = XCNEW (struct ipa_reference_local_vars_info_d);
647
 
648
  /* Add the info to the tree's annotation.  */
649
  set_reference_vars_info (fn, info);
650
 
651
  info->local = l;
652
  l->statics_read = BITMAP_ALLOC (&local_info_obstack);
653
  l->statics_written = BITMAP_ALLOC (&local_info_obstack);
654
 
655
  return l;
656
}
657
 
658
 
659
/* This is the main routine for finding the reference patterns for
660
   global variables within a function FN.  */
661
 
662
static void
663
analyze_function (struct cgraph_node *fn)
664
{
665
  tree decl = fn->decl;
666
  struct function *this_cfun = DECL_STRUCT_FUNCTION (decl);
667
  basic_block this_block;
668
#ifdef ENABLE_CHECKING
669
  tree step;
670
#endif
671
  ipa_reference_local_vars_info_t local;
672
 
673
  if (dump_file)
674
    fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn));
675
 
676
  push_cfun (DECL_STRUCT_FUNCTION (decl));
677
  current_function_decl = decl;
678
 
679
  init_function_info (fn);
680
  FOR_EACH_BB_FN (this_block, this_cfun)
681
    {
682
      gimple_stmt_iterator gsi;
683
      gimple phi;
684
      tree op;
685
      use_operand_p use;
686
      ssa_op_iter iter;
687
 
688
      /* Find the addresses taken in phi node arguments.  */
689
      for (gsi = gsi_start_phis (this_block);
690
           !gsi_end_p (gsi);
691
           gsi_next (&gsi))
692
        {
693
          phi = gsi_stmt (gsi);
694
          FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
695
            {
696
              op = USE_FROM_PTR (use);
697
              if (TREE_CODE (op) == ADDR_EXPR)
698
                mark_address_taken (get_base_var (op));
699
            }
700
        }
701
 
702
      for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
703
        scan_stmt_for_static_refs (&gsi, fn);
704
    }
705
 
706
  local = get_reference_vars_info (fn)->local;
707
  if ((flags_from_decl_or_type (decl) & (ECF_NOTHROW | ECF_NORETURN))
708
      == (ECF_NOTHROW | ECF_NORETURN))
709
    {
710
      local->calls_write_all = false;
711
      bitmap_clear (local->statics_written);
712
    }
713
 
714
  /* Free bitmaps of direct references if we can not use them anyway.  */
715
  if (local->calls_write_all)
716
    BITMAP_FREE (local->statics_written);
717
  if (local->calls_read_all)
718
    BITMAP_FREE (local->statics_read);
719
 
720
 
721
#ifdef ENABLE_CHECKING
722
  /* Verify that all local initializers was expanded by gimplifier.  */
723
  for (step = DECL_STRUCT_FUNCTION (decl)->local_decls;
724
       step;
725
       step = TREE_CHAIN (step))
726
    {
727
      tree var = TREE_VALUE (step);
728
      if (TREE_CODE (var) == VAR_DECL
729
          && DECL_INITIAL (var)
730
          && !TREE_STATIC (var))
731
        gcc_unreachable ();
732
    }
733
#endif
734
  pop_cfun ();
735
  current_function_decl = NULL;
736
}
737
 
738
/* Remove local data associated with function FN.  */
739
static void
740
clean_function_local_data (struct cgraph_node *fn)
741
{
742
  ipa_reference_vars_info_t info = get_reference_vars_info (fn);
743
  ipa_reference_local_vars_info_t l = info->local;
744
  if (l)
745
    {
746
      if (l->statics_read
747
          && l->statics_read != all_module_statics)
748
        BITMAP_FREE (l->statics_read);
749
      if (l->statics_written
750
          &&l->statics_written != all_module_statics)
751
        BITMAP_FREE (l->statics_written);
752
      free (l);
753
      info->local = NULL;
754
    }
755
}
756
 
757
/* Remove all data associated with function FN.  */
758
 
759
static void
760
clean_function (struct cgraph_node *fn)
761
{
762
  ipa_reference_vars_info_t info = get_reference_vars_info (fn);
763
  ipa_reference_global_vars_info_t g = info->global;
764
 
765
  clean_function_local_data (fn);
766
  if (g)
767
    {
768
      if (g->statics_read
769
          && g->statics_read != all_module_statics)
770
        BITMAP_FREE (g->statics_read);
771
 
772
      if (g->statics_written
773
          && g->statics_written != all_module_statics)
774
        BITMAP_FREE (g->statics_written);
775
 
776
      if (g->statics_not_read
777
          && g->statics_not_read != all_module_statics)
778
        BITMAP_FREE (g->statics_not_read);
779
 
780
      if (g->statics_not_written
781
          && g->statics_not_written != all_module_statics)
782
        BITMAP_FREE (g->statics_not_written);
783
      free (g);
784
      info->global = NULL;
785
    }
786
 
787
  free (get_reference_vars_info (fn));
788
  set_reference_vars_info (fn, NULL);
789
}
790
 
791
/* Called when new function is inserted to callgraph late.  */
792
static void
793
add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
794
{
795
  /* There are some shared nodes, in particular the initializers on
796
     static declarations.  We do not need to scan them more than once
797
     since all we would be interested in are the addressof
798
     operations.  */
799
  analyze_function (node);
800
  visited_nodes = NULL;
801
}
802
 
803
static bitmap
804
copy_local_bitmap (bitmap src)
805
{
806
  bitmap dst;
807
  if (!src)
808
    return NULL;
809
  if (src == all_module_statics)
810
    return all_module_statics;
811
  dst = BITMAP_ALLOC (&local_info_obstack);
812
  bitmap_copy (dst, src);
813
  return dst;
814
}
815
 
816
static bitmap
817
copy_global_bitmap (bitmap src)
818
{
819
  bitmap dst;
820
  if (!src)
821
    return NULL;
822
  if (src == all_module_statics)
823
    return all_module_statics;
824
  dst = BITMAP_ALLOC (&global_info_obstack);
825
  bitmap_copy (dst, src);
826
  return dst;
827
}
828
 
829
/* Called when new clone is inserted to callgraph late.  */
830
 
831
static void
832
duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
833
                     void *data ATTRIBUTE_UNUSED)
834
{
835
  ipa_reference_global_vars_info_t ginfo;
836
  ipa_reference_local_vars_info_t linfo;
837
  ipa_reference_global_vars_info_t dst_ginfo;
838
  ipa_reference_local_vars_info_t dst_linfo;
839
 
840
  ginfo = get_global_reference_vars_info (src);
841
  linfo = get_local_reference_vars_info (src);
842
  if (!linfo && !ginfo)
843
    return;
844
  init_function_info (dst);
845
  if (linfo)
846
    {
847
      dst_linfo = get_local_reference_vars_info (dst);
848
      dst_linfo->statics_read = copy_local_bitmap (linfo->statics_read);
849
      dst_linfo->statics_written = copy_local_bitmap (linfo->statics_written);
850
      dst_linfo->calls_read_all = linfo->calls_read_all;
851
      dst_linfo->calls_write_all = linfo->calls_write_all;
852
    }
853
  if (ginfo)
854
    {
855
      get_reference_vars_info (dst)->global = XCNEW (struct ipa_reference_global_vars_info_d);
856
      dst_ginfo = get_global_reference_vars_info (dst);
857
      dst_ginfo->statics_read = copy_global_bitmap (ginfo->statics_read);
858
      dst_ginfo->statics_written = copy_global_bitmap (ginfo->statics_written);
859
      dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read);
860
      dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written);
861
    }
862
}
863
 
864
/* Called when node is removed.  */
865
 
866
static void
867
remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
868
{
869
  if (get_reference_vars_info (node))
870
    clean_function (node);
871
}
872
 
873
/* Analyze each function in the cgraph to see which global or statics
874
   are read or written.  */
875
 
876
static void
877
generate_summary (void)
878
{
879
  struct cgraph_node *node;
880
  struct varpool_node *vnode;
881
  unsigned int index;
882
  bitmap_iterator bi;
883
  bitmap module_statics_readonly;
884
  bitmap bm_temp;
885
 
886
  ipa_init ();
887
  module_statics_readonly = BITMAP_ALLOC (&local_info_obstack);
888
  bm_temp = BITMAP_ALLOC (&local_info_obstack);
889
 
890
  /* Process all of the variables first.  */
891
  FOR_EACH_STATIC_INITIALIZER (vnode)
892
    analyze_variable (vnode);
893
 
894
  /* Process all of the functions next.
895
 
896
     We do not want to process any of the clones so we check that this
897
     is a master clone.  However, we do need to process any
898
     AVAIL_OVERWRITABLE functions (these are never clones) because
899
     they may cause a static variable to escape.  The code that can
900
     overwrite such a function cannot access the statics because it
901
     would not be in the same compilation unit.  When the analysis is
902
     finished, the computed information of these AVAIL_OVERWRITABLE is
903
     replaced with worst case info.
904
  */
905
  for (node = cgraph_nodes; node; node = node->next)
906
    if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
907
      analyze_function (node);
908
 
909
  pointer_set_destroy (visited_nodes);
910
  visited_nodes = NULL;
911
 
912
  /* Prune out the variables that were found to behave badly
913
     (i.e. have their address taken).  */
914
  EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi)
915
    {
916
      splay_tree_remove (reference_vars_to_consider, index);
917
    }
918
 
919
  bitmap_and_compl_into (all_module_statics,
920
                         module_statics_escape);
921
 
922
  bitmap_and_compl (module_statics_readonly, all_module_statics,
923
                    module_statics_written);
924
 
925
  /* If the address is not taken, we can unset the addressable bit
926
     on this variable.  */
927
  EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
928
    {
929
      tree var = get_static_decl (index);
930
      TREE_ADDRESSABLE (var) = 0;
931
      if (dump_file)
932
        fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n",
933
                 get_static_name (index));
934
    }
935
 
936
  /* If the variable is never written, we can set the TREE_READONLY
937
     flag.  Additionally if it has a DECL_INITIAL that is made up of
938
     constants we can treat the entire global as a constant.  */
939
 
940
  bitmap_and_compl (module_statics_readonly, all_module_statics,
941
                    module_statics_written);
942
  EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi)
943
    {
944
      tree var = get_static_decl (index);
945
 
946
      /* Ignore variables in named sections - changing TREE_READONLY
947
         changes the section flags, potentially causing conflicts with
948
         other variables in the same named section.  */
949
      if (DECL_SECTION_NAME (var) == NULL_TREE)
950
        {
951
          TREE_READONLY (var) = 1;
952
          if (dump_file)
953
            fprintf (dump_file, "read-only var %s\n",
954
                     get_static_name (index));
955
        }
956
    }
957
 
958
  BITMAP_FREE(module_statics_escape);
959
  BITMAP_FREE(module_statics_written);
960
  module_statics_escape = NULL;
961
  module_statics_written = NULL;
962
 
963
  if (dump_file)
964
    EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
965
      {
966
        fprintf (dump_file, "\nPromotable global:%s",
967
                 get_static_name (index));
968
      }
969
 
970
  for (node = cgraph_nodes; node; node = node->next)
971
    if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
972
      {
973
        ipa_reference_local_vars_info_t l;
974
        l = get_reference_vars_info (node)->local;
975
 
976
        /* Any variables that are not in all_module_statics are
977
           removed from the local maps.  This will include all of the
978
           variables that were found to escape in the function
979
           scanning.  */
980
        if (l->statics_read)
981
          bitmap_and_into (l->statics_read,
982
                           all_module_statics);
983
        if (l->statics_written)
984
          bitmap_and_into (l->statics_written,
985
                           all_module_statics);
986
      }
987
 
988
  BITMAP_FREE(module_statics_readonly);
989
  BITMAP_FREE(bm_temp);
990
 
991
  if (dump_file)
992
    for (node = cgraph_nodes; node; node = node->next)
993
      if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
994
        {
995
          ipa_reference_local_vars_info_t l;
996
          unsigned int index;
997
          bitmap_iterator bi;
998
 
999
          l = get_reference_vars_info (node)->local;
1000
          fprintf (dump_file,
1001
                   "\nFunction name:%s/%i:",
1002
                   cgraph_node_name (node), node->uid);
1003
          fprintf (dump_file, "\n  locals read: ");
1004
          if (l->statics_read)
1005
            EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
1006
                                      0, index, bi)
1007
              {
1008
                fprintf (dump_file, "%s ",
1009
                         get_static_name (index));
1010
              }
1011
          fprintf (dump_file, "\n  locals written: ");
1012
          if (l->statics_written)
1013
            EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
1014
                                      0, index, bi)
1015
              {
1016
                fprintf(dump_file, "%s ",
1017
                        get_static_name (index));
1018
              }
1019
          if (l->calls_read_all)
1020
             fprintf (dump_file, "\n  calls read all: ");
1021
          if (l->calls_write_all)
1022
             fprintf (dump_file, "\n  calls read all: ");
1023
        }
1024
}
1025
 
1026
 
1027
/* Return true if we need to write summary of NODE. */
1028
 
1029
static bool
1030
write_node_summary_p (struct cgraph_node *node)
1031
{
1032
  gcc_assert (node->global.inlined_to == NULL);
1033
  return (node->analyzed
1034
          && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE
1035
          && get_reference_vars_info (node) != NULL);
1036
}
1037
 
1038
/* Serialize the ipa info for lto.  */
1039
 
1040
static void
1041
ipa_reference_write_summary (cgraph_node_set set)
1042
{
1043
  struct cgraph_node *node;
1044
  struct lto_simple_output_block *ob
1045
    = lto_create_simple_output_block (LTO_section_ipa_reference);
1046
  unsigned int count = 0;
1047
  cgraph_node_set_iterator csi;
1048
 
1049
  for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
1050
    if (write_node_summary_p (csi_node (csi)))
1051
        count++;
1052
 
1053
  lto_output_uleb128_stream (ob->main_stream, count);
1054
 
1055
  /* Process all of the functions.  */
1056
  for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
1057
    {
1058
      node = csi_node (csi);
1059
      if (write_node_summary_p (node))
1060
        {
1061
          ipa_reference_local_vars_info_t l
1062
            = get_reference_vars_info (node)->local;
1063
          unsigned int index;
1064
          bitmap_iterator bi;
1065
          lto_cgraph_encoder_t encoder;
1066
          int node_ref;
1067
 
1068
          encoder = ob->decl_state->cgraph_node_encoder;
1069
          node_ref = lto_cgraph_encoder_encode (encoder, node);
1070
          lto_output_uleb128_stream (ob->main_stream, node_ref);
1071
 
1072
          /* Stream out the statics read.  */
1073
          if (l->calls_read_all)
1074
            lto_output_sleb128_stream (ob->main_stream, -1);
1075
          else
1076
            {
1077
              lto_output_sleb128_stream (ob->main_stream,
1078
                                         bitmap_count_bits (l->statics_read));
1079
              EXECUTE_IF_SET_IN_BITMAP (l->statics_read, 0, index, bi)
1080
                lto_output_var_decl_index(ob->decl_state, ob->main_stream,
1081
                                          get_static_decl (index));
1082
            }
1083
 
1084
          /* Stream out the statics written.  */
1085
          if (l->calls_write_all)
1086
            lto_output_sleb128_stream (ob->main_stream, -1);
1087
          else
1088
            {
1089
              lto_output_sleb128_stream (ob->main_stream,
1090
                                         bitmap_count_bits (l->statics_written));
1091
              EXECUTE_IF_SET_IN_BITMAP (l->statics_written, 0, index, bi)
1092
                lto_output_var_decl_index(ob->decl_state, ob->main_stream,
1093
                                          get_static_decl (index));
1094
            }
1095
        }
1096
    }
1097
  lto_destroy_simple_output_block (ob);
1098
}
1099
 
1100
 
1101
/* Deserialize the ipa info for lto.  */
1102
 
1103
static void
1104
ipa_reference_read_summary (void)
1105
{
1106
  struct lto_file_decl_data ** file_data_vec
1107
    = lto_get_file_decl_data ();
1108
  struct lto_file_decl_data * file_data;
1109
  unsigned int j = 0;
1110
 
1111
  ipa_init ();
1112
 
1113
  while ((file_data = file_data_vec[j++]))
1114
    {
1115
      const char *data;
1116
      size_t len;
1117
      struct lto_input_block *ib
1118
        = lto_create_simple_input_block (file_data,
1119
                                         LTO_section_ipa_reference,
1120
                                         &data, &len);
1121
      if (ib)
1122
        {
1123
          unsigned int i;
1124
          unsigned int f_count = lto_input_uleb128 (ib);
1125
 
1126
          for (i = 0; i < f_count; i++)
1127
            {
1128
              unsigned int j, index;
1129
              struct cgraph_node *node;
1130
              ipa_reference_local_vars_info_t l;
1131
              int v_count;
1132
              lto_cgraph_encoder_t encoder;
1133
 
1134
              index = lto_input_uleb128 (ib);
1135
              encoder = file_data->cgraph_node_encoder;
1136
              node = lto_cgraph_encoder_deref (encoder, index);
1137
              l = init_function_info (node);
1138
 
1139
              /* Set the statics read.  */
1140
              v_count = lto_input_sleb128 (ib);
1141
              if (v_count == -1)
1142
                l->calls_read_all = true;
1143
              else
1144
                for (j = 0; j < (unsigned int)v_count; j++)
1145
                  {
1146
                    unsigned int var_index = lto_input_uleb128 (ib);
1147
                    tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1148
                                                                   var_index);
1149
                    add_static_var (v_decl);
1150
                    bitmap_set_bit (l->statics_read, DECL_UID (v_decl));
1151
                  }
1152
 
1153
              /* Set the statics written.  */
1154
              v_count = lto_input_sleb128 (ib);
1155
              if (v_count == -1)
1156
                l->calls_write_all = true;
1157
              else
1158
                for (j = 0; j < (unsigned int)v_count; j++)
1159
                  {
1160
                    unsigned int var_index = lto_input_uleb128 (ib);
1161
                    tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1162
                                                                   var_index);
1163
                    add_static_var (v_decl);
1164
                    bitmap_set_bit (l->statics_written, DECL_UID (v_decl));
1165
                  }
1166
            }
1167
 
1168
          lto_destroy_simple_input_block (file_data,
1169
                                          LTO_section_ipa_reference,
1170
                                          ib, data, len);
1171
        }
1172
    }
1173
}
1174
 
1175
 
1176
 
1177
/* Set READ_ALL/WRITE_ALL based on DECL flags.  */
1178
static void
1179
read_write_all_from_decl (tree decl, bool * read_all, bool * write_all)
1180
{
1181
  int flags = flags_from_decl_or_type (decl);
1182
  if (flags & ECF_CONST)
1183
    ;
1184
  else if (flags & ECF_PURE)
1185
    *read_all = true;
1186
  else
1187
    {
1188
       /* TODO: To be able to produce sane results, we should also handle
1189
          common builtins, in particular throw.
1190
          Indirect calls hsould be only counted and as inliner is replacing them
1191
          by direct calls, we can conclude if any indirect calls are left in body */
1192
      *read_all = true;
1193
      /* When function does not reutrn, it is safe to ignore anythign it writes
1194
         to, because the effect will never happen.  */
1195
      if ((flags & (ECF_NOTHROW | ECF_NORETURN))
1196
          != (ECF_NOTHROW | ECF_NORETURN))
1197
        *write_all = true;
1198
    }
1199
}
1200
 
1201
/* Produce the global information by preforming a transitive closure
1202
   on the local information that was produced by ipa_analyze_function
1203
   and ipa_analyze_variable.  */
1204
 
1205
static unsigned int
1206
propagate (void)
1207
{
1208
  struct cgraph_node *node;
1209
  struct cgraph_node *w;
1210
  struct cgraph_node **order =
1211
    XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1212
  int order_pos = ipa_utils_reduced_inorder (order, false, true, NULL);
1213
  int i;
1214
 
1215
  cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
1216
  if (dump_file)
1217
    dump_cgraph (dump_file);
1218
 
1219
  /* Propagate the local information thru the call graph to produce
1220
     the global information.  All the nodes within a cycle will have
1221
     the same info so we collapse cycles first.  Then we can do the
1222
     propagation in one pass from the leaves to the roots.  */
1223
  order_pos = ipa_utils_reduced_inorder (order, true, true, NULL);
1224
  if (dump_file)
1225
    ipa_utils_print_order(dump_file, "reduced", order, order_pos);
1226
 
1227
  for (i = 0; i < order_pos; i++ )
1228
    {
1229
      ipa_reference_vars_info_t node_info;
1230
      ipa_reference_global_vars_info_t node_g =
1231
        XCNEW (struct ipa_reference_global_vars_info_d);
1232
      ipa_reference_local_vars_info_t node_l;
1233
      struct cgraph_edge *e;
1234
 
1235
      bool read_all;
1236
      bool write_all;
1237
      struct ipa_dfs_info * w_info;
1238
 
1239
      node = order[i];
1240
      node_info = get_reference_vars_info (node);
1241
      if (!node_info)
1242
        {
1243
          dump_cgraph_node (stderr, node);
1244
          dump_cgraph (stderr);
1245
          gcc_unreachable ();
1246
        }
1247
 
1248
      gcc_assert (!node_info->global);
1249
      node_l = node_info->local;
1250
 
1251
      read_all = node_l->calls_read_all;
1252
      write_all = node_l->calls_write_all;
1253
 
1254
      /* When function is overwrittable, we can not assume anything.  */
1255
      if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
1256
        read_write_all_from_decl (node->decl, &read_all, &write_all);
1257
 
1258
      for (e = node->callees; e; e = e->next_callee)
1259
        if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
1260
          read_write_all_from_decl (e->callee->decl, &read_all, &write_all);
1261
 
1262
 
1263
      /* If any node in a cycle is calls_read_all or calls_write_all
1264
         they all are. */
1265
      w_info = (struct ipa_dfs_info *) node->aux;
1266
      w = w_info->next_cycle;
1267
      while (w)
1268
        {
1269
          ipa_reference_local_vars_info_t w_l =
1270
            get_reference_vars_info (w)->local;
1271
 
1272
          /* When function is overwrittable, we can not assume anything.  */
1273
          if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE)
1274
            read_write_all_from_decl (w->decl, &read_all, &write_all);
1275
 
1276
          for (e = w->callees; e; e = e->next_callee)
1277
            if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
1278
              read_write_all_from_decl (e->callee->decl, &read_all, &write_all);
1279
 
1280
          read_all |= w_l->calls_read_all;
1281
          write_all |= w_l->calls_write_all;
1282
 
1283
          w_info = (struct ipa_dfs_info *) w->aux;
1284
          w = w_info->next_cycle;
1285
        }
1286
 
1287
 
1288
      /* Initialized the bitmaps for the reduced nodes */
1289
      if (read_all)
1290
        node_g->statics_read = all_module_statics;
1291
      else
1292
        {
1293
          node_g->statics_read = BITMAP_ALLOC (&global_info_obstack);
1294
          bitmap_copy (node_g->statics_read,
1295
                       node_l->statics_read);
1296
        }
1297
      if (write_all)
1298
        node_g->statics_written = all_module_statics;
1299
      else
1300
        {
1301
          node_g->statics_written = BITMAP_ALLOC (&global_info_obstack);
1302
          bitmap_copy (node_g->statics_written,
1303
                       node_l->statics_written);
1304
        }
1305
 
1306
      propagate_bits (node_g, node);
1307
      w_info = (struct ipa_dfs_info *) node->aux;
1308
      w = w_info->next_cycle;
1309
      while (w)
1310
        {
1311
          ipa_reference_vars_info_t w_ri =
1312
            get_reference_vars_info (w);
1313
          ipa_reference_local_vars_info_t w_l = w_ri->local;
1314
 
1315
          /* These global bitmaps are initialized from the local info
1316
             of all of the nodes in the region.  However there is no
1317
             need to do any work if the bitmaps were set to
1318
             all_module_statics.  */
1319
          if (!read_all)
1320
            bitmap_ior_into (node_g->statics_read,
1321
                             w_l->statics_read);
1322
          if (!write_all)
1323
            bitmap_ior_into (node_g->statics_written,
1324
                             w_l->statics_written);
1325
          propagate_bits (node_g, w);
1326
          w_info = (struct ipa_dfs_info *) w->aux;
1327
          w = w_info->next_cycle;
1328
        }
1329
 
1330
      /* All nodes within a cycle have the same global info bitmaps.  */
1331
      node_info->global = node_g;
1332
      w_info = (struct ipa_dfs_info *) node->aux;
1333
      w = w_info->next_cycle;
1334
      while (w)
1335
        {
1336
          ipa_reference_vars_info_t w_ri =
1337
            get_reference_vars_info (w);
1338
 
1339
          gcc_assert (!w_ri->global);
1340
          w_ri->global = XCNEW (struct ipa_reference_global_vars_info_d);
1341
          w_ri->global->statics_read = copy_global_bitmap (node_g->statics_read);
1342
          w_ri->global->statics_written = copy_global_bitmap (node_g->statics_written);
1343
 
1344
          w_info = (struct ipa_dfs_info *) w->aux;
1345
          w = w_info->next_cycle;
1346
        }
1347
    }
1348
 
1349
  if (dump_file)
1350
    {
1351
      for (i = 0; i < order_pos; i++ )
1352
        {
1353
          ipa_reference_vars_info_t node_info;
1354
          ipa_reference_global_vars_info_t node_g;
1355
          ipa_reference_local_vars_info_t node_l;
1356
          unsigned int index;
1357
          bitmap_iterator bi;
1358
          struct ipa_dfs_info * w_info;
1359
 
1360
          node = order[i];
1361
          node_info = get_reference_vars_info (node);
1362
          node_g = node_info->global;
1363
          node_l = node_info->local;
1364
          fprintf (dump_file,
1365
                   "\nFunction name:%s/%i:",
1366
                   cgraph_node_name (node), node->uid);
1367
          fprintf (dump_file, "\n  locals read: ");
1368
          if (node_l->statics_read)
1369
            EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read,
1370
                                      0, index, bi)
1371
              {
1372
                fprintf (dump_file, "%s ",
1373
                         get_static_name (index));
1374
              }
1375
          fprintf (dump_file, "\n  locals written: ");
1376
          if (node_l->statics_written)
1377
            EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written,
1378
                                      0, index, bi)
1379
              {
1380
                fprintf(dump_file, "%s ",
1381
                        get_static_name (index));
1382
              }
1383
 
1384
          w_info = (struct ipa_dfs_info *) node->aux;
1385
          w = w_info->next_cycle;
1386
          while (w)
1387
            {
1388
              ipa_reference_vars_info_t w_ri =
1389
                get_reference_vars_info (w);
1390
              ipa_reference_local_vars_info_t w_l = w_ri->local;
1391
              fprintf (dump_file, "\n  next cycle: %s/%i ",
1392
                       cgraph_node_name (w), w->uid);
1393
              fprintf (dump_file, "\n    locals read: ");
1394
              if (w_l->statics_read)
1395
                EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read,
1396
                                          0, index, bi)
1397
                  {
1398
                    fprintf (dump_file, "%s ",
1399
                             get_static_name (index));
1400
                  }
1401
 
1402
              fprintf (dump_file, "\n    locals written: ");
1403
              if (w_l->statics_written)
1404
                EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written,
1405
                                          0, index, bi)
1406
                  {
1407
                    fprintf (dump_file, "%s ",
1408
                             get_static_name (index));
1409
                  }
1410
 
1411
              w_info = (struct ipa_dfs_info *) w->aux;
1412
              w = w_info->next_cycle;
1413
            }
1414
          fprintf (dump_file, "\n  globals read: ");
1415
          if (node_g->statics_read == all_module_statics)
1416
            fprintf (dump_file, "ALL");
1417
          else
1418
            EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read,
1419
                                      0, index, bi)
1420
              {
1421
                fprintf (dump_file, "%s ",
1422
                         get_static_name (index));
1423
              }
1424
          fprintf (dump_file, "\n  globals written: ");
1425
          if (node_g->statics_written == all_module_statics)
1426
            fprintf (dump_file, "ALL");
1427
          else
1428
            EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written,
1429
                                      0, index, bi)
1430
              {
1431
                fprintf (dump_file, "%s ",
1432
                         get_static_name (index));
1433
              }
1434
        }
1435
    }
1436
 
1437
  /* Cleanup. */
1438
  for (i = 0; i < order_pos; i++ )
1439
    {
1440
      ipa_reference_vars_info_t node_info;
1441
      ipa_reference_global_vars_info_t node_g;
1442
      node = order[i];
1443
      node_info = get_reference_vars_info (node);
1444
      node_g = node_info->global;
1445
 
1446
      /* Create the complimentary sets.  These are more useful for
1447
         certain apis.  */
1448
      node_g->statics_not_read = BITMAP_ALLOC (&global_info_obstack);
1449
      node_g->statics_not_written = BITMAP_ALLOC (&global_info_obstack);
1450
 
1451
      if (node_g->statics_read != all_module_statics)
1452
        bitmap_and_compl (node_g->statics_not_read,
1453
                          all_module_statics,
1454
                          node_g->statics_read);
1455
 
1456
      if (node_g->statics_written
1457
          != all_module_statics)
1458
        bitmap_and_compl (node_g->statics_not_written,
1459
                          all_module_statics,
1460
                          node_g->statics_written);
1461
   }
1462
 
1463
  free (order);
1464
 
1465
  for (node = cgraph_nodes; node; node = node->next)
1466
    {
1467
      ipa_reference_vars_info_t node_info;
1468
      node_info = get_reference_vars_info (node);
1469
      /* Get rid of the aux information.  */
1470
 
1471
      if (node->aux)
1472
        {
1473
          free (node->aux);
1474
          node->aux = NULL;
1475
        }
1476
 
1477
      if (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE)
1478
        clean_function (node);
1479
      else if (node_info)
1480
        clean_function_local_data (node);
1481
    }
1482
  bitmap_obstack_release (&local_info_obstack);
1483
  return 0;
1484
}
1485
 
1486
 
1487
static bool
1488
gate_reference (void)
1489
{
1490
  return (flag_ipa_reference
1491
          /* Don't bother doing anything if the program has errors.  */
1492
          && !(errorcount || sorrycount));
1493
}
1494
 
1495
struct ipa_opt_pass_d pass_ipa_reference =
1496
{
1497
 {
1498
  IPA_PASS,
1499
  "static-var",                         /* name */
1500
  gate_reference,                       /* gate */
1501
  propagate,                            /* execute */
1502
  NULL,                                 /* sub */
1503
  NULL,                                 /* next */
1504
  0,                                     /* static_pass_number */
1505
  TV_IPA_REFERENCE,                     /* tv_id */
1506
  0,                                     /* properties_required */
1507
  0,                                     /* properties_provided */
1508
  0,                                     /* properties_destroyed */
1509
  0,                                     /* todo_flags_start */
1510
 
1511
 },
1512
 generate_summary,                      /* generate_summary */
1513
 ipa_reference_write_summary,           /* write_summary */
1514
 ipa_reference_read_summary,            /* read_summary */
1515
 NULL,                                  /* function_read_summary */
1516
 NULL,                                  /* stmt_fixup */
1517
 0,                                      /* TODOs */
1518
 NULL,                                  /* function_transform */
1519
 NULL                                   /* variable_transform */
1520
};
1521
 
1522
#include "gt-ipa-reference.h"

powered by: WebSVN 2.1.0

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