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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [ipa-reference.c] - Blame information for rev 825

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

Line No. Rev Author Line
1 38 julius
/* Callgraph based analysis of static variables.
2
   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
3
   Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 3, or (at your option) any later
10
version.
11
 
12
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GCC; see the file COPYING3.  If not see
19
<http://www.gnu.org/licenses/>.  */
20
 
21
/* This file gathers information about how variables whose scope is
22
   confined to the compilation unit are used.
23
 
24
   There are two categories of information produced by this pass:
25
 
26
   1) The addressable (TREE_ADDRESSABLE) bit and readonly
27
   (TREE_READONLY) bit associated with these variables is properly set
28
   based on scanning all of the code withing the compilation unit.
29
 
30
   2) The transitive call site specific clobber effects are computed
31
   for the variables whose scope is contained within this compilation
32
   unit.
33
 
34
   First each function and static variable initialization is analyzed
35
   to determine which local static variables are either read, written,
36
   or have their address taken.  Any local static that has its address
37
   taken is removed from consideration.  Once the local read and
38
   writes are determined, a transitive closure of this information is
39
   performed over the call graph to determine the worst case set of
40
   side effects of each call.  In later parts of the compiler, these
41
   local and global sets are examined to make the call clobbering less
42
   traumatic, promote some statics to registers, and improve aliasing
43
   information.
44
 
45
   Currently must be run after inlining decisions have been made since
46
   otherwise, the local sets will not contain information that is
47
   consistent with post inlined state.  The global sets are not prone
48
   to this problem since they are by definition transitive.
49
*/
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 "ggc.h"
62
#include "ipa-utils.h"
63
#include "ipa-reference.h"
64
#include "c-common.h"
65
#include "tree-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
 
73
/* This splay tree contains all of the static variables that are
74
   being considered by the compilation level alias analysis.  For
75
   module_at_a_time compilation, this is the set of static but not
76
   public variables.  Any variables that either have their address
77
   taken or participate in otherwise unsavory operations are deleted
78
   from this list.  */
79
static GTY((param1_is(int), param2_is(tree)))
80
     splay_tree reference_vars_to_consider;
81
 
82
/* This bitmap is used to knock out the module static variables whose
83
   addresses have been taken and passed around.  */
84
static bitmap module_statics_escape;
85
 
86
/* This bitmap is used to knock out the module static variables that
87
   are not readonly.  */
88
static bitmap module_statics_written;
89
 
90
/* A bit is set for every module static we are considering.  This is
91
   ored into the local info when asm code is found that clobbers all
92
   memory. */
93
static bitmap all_module_statics;
94
 
95
static struct pointer_set_t *visited_nodes;
96
 
97
static bitmap_obstack ipa_obstack;
98
 
99
enum initialization_status_t
100
{
101
  UNINITIALIZED,
102
  RUNNING,
103
  FINISHED
104
};
105
 
106
tree memory_identifier_string;
107
 
108
/* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
109
static inline ipa_reference_vars_info_t
110
get_reference_vars_info_from_cgraph (struct cgraph_node * node)
111
{
112
  return get_function_ann (node->decl)->reference_vars_info;
113
}
114
 
115
/* Get a bitmap that contains all of the locally referenced static
116
   variables for function FN.  */
117
static ipa_reference_local_vars_info_t
118
get_local_reference_vars_info (tree fn)
119
{
120
  ipa_reference_vars_info_t info = get_function_ann (fn)->reference_vars_info;
121
 
122
  if (info)
123
    return info->local;
124
  else
125
    /* This phase was not run.  */
126
    return NULL;
127
}
128
 
129
/* Get a bitmap that contains all of the globally referenced static
130
   variables for function FN.  */
131
 
132
static ipa_reference_global_vars_info_t
133
get_global_reference_vars_info (tree fn)
134
{
135
  ipa_reference_vars_info_t info = get_function_ann (fn)->reference_vars_info;
136
 
137
  if (info)
138
    return info->global;
139
  else
140
    /* This phase was not run.  */
141
    return NULL;
142
}
143
 
144
/* Return a bitmap indexed by VAR_DECL uid for the static variables
145
   that may be read locally by the execution of the function fn.
146
   Returns NULL if no data is available.  */
147
 
148
bitmap
149
ipa_reference_get_read_local (tree fn)
150
{
151
  ipa_reference_local_vars_info_t l = get_local_reference_vars_info (fn);
152
  if (l)
153
    return l->statics_read;
154
  else
155
    return NULL;
156
}
157
 
158
/* Return a bitmap indexed by VAR_DECL uid for the static variables
159
   that may be written locally by the execution of the function fn.
160
   Returns NULL if no data is available.  */
161
 
162
bitmap
163
ipa_reference_get_written_local (tree fn)
164
{
165
  ipa_reference_local_vars_info_t l = get_local_reference_vars_info (fn);
166
  if (l)
167
    return l->statics_written;
168
  else
169
    return NULL;
170
}
171
 
172
/* Return a bitmap indexed by VAR_DECL uid for the static variables
173
   that are read during the execution of the function FN.  Returns
174
   NULL if no data is available.  */
175
 
176
bitmap
177
ipa_reference_get_read_global (tree fn)
178
{
179
  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
180
  if (g)
181
    return g->statics_read;
182
  else
183
    return NULL;
184
}
185
 
186
/* Return a bitmap indexed by VAR_DECL uid for the static variables
187
   that are written during the execution of the function FN.  Note
188
   that variables written may or may not be read during the function
189
   call.  Returns NULL if no data is available.  */
190
 
191
bitmap
192
ipa_reference_get_written_global (tree fn)
193
{
194
  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
195
  if (g)
196
    return g->statics_written;
197
  else
198
    return NULL;
199
}
200
 
201
/* Return a bitmap indexed by_DECL_UID uid for the static variables
202
   that are not read during the execution of the function FN.  Returns
203
   NULL if no data is available.  */
204
 
205
bitmap
206
ipa_reference_get_not_read_global (tree fn)
207
{
208
  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
209
  if (g)
210
    return g->statics_not_read;
211
  else
212
    return NULL;
213
}
214
 
215
/* Return a bitmap indexed by DECL_UID uid for the static variables
216
   that are not written during the execution of the function FN.  Note
217
   that variables written may or may not be read during the function
218
   call.  Returns NULL if no data is available.  */
219
 
220
bitmap
221
ipa_reference_get_not_written_global (tree fn)
222
{
223
  ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
224
  if (g)
225
    return g->statics_not_written;
226
  else
227
    return NULL;
228
}
229
 
230
 
231
 
232
/* Add VAR to all_module_statics and the two
233
   reference_vars_to_consider* sets.  */
234
 
235
static inline void
236
add_static_var (tree var)
237
{
238
  int uid = DECL_UID (var);
239
  if (!bitmap_bit_p (all_module_statics, uid))
240
    {
241
      splay_tree_insert (reference_vars_to_consider,
242
                         uid, (splay_tree_value)var);
243
      bitmap_set_bit (all_module_statics, uid);
244
    }
245
}
246
 
247
/* Return true if the variable T is the right kind of static variable to
248
   perform compilation unit scope escape analysis.  */
249
 
250
static inline bool
251
has_proper_scope_for_analysis (tree t)
252
{
253
  /* If the variable has the "used" attribute, treat it as if it had a
254
     been touched by the devil.  */
255
  if (lookup_attribute ("used", DECL_ATTRIBUTES (t)))
256
    return false;
257
 
258
  /* Do not want to do anything with volatile except mark any
259
     function that uses one to be not const or pure.  */
260
  if (TREE_THIS_VOLATILE (t))
261
    return false;
262
 
263
  /* Do not care about a local automatic that is not static.  */
264
  if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
265
    return false;
266
 
267
  if (DECL_EXTERNAL (t) || TREE_PUBLIC (t))
268
    return false;
269
 
270
  /* This is a variable we care about.  Check if we have seen it
271
     before, and if not add it the set of variables we care about.  */
272
  if (!bitmap_bit_p (all_module_statics, DECL_UID (t)))
273
    add_static_var (t);
274
 
275
  return true;
276
}
277
 
278
/* If T is a VAR_DECL for a static that we are interested in, add the
279
   uid to the bitmap.  */
280
 
281
static void
282
check_operand (ipa_reference_local_vars_info_t local,
283
               tree t, bool checking_write)
284
{
285
  if (!t) return;
286
 
287
  if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL)
288
      && (has_proper_scope_for_analysis (t)))
289
    {
290
      if (checking_write)
291
        {
292
          if (local)
293
            bitmap_set_bit (local->statics_written, DECL_UID (t));
294
          /* Mark the write so we can tell which statics are
295
             readonly.  */
296
          bitmap_set_bit (module_statics_written, DECL_UID (t));
297
        }
298
      else if (local)
299
        bitmap_set_bit (local->statics_read, DECL_UID (t));
300
    }
301
}
302
 
303
/* Examine tree T for references to static variables. All internal
304
   references like array references or indirect references are added
305
   to the READ_BM. Direct references are added to either READ_BM or
306
   WRITE_BM depending on the value of CHECKING_WRITE.   */
307
 
308
static void
309
check_tree (ipa_reference_local_vars_info_t local, tree t, bool checking_write)
310
{
311
  if ((TREE_CODE (t) == EXC_PTR_EXPR) || (TREE_CODE (t) == FILTER_EXPR))
312
    return;
313
 
314
  while (TREE_CODE (t) == REALPART_EXPR
315
         || TREE_CODE (t) == IMAGPART_EXPR
316
         || handled_component_p (t))
317
    {
318
      if (TREE_CODE (t) == ARRAY_REF)
319
        check_operand (local, TREE_OPERAND (t, 1), false);
320
      t = TREE_OPERAND (t, 0);
321
    }
322
 
323
  /* The bottom of an indirect reference can only be read, not
324
     written.  So just recurse and whatever we find, check it against
325
     the read bitmaps.  */
326
 
327
  /*  if (INDIRECT_REF_P (t) || TREE_CODE (t) == MEM_REF) */
328
  /* FIXME when we have array_ref's of pointers.  */
329
  if (INDIRECT_REF_P (t))
330
    check_tree (local, TREE_OPERAND (t, 0), false);
331
 
332
  if (SSA_VAR_P (t))
333
    check_operand (local, t, checking_write);
334
}
335
 
336
/* Scan tree T to see if there are any addresses taken in within T.  */
337
 
338
static void
339
look_for_address_of (tree t)
340
{
341
  if (TREE_CODE (t) == ADDR_EXPR)
342
    {
343
      tree x = get_base_var (t);
344
      if (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == FUNCTION_DECL)
345
        if (has_proper_scope_for_analysis (x))
346
          bitmap_set_bit (module_statics_escape, DECL_UID (x));
347
    }
348
}
349
 
350
/* Check to see if T is a read or address of operation on a static var
351
   we are interested in analyzing.  LOCAL is passed in to get access
352
   to its bit vectors.  Local is NULL if this is called from a static
353
   initializer.  */
354
 
355
static void
356
check_rhs_var (ipa_reference_local_vars_info_t local, tree t)
357
{
358
  look_for_address_of (t);
359
 
360
  if (local == NULL)
361
    return;
362
 
363
  check_tree(local, t, false);
364
}
365
 
366
/* Check to see if T is an assignment to a static var we are
367
   interested in analyzing.  LOCAL is passed in to get access to its bit
368
   vectors.  */
369
 
370
static void
371
check_lhs_var (ipa_reference_local_vars_info_t local, tree t)
372
{
373
  if (local == NULL)
374
    return;
375
 
376
  check_tree(local, t, true);
377
}
378
 
379
/* This is a scaled down version of get_asm_expr_operands from
380
   tree_ssa_operands.c.  The version there runs much later and assumes
381
   that aliasing information is already available. Here we are just
382
   trying to find if the set of inputs and outputs contain references
383
   or address of operations to local static variables.  FN is the
384
   function being analyzed and STMT is the actual asm statement.  */
385
 
386
static void
387
get_asm_expr_operands (ipa_reference_local_vars_info_t local, tree stmt)
388
{
389
  int noutputs = list_length (ASM_OUTPUTS (stmt));
390
  const char **oconstraints
391
    = (const char **) alloca ((noutputs) * sizeof (const char *));
392
  int i;
393
  tree link;
394
  const char *constraint;
395
  bool allows_mem, allows_reg, is_inout;
396
 
397
  for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
398
    {
399
      oconstraints[i] = constraint
400
        = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
401
      parse_output_constraint (&constraint, i, 0, 0,
402
                               &allows_mem, &allows_reg, &is_inout);
403
 
404
      check_lhs_var (local, TREE_VALUE (link));
405
    }
406
 
407
  for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
408
    {
409
      constraint
410
        = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
411
      parse_input_constraint (&constraint, 0, 0, noutputs, 0,
412
                              oconstraints, &allows_mem, &allows_reg);
413
 
414
      check_rhs_var (local, TREE_VALUE (link));
415
    }
416
 
417
  for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
418
    if (simple_cst_equal(TREE_VALUE (link), memory_identifier_string) == 1)
419
      {
420
        /* Abandon all hope, ye who enter here. */
421
        local->calls_read_all = true;
422
        local->calls_write_all = true;
423
      }
424
}
425
 
426
/* Check the parameters of a function call from CALLER to CALL_EXPR to
427
   see if any of them are static vars.  Also check to see if this is
428
   either an indirect call, a call outside the compilation unit, or
429
   has special attributes that effect the clobbers.  The caller
430
   parameter is the tree node for the caller and the second operand is
431
   the tree node for the entire call expression.  */
432
 
433
static void
434
check_call (ipa_reference_local_vars_info_t local, tree call_expr)
435
{
436
  int flags = call_expr_flags (call_expr);
437
  tree operand_list = TREE_OPERAND (call_expr, 1);
438
  tree operand;
439
  tree callee_t = get_callee_fndecl (call_expr);
440
  enum availability avail = AVAIL_NOT_AVAILABLE;
441
 
442
  for (operand = operand_list;
443
       operand != NULL_TREE;
444
       operand = TREE_CHAIN (operand))
445
    {
446
      tree argument = TREE_VALUE (operand);
447
      check_rhs_var (local, argument);
448
    }
449
 
450
  if (callee_t)
451
    {
452
      struct cgraph_node* callee = cgraph_node(callee_t);
453
      avail = cgraph_function_body_availability (callee);
454
    }
455
 
456
  if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
457
    if (local)
458
      {
459
        if (flags & ECF_PURE)
460
          local->calls_read_all = true;
461
        else
462
          {
463
            local->calls_read_all = true;
464
            local->calls_write_all = true;
465
          }
466
      }
467
}
468
 
469
/* TP is the part of the tree currently under the microscope.
470
   WALK_SUBTREES is part of the walk_tree api but is unused here.
471
   DATA is cgraph_node of the function being walked.  */
472
 
473
/* FIXME: When this is converted to run over SSA form, this code
474
   should be converted to use the operand scanner.  */
475
 
476
static tree
477
scan_for_static_refs (tree *tp,
478
                      int *walk_subtrees,
479
                      void *data)
480
{
481
  struct cgraph_node *fn = data;
482
  tree t = *tp;
483
  ipa_reference_local_vars_info_t local = NULL;
484
  if (fn)
485
    local = get_reference_vars_info_from_cgraph (fn)->local;
486
 
487
  switch (TREE_CODE (t))
488
    {
489
    case VAR_DECL:
490
      if (DECL_INITIAL (t))
491
        walk_tree (&DECL_INITIAL (t), scan_for_static_refs, fn, visited_nodes);
492
      *walk_subtrees = 0;
493
      break;
494
 
495
    case MODIFY_EXPR:
496
      {
497
        /* First look on the lhs and see what variable is stored to */
498
        tree lhs = TREE_OPERAND (t, 0);
499
        tree rhs = TREE_OPERAND (t, 1);
500
        check_lhs_var (local, lhs);
501
 
502
        /* For the purposes of figuring out what the cast affects */
503
 
504
        /* Next check the operands on the rhs to see if they are ok. */
505
        switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
506
          {
507
          case tcc_binary:
508
          case tcc_comparison:
509
            {
510
              tree op0 = TREE_OPERAND (rhs, 0);
511
              tree op1 = TREE_OPERAND (rhs, 1);
512
              check_rhs_var (local, op0);
513
              check_rhs_var (local, op1);
514
            }
515
            break;
516
          case tcc_unary:
517
            {
518
              tree op0 = TREE_OPERAND (rhs, 0);
519
              check_rhs_var (local, op0);
520
            }
521
 
522
            break;
523
          case tcc_reference:
524
            check_rhs_var (local, rhs);
525
            break;
526
          case tcc_declaration:
527
            check_rhs_var (local, rhs);
528
            break;
529
          case tcc_expression:
530
            switch (TREE_CODE (rhs))
531
              {
532
              case ADDR_EXPR:
533
                check_rhs_var (local, rhs);
534
                break;
535
              case CALL_EXPR:
536
                check_call (local, rhs);
537
                break;
538
              default:
539
                break;
540
              }
541
            break;
542
          default:
543
            break;
544
          }
545
        *walk_subtrees = 0;
546
      }
547
      break;
548
 
549
    case ADDR_EXPR:
550
      /* This case is here to find addresses on rhs of constructors in
551
         decl_initial of static variables. */
552
      check_rhs_var (local, t);
553
      *walk_subtrees = 0;
554
      break;
555
 
556
    case LABEL_EXPR:
557
      if (DECL_NONLOCAL (TREE_OPERAND (t, 0)))
558
        {
559
          /* Target of long jump. */
560
          local->calls_read_all = true;
561
          local->calls_write_all = true;
562
        }
563
      break;
564
 
565
    case CALL_EXPR:
566
      check_call (local, t);
567
      *walk_subtrees = 0;
568
      break;
569
 
570
    case ASM_EXPR:
571
      get_asm_expr_operands (local, t);
572
      *walk_subtrees = 0;
573
      break;
574
 
575
    default:
576
      break;
577
    }
578
  return NULL;
579
}
580
 
581
 
582
/* Lookup the tree node for the static variable that has UID.  */
583
static tree
584
get_static_decl (int index)
585
{
586
  splay_tree_node stn =
587
    splay_tree_lookup (reference_vars_to_consider, index);
588
  if (stn)
589
    return (tree)stn->value;
590
  return NULL;
591
}
592
 
593
/* Lookup the tree node for the static variable that has UID and
594
   convert the name to a string for debugging.  */
595
 
596
static const char *
597
get_static_name (int index)
598
{
599
  splay_tree_node stn =
600
    splay_tree_lookup (reference_vars_to_consider, index);
601
  if (stn)
602
    return lang_hooks.decl_printable_name ((tree)(stn->value), 2);
603
  return NULL;
604
}
605
 
606
/* Or in all of the bits from every callee into X, the caller's, bit
607
   vector.  There are several cases to check to avoid the sparse
608
   bitmap oring.  */
609
 
610
static void
611
propagate_bits (struct cgraph_node *x)
612
{
613
  ipa_reference_vars_info_t x_info = get_reference_vars_info_from_cgraph (x);
614
  ipa_reference_global_vars_info_t x_global = x_info->global;
615
 
616
  struct cgraph_edge *e;
617
  for (e = x->callees; e; e = e->next_callee)
618
    {
619
      struct cgraph_node *y = e->callee;
620
 
621
      /* Only look at the master nodes and skip external nodes.  */
622
      y = cgraph_master_clone (y);
623
      if (y)
624
        {
625
          if (get_reference_vars_info_from_cgraph (y))
626
            {
627
              ipa_reference_vars_info_t y_info = get_reference_vars_info_from_cgraph (y);
628
              ipa_reference_global_vars_info_t y_global = y_info->global;
629
 
630
              if (x_global->statics_read
631
                  != all_module_statics)
632
                {
633
                  if (y_global->statics_read
634
                      == all_module_statics)
635
                    {
636
                      BITMAP_FREE (x_global->statics_read);
637
                      x_global->statics_read
638
                        = all_module_statics;
639
                    }
640
                  /* Skip bitmaps that are pointer equal to node's bitmap
641
                     (no reason to spin within the cycle).  */
642
                  else if (x_global->statics_read
643
                           != y_global->statics_read)
644
                    bitmap_ior_into (x_global->statics_read,
645
                                     y_global->statics_read);
646
                }
647
 
648
              if (x_global->statics_written
649
                  != all_module_statics)
650
                {
651
                  if (y_global->statics_written
652
                      == all_module_statics)
653
                    {
654
                      BITMAP_FREE (x_global->statics_written);
655
                      x_global->statics_written
656
                        = all_module_statics;
657
                    }
658
                  /* Skip bitmaps that are pointer equal to node's bitmap
659
                     (no reason to spin within the cycle).  */
660
                  else if (x_global->statics_written
661
                           != y_global->statics_written)
662
                    bitmap_ior_into (x_global->statics_written,
663
                                     y_global->statics_written);
664
                }
665
            }
666
          else
667
            {
668
              gcc_unreachable ();
669
            }
670
        }
671
    }
672
}
673
 
674
/* Look at all of the callees of X to see which ones represent inlined
675
   calls.  For each of these callees, merge their local info into
676
   TARGET and check their children recursively.
677
 
678
   This function goes away when Jan changes the inliner and IPA
679
   analysis so that this is not run between the time when inlining
680
   decisions are made and when the inlining actually occurs.  */
681
 
682
static void
683
merge_callee_local_info (struct cgraph_node *target,
684
                         struct cgraph_node *x)
685
{
686
  struct cgraph_edge *e;
687
  ipa_reference_local_vars_info_t x_l =
688
    get_reference_vars_info_from_cgraph (target)->local;
689
 
690
  /* Make the world safe for tail recursion.  */
691
  struct ipa_dfs_info *node_info = x->aux;
692
 
693
  if (node_info->aux)
694
    return;
695
 
696
  node_info->aux = x;
697
 
698
  for (e = x->callees; e; e = e->next_callee)
699
    {
700
      struct cgraph_node *y = e->callee;
701
      if (y->global.inlined_to)
702
        {
703
          ipa_reference_vars_info_t y_info;
704
          ipa_reference_local_vars_info_t y_l;
705
          struct cgraph_node* orig_y = y;
706
 
707
          y = cgraph_master_clone (y);
708
          if (y)
709
            {
710
              y_info = get_reference_vars_info_from_cgraph (y);
711
              y_l = y_info->local;
712
              if (x_l != y_l)
713
                {
714
                  bitmap_ior_into (x_l->statics_read,
715
                                   y_l->statics_read);
716
                  bitmap_ior_into (x_l->statics_written,
717
                                   y_l->statics_written);
718
                }
719
              x_l->calls_read_all |= y_l->calls_read_all;
720
              x_l->calls_write_all |= y_l->calls_write_all;
721
              merge_callee_local_info (target, y);
722
            }
723
          else
724
            {
725
              fprintf(stderr, "suspect inlining of ");
726
              dump_cgraph_node (stderr, orig_y);
727
              fprintf(stderr, "\ninto ");
728
              dump_cgraph_node (stderr, target);
729
              dump_cgraph (stderr);
730
              gcc_assert(false);
731
            }
732
        }
733
    }
734
 
735
  node_info->aux = NULL;
736
}
737
 
738
/* The init routine for analyzing global static variable usage.  See
739
   comments at top for description.  */
740
static void
741
ipa_init (void)
742
{
743
  struct cgraph_node *node;
744
  memory_identifier_string = build_string(7, "memory");
745
 
746
  reference_vars_to_consider =
747
    splay_tree_new_ggc (splay_tree_compare_ints);
748
 
749
  bitmap_obstack_initialize (&ipa_obstack);
750
  module_statics_escape = BITMAP_ALLOC (&ipa_obstack);
751
  module_statics_written = BITMAP_ALLOC (&ipa_obstack);
752
  all_module_statics = BITMAP_ALLOC (&ipa_obstack);
753
 
754
  /* This will add NODE->DECL to the splay trees.  */
755
  for (node = cgraph_nodes; node; node = node->next)
756
    has_proper_scope_for_analysis (node->decl);
757
 
758
  /* There are some shared nodes, in particular the initializers on
759
     static declarations.  We do not need to scan them more than once
760
     since all we would be interested in are the addressof
761
     operations.  */
762
  visited_nodes = pointer_set_create ();
763
}
764
 
765
/* Check out the rhs of a static or global initialization VNODE to see
766
   if any of them contain addressof operations.  Note that some of
767
   these variables may  not even be referenced in the code in this
768
   compilation unit but their right hand sides may contain references
769
   to variables defined within this unit.  */
770
 
771
static void
772
analyze_variable (struct cgraph_varpool_node *vnode)
773
{
774
  tree global = vnode->decl;
775
  if (TREE_CODE (global) == VAR_DECL)
776
    {
777
      if (DECL_INITIAL (global))
778
        walk_tree (&DECL_INITIAL (global), scan_for_static_refs,
779
                   NULL, visited_nodes);
780
    }
781
  else gcc_unreachable ();
782
}
783
 
784
/* This is the main routine for finding the reference patterns for
785
   global variables within a function FN.  */
786
 
787
static void
788
analyze_function (struct cgraph_node *fn)
789
{
790
  ipa_reference_vars_info_t info
791
    = xcalloc (1, sizeof (struct ipa_reference_vars_info_d));
792
  ipa_reference_local_vars_info_t l
793
    = xcalloc (1, sizeof (struct ipa_reference_local_vars_info_d));
794
  tree decl = fn->decl;
795
 
796
  /* Add the info to the tree's annotation.  */
797
  get_function_ann (fn->decl)->reference_vars_info = info;
798
 
799
  info->local = l;
800
  l->statics_read = BITMAP_ALLOC (&ipa_obstack);
801
  l->statics_written = BITMAP_ALLOC (&ipa_obstack);
802
 
803
  if (dump_file)
804
    fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn));
805
 
806
  {
807
    struct function *this_cfun = DECL_STRUCT_FUNCTION (decl);
808
    basic_block this_block;
809
 
810
    FOR_EACH_BB_FN (this_block, this_cfun)
811
      {
812
        block_stmt_iterator bsi;
813
        for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
814
          walk_tree (bsi_stmt_ptr (bsi), scan_for_static_refs,
815
                     fn, visited_nodes);
816
      }
817
  }
818
 
819
  /* There may be const decls with interesting right hand sides.  */
820
  if (DECL_STRUCT_FUNCTION (decl))
821
    {
822
      tree step;
823
      for (step = DECL_STRUCT_FUNCTION (decl)->unexpanded_var_list;
824
           step;
825
           step = TREE_CHAIN (step))
826
        {
827
          tree var = TREE_VALUE (step);
828
          if (TREE_CODE (var) == VAR_DECL
829
              && DECL_INITIAL (var)
830
              && !TREE_STATIC (var))
831
            walk_tree (&DECL_INITIAL (var), scan_for_static_refs,
832
                       fn, visited_nodes);
833
        }
834
    }
835
}
836
 
837
/* If FN is avail == AVAIL_OVERWRITABLE, replace the effects bit
838
   vectors with worst case bit vectors.  We had to analyze it above to
839
   find out if it took the address of any statics. However, now that
840
   we know that, we can get rid of all of the other side effects.  */
841
 
842
static void
843
clean_function (struct cgraph_node *fn)
844
{
845
  ipa_reference_vars_info_t info = get_reference_vars_info_from_cgraph (fn);
846
  ipa_reference_local_vars_info_t l = info->local;
847
  ipa_reference_global_vars_info_t g = info->global;
848
 
849
  if (l)
850
    {
851
      if (l->statics_read
852
          && l->statics_read != all_module_statics)
853
        BITMAP_FREE (l->statics_read);
854
      if (l->statics_written
855
          &&l->statics_written != all_module_statics)
856
        BITMAP_FREE (l->statics_written);
857
      free (l);
858
    }
859
 
860
  if (g)
861
    {
862
      if (g->statics_read
863
          && g->statics_read != all_module_statics)
864
        BITMAP_FREE (g->statics_read);
865
 
866
      if (g->statics_written
867
          && g->statics_written != all_module_statics)
868
        BITMAP_FREE (g->statics_written);
869
 
870
      if (g->statics_not_read
871
          && g->statics_not_read != all_module_statics)
872
        BITMAP_FREE (g->statics_not_read);
873
 
874
      if (g->statics_not_written
875
          && g->statics_not_written != all_module_statics)
876
        BITMAP_FREE (g->statics_not_written);
877
      free (g);
878
    }
879
 
880
 
881
  free (get_function_ann (fn->decl)->reference_vars_info);
882
  get_function_ann (fn->decl)->reference_vars_info = NULL;
883
}
884
 
885
 
886
/* Produce the global information by preforming a transitive closure
887
   on the local information that was produced by ipa_analyze_function
888
   and ipa_analyze_variable.  */
889
 
890
static unsigned int
891
static_execute (void)
892
{
893
  struct cgraph_node *node;
894
  struct cgraph_varpool_node *vnode;
895
  struct cgraph_node *w;
896
  struct cgraph_node **order =
897
    xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
898
  int order_pos = order_pos = ipa_utils_reduced_inorder (order, false, true);
899
  int i;
900
 
901
  ipa_init ();
902
 
903
  /* Process all of the variables first.  */
904
  for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed)
905
    analyze_variable (vnode);
906
 
907
  /* Process all of the functions next.
908
 
909
     We do not want to process any of the clones so we check that this
910
     is a master clone.  However, we do need to process any
911
     AVAIL_OVERWRITABLE functions (these are never clones) because
912
     they may cause a static variable to escape.  The code that can
913
     overwrite such a function cannot access the statics because it
914
     would not be in the same compilation unit.  When the analysis is
915
     finished, the computed information of these AVAIL_OVERWRITABLE is
916
     replaced with worst case info.
917
  */
918
  for (node = cgraph_nodes; node; node = node->next)
919
    if (node->analyzed
920
        && (cgraph_is_master_clone (node)
921
            || (cgraph_function_body_availability (node)
922
                == AVAIL_OVERWRITABLE)))
923
      analyze_function (node);
924
 
925
  pointer_set_destroy (visited_nodes);
926
  visited_nodes = NULL;
927
  if (dump_file)
928
    dump_cgraph (dump_file);
929
 
930
  /* Prune out the variables that were found to behave badly
931
     (i.e. have their address taken).  */
932
  {
933
    unsigned int index;
934
    bitmap_iterator bi;
935
    bitmap module_statics_readonly = BITMAP_ALLOC (&ipa_obstack);
936
    bitmap module_statics_const = BITMAP_ALLOC (&ipa_obstack);
937
    bitmap bm_temp = BITMAP_ALLOC (&ipa_obstack);
938
 
939
    EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi)
940
      {
941
        splay_tree_remove (reference_vars_to_consider, index);
942
      }
943
 
944
    bitmap_and_compl_into (all_module_statics,
945
                           module_statics_escape);
946
 
947
    bitmap_and_compl (module_statics_readonly, all_module_statics,
948
                      module_statics_written);
949
 
950
    /* If the address is not taken, we can unset the addressable bit
951
       on this variable.  */
952
    EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
953
      {
954
        tree var = get_static_decl (index);
955
        TREE_ADDRESSABLE (var) = 0;
956
        if (dump_file)
957
          fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n",
958
                   get_static_name (index));
959
      }
960
 
961
    /* If the variable is never written, we can set the TREE_READONLY
962
       flag.  Additionally if it has a DECL_INITIAL that is made up of
963
       constants we can treat the entire global as a constant.  */
964
 
965
    bitmap_and_compl (module_statics_readonly, all_module_statics,
966
                      module_statics_written);
967
    EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi)
968
      {
969
        tree var = get_static_decl (index);
970
 
971
        /* Readonly on a function decl is very different from the
972
           variable.  */
973
        if (TREE_CODE (var) == FUNCTION_DECL)
974
          continue;
975
 
976
        /* Ignore variables in named sections - changing TREE_READONLY
977
           changes the section flags, potentially causing conflicts with
978
           other variables in the same named section.  */
979
        if (DECL_SECTION_NAME (var) == NULL_TREE)
980
          {
981
            TREE_READONLY (var) = 1;
982
            if (dump_file)
983
              fprintf (dump_file, "read-only var %s\n",
984
                       get_static_name (index));
985
          }
986
        if (DECL_INITIAL (var)
987
            && is_gimple_min_invariant (DECL_INITIAL (var)))
988
          {
989
            bitmap_set_bit (module_statics_const, index);
990
            if (dump_file)
991
              fprintf (dump_file, "read-only constant %s\n",
992
                       get_static_name (index));
993
          }
994
      }
995
 
996
    BITMAP_FREE(module_statics_escape);
997
    BITMAP_FREE(module_statics_written);
998
 
999
    if (dump_file)
1000
      EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
1001
        {
1002
          fprintf (dump_file, "\nPromotable global:%s",
1003
                   get_static_name (index));
1004
        }
1005
 
1006
    for (i = 0; i < order_pos; i++ )
1007
      {
1008
        ipa_reference_local_vars_info_t l;
1009
        node = order[i];
1010
        l = get_reference_vars_info_from_cgraph (node)->local;
1011
 
1012
        /* Any variables that are not in all_module_statics are
1013
           removed from the local maps.  This will include all of the
1014
           variables that were found to escape in the function
1015
           scanning.  */
1016
        bitmap_and_into (l->statics_read,
1017
                         all_module_statics);
1018
        bitmap_and_into (l->statics_written,
1019
                         all_module_statics);
1020
      }
1021
 
1022
    BITMAP_FREE(module_statics_readonly);
1023
    BITMAP_FREE(module_statics_const);
1024
    BITMAP_FREE(bm_temp);
1025
  }
1026
 
1027
  if (dump_file)
1028
    {
1029
      for (i = 0; i < order_pos; i++ )
1030
        {
1031
          unsigned int index;
1032
          ipa_reference_local_vars_info_t l;
1033
          bitmap_iterator bi;
1034
 
1035
          node = order[i];
1036
          l = get_reference_vars_info_from_cgraph (node)->local;
1037
          fprintf (dump_file,
1038
                   "\nFunction name:%s/%i:",
1039
                   cgraph_node_name (node), node->uid);
1040
          fprintf (dump_file, "\n  locals read: ");
1041
          EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
1042
                                    0, index, bi)
1043
            {
1044
              fprintf (dump_file, "%s ",
1045
                       get_static_name (index));
1046
            }
1047
          fprintf (dump_file, "\n  locals written: ");
1048
          EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
1049
                                    0, index, bi)
1050
            {
1051
              fprintf(dump_file, "%s ",
1052
                      get_static_name (index));
1053
            }
1054
        }
1055
    }
1056
 
1057
  /* Propagate the local information thru the call graph to produce
1058
     the global information.  All the nodes within a cycle will have
1059
     the same info so we collapse cycles first.  Then we can do the
1060
     propagation in one pass from the leaves to the roots.  */
1061
  order_pos = ipa_utils_reduced_inorder (order, true, true);
1062
  if (dump_file)
1063
    ipa_utils_print_order(dump_file, "reduced", order, order_pos);
1064
 
1065
  for (i = 0; i < order_pos; i++ )
1066
    {
1067
      ipa_reference_vars_info_t node_info;
1068
      ipa_reference_global_vars_info_t node_g =
1069
        xcalloc (1, sizeof (struct ipa_reference_global_vars_info_d));
1070
      ipa_reference_local_vars_info_t node_l;
1071
 
1072
      bool read_all;
1073
      bool write_all;
1074
      struct ipa_dfs_info * w_info;
1075
 
1076
      node = order[i];
1077
      node_info = get_reference_vars_info_from_cgraph (node);
1078
      if (!node_info)
1079
        {
1080
          dump_cgraph_node (stderr, node);
1081
          dump_cgraph (stderr);
1082
          gcc_unreachable ();
1083
        }
1084
 
1085
      node_info->global = node_g;
1086
      node_l = node_info->local;
1087
 
1088
      read_all = node_l->calls_read_all;
1089
      write_all = node_l->calls_write_all;
1090
 
1091
      /* If any node in a cycle is calls_read_all or calls_write_all
1092
         they all are. */
1093
      w_info = node->aux;
1094
      w = w_info->next_cycle;
1095
      while (w)
1096
        {
1097
          ipa_reference_local_vars_info_t w_l =
1098
            get_reference_vars_info_from_cgraph (w)->local;
1099
          read_all |= w_l->calls_read_all;
1100
          write_all |= w_l->calls_write_all;
1101
 
1102
          w_info = w->aux;
1103
          w = w_info->next_cycle;
1104
        }
1105
 
1106
      /* Initialized the bitmaps for the reduced nodes */
1107
      if (read_all)
1108
        node_g->statics_read = all_module_statics;
1109
      else
1110
        {
1111
          node_g->statics_read = BITMAP_ALLOC (&ipa_obstack);
1112
          bitmap_copy (node_g->statics_read,
1113
                       node_l->statics_read);
1114
        }
1115
 
1116
      if (write_all)
1117
        node_g->statics_written = all_module_statics;
1118
      else
1119
        {
1120
          node_g->statics_written = BITMAP_ALLOC (&ipa_obstack);
1121
          bitmap_copy (node_g->statics_written,
1122
                       node_l->statics_written);
1123
        }
1124
 
1125
      w_info = node->aux;
1126
      w = w_info->next_cycle;
1127
      while (w)
1128
        {
1129
          ipa_reference_vars_info_t w_ri =
1130
            get_reference_vars_info_from_cgraph (w);
1131
          ipa_reference_local_vars_info_t w_l = w_ri->local;
1132
 
1133
          /* All nodes within a cycle share the same global info bitmaps.  */
1134
          w_ri->global = node_g;
1135
 
1136
          /* These global bitmaps are initialized from the local info
1137
             of all of the nodes in the region.  However there is no
1138
             need to do any work if the bitmaps were set to
1139
             all_module_statics.  */
1140
          if (!read_all)
1141
            bitmap_ior_into (node_g->statics_read,
1142
                             w_l->statics_read);
1143
          if (!write_all)
1144
            bitmap_ior_into (node_g->statics_written,
1145
                             w_l->statics_written);
1146
          w_info = w->aux;
1147
          w = w_info->next_cycle;
1148
        }
1149
 
1150
      w = node;
1151
      while (w)
1152
        {
1153
          propagate_bits (w);
1154
          w_info = w->aux;
1155
          w = w_info->next_cycle;
1156
        }
1157
    }
1158
 
1159
  /* Need to fix up the local information sets.  The information that
1160
     has been gathered so far is preinlining.  However, the
1161
     compilation will progress post inlining so the local sets for the
1162
     inlined calls need to be merged into the callers.  Note that the
1163
     local sets are not shared between all of the nodes in a cycle so
1164
     those nodes in the cycle must be processed explicitly.  */
1165
  for (i = 0; i < order_pos; i++ )
1166
    {
1167
      struct ipa_dfs_info * w_info;
1168
      node = order[i];
1169
      merge_callee_local_info (node, node);
1170
 
1171
      w_info = node->aux;
1172
      w = w_info->next_cycle;
1173
      while (w)
1174
        {
1175
          merge_callee_local_info (w, w);
1176
          w_info = w->aux;
1177
          w = w_info->next_cycle;
1178
        }
1179
    }
1180
 
1181
  if (dump_file)
1182
    {
1183
      for (i = 0; i < order_pos; i++ )
1184
        {
1185
          ipa_reference_vars_info_t node_info;
1186
          ipa_reference_global_vars_info_t node_g;
1187
          ipa_reference_local_vars_info_t node_l;
1188
          unsigned int index;
1189
          bitmap_iterator bi;
1190
          struct ipa_dfs_info * w_info;
1191
 
1192
          node = order[i];
1193
          node_info = get_reference_vars_info_from_cgraph (node);
1194
          node_g = node_info->global;
1195
          node_l = node_info->local;
1196
          fprintf (dump_file,
1197
                   "\nFunction name:%s/%i:",
1198
                   cgraph_node_name (node), node->uid);
1199
          fprintf (dump_file, "\n  locals read: ");
1200
          EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read,
1201
                                    0, index, bi)
1202
            {
1203
              fprintf (dump_file, "%s ",
1204
                       get_static_name (index));
1205
            }
1206
          fprintf (dump_file, "\n  locals written: ");
1207
          EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written,
1208
                                    0, index, bi)
1209
            {
1210
              fprintf(dump_file, "%s ",
1211
                      get_static_name (index));
1212
            }
1213
 
1214
          w_info = node->aux;
1215
          w = w_info->next_cycle;
1216
          while (w)
1217
            {
1218
              ipa_reference_vars_info_t w_ri =
1219
                get_reference_vars_info_from_cgraph (w);
1220
              ipa_reference_local_vars_info_t w_l = w_ri->local;
1221
              fprintf (dump_file, "\n  next cycle: %s/%i ",
1222
                       cgraph_node_name (w), w->uid);
1223
              fprintf (dump_file, "\n    locals read: ");
1224
              EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read,
1225
                                        0, index, bi)
1226
                {
1227
                  fprintf (dump_file, "%s ",
1228
                           get_static_name (index));
1229
                }
1230
 
1231
              fprintf (dump_file, "\n    locals written: ");
1232
              EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written,
1233
                                        0, index, bi)
1234
                {
1235
                  fprintf(dump_file, "%s ",
1236
                          get_static_name (index));
1237
                }
1238
 
1239
 
1240
              w_info = w->aux;
1241
              w = w_info->next_cycle;
1242
            }
1243
          fprintf (dump_file, "\n  globals read: ");
1244
          EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read,
1245
                                    0, index, bi)
1246
            {
1247
              fprintf (dump_file, "%s ",
1248
                       get_static_name (index));
1249
            }
1250
          fprintf (dump_file, "\n  globals written: ");
1251
          EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written,
1252
                                    0, index, bi)
1253
            {
1254
              fprintf (dump_file, "%s ",
1255
                       get_static_name (index));
1256
            }
1257
        }
1258
    }
1259
 
1260
  /* Cleanup. */
1261
  for (i = 0; i < order_pos; i++ )
1262
    {
1263
      ipa_reference_vars_info_t node_info;
1264
      ipa_reference_global_vars_info_t node_g;
1265
      node = order[i];
1266
      node_info = get_reference_vars_info_from_cgraph (node);
1267
      node_g = node_info->global;
1268
 
1269
      /* Create the complimentary sets.  These are more useful for
1270
         certain apis.  */
1271
      node_g->statics_not_read = BITMAP_ALLOC (&ipa_obstack);
1272
      node_g->statics_not_written = BITMAP_ALLOC (&ipa_obstack);
1273
 
1274
      if (node_g->statics_read != all_module_statics)
1275
        {
1276
          bitmap_and_compl (node_g->statics_not_read,
1277
                            all_module_statics,
1278
                            node_g->statics_read);
1279
        }
1280
 
1281
      if (node_g->statics_written
1282
          != all_module_statics)
1283
        bitmap_and_compl (node_g->statics_not_written,
1284
                          all_module_statics,
1285
                          node_g->statics_written);
1286
   }
1287
 
1288
  free (order);
1289
 
1290
  for (node = cgraph_nodes; node; node = node->next)
1291
    {
1292
      /* Get rid of the aux information.  */
1293
 
1294
      if (node->aux)
1295
        {
1296
          free (node->aux);
1297
          node->aux = NULL;
1298
        }
1299
 
1300
      if (node->analyzed
1301
          && (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE))
1302
        clean_function (node);
1303
    }
1304
  return 0;
1305
}
1306
 
1307
 
1308
static bool
1309
gate_reference (void)
1310
{
1311
  return (flag_unit_at_a_time != 0  && flag_ipa_reference
1312
          /* Don't bother doing anything if the program has errors.  */
1313
          && !(errorcount || sorrycount));
1314
}
1315
 
1316
struct tree_opt_pass pass_ipa_reference =
1317
{
1318
  "static-var",                         /* name */
1319
  gate_reference,                       /* gate */
1320
  static_execute,                       /* execute */
1321
  NULL,                                 /* sub */
1322
  NULL,                                 /* next */
1323
  0,                                     /* static_pass_number */
1324
  TV_IPA_REFERENCE,                     /* tv_id */
1325
  0,                                     /* properties_required */
1326
  0,                                     /* properties_provided */
1327
  0,                                     /* properties_destroyed */
1328
  0,                                     /* todo_flags_start */
1329
  0,                                    /* todo_flags_finish */
1330
 
1331
};
1332
 
1333
#include "gt-ipa-reference.h"
1334
 

powered by: WebSVN 2.1.0

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