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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.2.2/] [gcc/] [ipa-pure-const.c] - Blame information for rev 318

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 mark functions as being either const (TREE_READONLY) or
22
   pure (DECL_IS_PURE).
23
 
24
   This must be run after inlining decisions have been made since
25
   otherwise, the local sets will not contain information that is
26
   consistent with post inlined state.  The global sets are not prone
27
   to this problem since they are by definition transitive.  */
28
 
29
/* The code in this module is called by the ipa pass manager. It
30
   should be one of the later passes since it's information is used by
31
   the rest of the compilation. */
32
 
33
#include "config.h"
34
#include "system.h"
35
#include "coretypes.h"
36
#include "tm.h"
37
#include "tree.h"
38
#include "tree-flow.h"
39
#include "tree-inline.h"
40
#include "tree-pass.h"
41
#include "langhooks.h"
42
#include "pointer-set.h"
43
#include "ggc.h"
44
#include "ipa-utils.h"
45
#include "c-common.h"
46
#include "tree-gimple.h"
47
#include "cgraph.h"
48
#include "output.h"
49
#include "flags.h"
50
#include "timevar.h"
51
#include "diagnostic.h"
52
#include "langhooks.h"
53
#include "target.h"
54
 
55
static struct pointer_set_t *visited_nodes;
56
 
57
/* Lattice values for const and pure functions.  Everything starts out
58
   being const, then may drop to pure and then neither depending on
59
   what is found.  */
60
enum pure_const_state_e
61
{
62
  IPA_CONST,
63
  IPA_PURE,
64
  IPA_NEITHER
65
};
66
 
67
/* Holder inserted into the ipa_dfs_info aux field to hold the
68
   const_state.  */
69
struct funct_state_d
70
{
71
  enum pure_const_state_e pure_const_state;
72
  bool state_set_in_source;
73
};
74
 
75
typedef struct funct_state_d * funct_state;
76
 
77
/* Return the function state from NODE.  */
78
 
79
static inline funct_state
80
get_function_state (struct cgraph_node *node)
81
{
82
  struct ipa_dfs_info * info = node->aux;
83
  return info->aux;
84
}
85
 
86
/* Check to see if the use (or definition when CHECHING_WRITE is true)
87
   variable T is legal in a function that is either pure or const.  */
88
 
89
static inline void
90
check_decl (funct_state local,
91
            tree t, bool checking_write)
92
{
93
  /* If the variable has the "used" attribute, treat it as if it had a
94
     been touched by the devil.  */
95
  if (lookup_attribute ("used", DECL_ATTRIBUTES (t)))
96
    {
97
      local->pure_const_state = IPA_NEITHER;
98
      return;
99
    }
100
 
101
  /* Do not want to do anything with volatile except mark any
102
     function that uses one to be not const or pure.  */
103
  if (TREE_THIS_VOLATILE (t))
104
    {
105
      local->pure_const_state = IPA_NEITHER;
106
      return;
107
    }
108
 
109
  /* Do not care about a local automatic that is not static.  */
110
  if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
111
    return;
112
 
113
  /* Since we have dealt with the locals and params cases above, if we
114
     are CHECKING_WRITE, this cannot be a pure or constant
115
     function.  */
116
  if (checking_write)
117
    local->pure_const_state = IPA_NEITHER;
118
 
119
  if (DECL_EXTERNAL (t) || TREE_PUBLIC (t))
120
    {
121
      /* If the front end set the variable to be READONLY and
122
         constant, we can allow this variable in pure or const
123
         functions but the scope is too large for our analysis to set
124
         these bits ourselves.  */
125
 
126
      if (TREE_READONLY (t)
127
          && DECL_INITIAL (t)
128
          && is_gimple_min_invariant (DECL_INITIAL (t)))
129
        ; /* Read of a constant, do not change the function state.  */
130
      else
131
        {
132
          /* Just a regular read.  */
133
          if (local->pure_const_state == IPA_CONST)
134
            local->pure_const_state = IPA_PURE;
135
        }
136
    }
137
 
138
  /* Compilation level statics can be read if they are readonly
139
     variables.  */
140
  if (TREE_READONLY (t))
141
    return;
142
 
143
  /* Just a regular read.  */
144
  if (local->pure_const_state == IPA_CONST)
145
    local->pure_const_state = IPA_PURE;
146
}
147
 
148
/* If T is a VAR_DECL check to see if it is an allowed reference.  */
149
 
150
static void
151
check_operand (funct_state local,
152
               tree t, bool checking_write)
153
{
154
  if (!t) return;
155
 
156
  if (TREE_CODE (t) == VAR_DECL)
157
    check_decl (local, t, checking_write);
158
}
159
 
160
/* Examine tree T for references.  */
161
 
162
static void
163
check_tree (funct_state local, tree t, bool checking_write)
164
{
165
  if ((TREE_CODE (t) == EXC_PTR_EXPR) || (TREE_CODE (t) == FILTER_EXPR))
166
    return;
167
 
168
  /* Any tree which is volatile disqualifies thie function from being
169
     const or pure. */
170
  if (TREE_THIS_VOLATILE (t))
171
    {
172
      local->pure_const_state = IPA_NEITHER;
173
      return;
174
    }
175
 
176
  while (TREE_CODE (t) == REALPART_EXPR
177
         || TREE_CODE (t) == IMAGPART_EXPR
178
         || handled_component_p (t))
179
    {
180
      if (TREE_CODE (t) == ARRAY_REF)
181
        check_operand (local, TREE_OPERAND (t, 1), false);
182
      t = TREE_OPERAND (t, 0);
183
    }
184
 
185
  /* The bottom of an indirect reference can only be read, not
186
     written.  */
187
  if (INDIRECT_REF_P (t))
188
    {
189
      check_tree (local, TREE_OPERAND (t, 0), false);
190
 
191
      /* Any indirect reference that occurs on the lhs
192
         disqualifies the function from being pure or const. Any
193
         indirect reference that occurs on the rhs disqualifies the
194
         function from being const.  */
195
      if (checking_write)
196
        {
197
          local->pure_const_state = IPA_NEITHER;
198
          return;
199
        }
200
      else if (local->pure_const_state == IPA_CONST)
201
        local->pure_const_state = IPA_PURE;
202
    }
203
 
204
  if (SSA_VAR_P (t))
205
    check_operand (local, t, checking_write);
206
}
207
 
208
/* Scan tree T to see if there are any addresses taken in within T.  */
209
 
210
static void
211
look_for_address_of (funct_state local, tree t)
212
{
213
  if (TREE_CODE (t) == ADDR_EXPR)
214
    {
215
      tree x = get_base_var (t);
216
      if (TREE_CODE (x) == VAR_DECL)
217
        {
218
          check_decl (local, x, false);
219
 
220
          /* Taking the address of something appears to be reasonable
221
             in PURE code.  Not allowed in const.  */
222
          if (local->pure_const_state == IPA_CONST)
223
            local->pure_const_state = IPA_PURE;
224
        }
225
    }
226
}
227
 
228
/* Check to see if T is a read or address of operation on a var we are
229
   interested in analyzing.  LOCAL is passed in to get access to its
230
   bit vectors.  */
231
 
232
static void
233
check_rhs_var (funct_state local, tree t)
234
{
235
  look_for_address_of (local, t);
236
 
237
  /* Memcmp and strlen can both trap and they are declared pure.  */
238
  if (tree_could_trap_p (t)
239
      && local->pure_const_state == IPA_CONST)
240
    local->pure_const_state = IPA_PURE;
241
 
242
  check_tree(local, t, false);
243
}
244
 
245
/* Check to see if T is an assignment to a var we are interested in
246
   analyzing.  LOCAL is passed in to get access to its bit vectors. */
247
 
248
static void
249
check_lhs_var (funct_state local, tree t)
250
{
251
  /* Memcmp and strlen can both trap and they are declared pure.
252
     Which seems to imply that we can apply the same rule here.  */
253
  if (tree_could_trap_p (t)
254
      && local->pure_const_state == IPA_CONST)
255
    local->pure_const_state = IPA_PURE;
256
 
257
  check_tree(local, t, true);
258
}
259
 
260
/* This is a scaled down version of get_asm_expr_operands from
261
   tree_ssa_operands.c.  The version there runs much later and assumes
262
   that aliasing information is already available. Here we are just
263
   trying to find if the set of inputs and outputs contain references
264
   or address of operations to local static variables.  STMT is the
265
   actual asm statement.  */
266
 
267
static void
268
get_asm_expr_operands (funct_state local, tree stmt)
269
{
270
  int noutputs = list_length (ASM_OUTPUTS (stmt));
271
  const char **oconstraints
272
    = (const char **) alloca ((noutputs) * sizeof (const char *));
273
  int i;
274
  tree link;
275
  const char *constraint;
276
  bool allows_mem, allows_reg, is_inout;
277
 
278
  for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
279
    {
280
      oconstraints[i] = constraint
281
        = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
282
      parse_output_constraint (&constraint, i, 0, 0,
283
                               &allows_mem, &allows_reg, &is_inout);
284
 
285
      check_lhs_var (local, TREE_VALUE (link));
286
    }
287
 
288
  for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
289
    {
290
      constraint
291
        = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
292
      parse_input_constraint (&constraint, 0, 0, noutputs, 0,
293
                              oconstraints, &allows_mem, &allows_reg);
294
 
295
      check_rhs_var (local, TREE_VALUE (link));
296
    }
297
 
298
  for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
299
    if (simple_cst_equal(TREE_VALUE (link), memory_identifier_string) == 1)
300
      /* Abandon all hope, ye who enter here. */
301
      local->pure_const_state = IPA_NEITHER;
302
 
303
  if (ASM_VOLATILE_P (stmt))
304
    local->pure_const_state = IPA_NEITHER;
305
}
306
 
307
/* Check the parameters of a function call to CALL_EXPR to see if
308
   there are any references in the parameters that are not allowed for
309
   pure or const functions.  Also check to see if this is either an
310
   indirect call, a call outside the compilation unit, or has special
311
   attributes that may also effect the purity.  The CALL_EXPR node for
312
   the entire call expression.  */
313
 
314
static void
315
check_call (funct_state local, tree call_expr)
316
{
317
  int flags = call_expr_flags(call_expr);
318
  tree operand_list = TREE_OPERAND (call_expr, 1);
319
  tree operand;
320
  tree callee_t = get_callee_fndecl (call_expr);
321
  struct cgraph_node* callee;
322
  enum availability avail = AVAIL_NOT_AVAILABLE;
323
 
324
  for (operand = operand_list;
325
       operand != NULL_TREE;
326
       operand = TREE_CHAIN (operand))
327
    {
328
      tree argument = TREE_VALUE (operand);
329
      check_rhs_var (local, argument);
330
    }
331
 
332
  /* The const and pure flags are set by a variety of places in the
333
     compiler (including here).  If someone has already set the flags
334
     for the callee, (such as for some of the builtins) we will use
335
     them, otherwise we will compute our own information.
336
 
337
     Const and pure functions have less clobber effects than other
338
     functions so we process these first.  Otherwise if it is a call
339
     outside the compilation unit or an indirect call we punt.  This
340
     leaves local calls which will be processed by following the call
341
     graph.  */
342
  if (callee_t)
343
    {
344
      callee = cgraph_node(callee_t);
345
      avail = cgraph_function_body_availability (callee);
346
 
347
      /* When bad things happen to bad functions, they cannot be const
348
         or pure.  */
349
      if (setjmp_call_p (callee_t))
350
        local->pure_const_state = IPA_NEITHER;
351
 
352
      if (DECL_BUILT_IN_CLASS (callee_t) == BUILT_IN_NORMAL)
353
        switch (DECL_FUNCTION_CODE (callee_t))
354
          {
355
          case BUILT_IN_LONGJMP:
356
          case BUILT_IN_NONLOCAL_GOTO:
357
            local->pure_const_state = IPA_NEITHER;
358
            break;
359
          default:
360
            break;
361
          }
362
    }
363
 
364
  /* The callee is either unknown (indirect call) or there is just no
365
     scannable code for it (external call) .  We look to see if there
366
     are any bits available for the callee (such as by declaration or
367
     because it is builtin) and process solely on the basis of those
368
     bits. */
369
  if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
370
    {
371
      if (flags & ECF_PURE)
372
        {
373
          if (local->pure_const_state == IPA_CONST)
374
            local->pure_const_state = IPA_PURE;
375
        }
376
      else
377
        local->pure_const_state = IPA_NEITHER;
378
    }
379
  else
380
    {
381
      /* We have the code and we will scan it for the effects. */
382
      if (flags & ECF_PURE)
383
        {
384
          if (local->pure_const_state == IPA_CONST)
385
            local->pure_const_state = IPA_PURE;
386
        }
387
    }
388
}
389
 
390
/* TP is the part of the tree currently under the microscope.
391
   WALK_SUBTREES is part of the walk_tree api but is unused here.
392
   DATA is cgraph_node of the function being walked.  */
393
 
394
/* FIXME: When this is converted to run over SSA form, this code
395
   should be converted to use the operand scanner.  */
396
 
397
static tree
398
scan_function (tree *tp,
399
                      int *walk_subtrees,
400
                      void *data)
401
{
402
  struct cgraph_node *fn = data;
403
  tree t = *tp;
404
  funct_state local = get_function_state (fn);
405
 
406
  switch (TREE_CODE (t))
407
    {
408
    case VAR_DECL:
409
      if (DECL_INITIAL (t))
410
        walk_tree (&DECL_INITIAL (t), scan_function, fn, visited_nodes);
411
      *walk_subtrees = 0;
412
      break;
413
 
414
    case MODIFY_EXPR:
415
      {
416
        /* First look on the lhs and see what variable is stored to */
417
        tree lhs = TREE_OPERAND (t, 0);
418
        tree rhs = TREE_OPERAND (t, 1);
419
        check_lhs_var (local, lhs);
420
 
421
        /* For the purposes of figuring out what the cast affects */
422
 
423
        /* Next check the operands on the rhs to see if they are ok. */
424
        switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
425
          {
426
          case tcc_binary:
427
            {
428
              tree op0 = TREE_OPERAND (rhs, 0);
429
              tree op1 = TREE_OPERAND (rhs, 1);
430
              check_rhs_var (local, op0);
431
              check_rhs_var (local, op1);
432
            }
433
            break;
434
          case tcc_unary:
435
            {
436
              tree op0 = TREE_OPERAND (rhs, 0);
437
              check_rhs_var (local, op0);
438
            }
439
 
440
            break;
441
          case tcc_reference:
442
            check_rhs_var (local, rhs);
443
            break;
444
          case tcc_declaration:
445
            check_rhs_var (local, rhs);
446
            break;
447
          case tcc_expression:
448
            switch (TREE_CODE (rhs))
449
              {
450
              case ADDR_EXPR:
451
                check_rhs_var (local, rhs);
452
                break;
453
              case CALL_EXPR:
454
                check_call (local, rhs);
455
                break;
456
              default:
457
                break;
458
              }
459
            break;
460
          default:
461
            break;
462
          }
463
        *walk_subtrees = 0;
464
      }
465
      break;
466
 
467
    case ADDR_EXPR:
468
      /* This case is here to find addresses on rhs of constructors in
469
         decl_initial of static variables. */
470
      check_rhs_var (local, t);
471
      *walk_subtrees = 0;
472
      break;
473
 
474
    case LABEL_EXPR:
475
      if (DECL_NONLOCAL (TREE_OPERAND (t, 0)))
476
        /* Target of long jump. */
477
        local->pure_const_state = IPA_NEITHER;
478
      break;
479
 
480
    case CALL_EXPR:
481
      check_call (local, t);
482
      *walk_subtrees = 0;
483
      break;
484
 
485
    case ASM_EXPR:
486
      get_asm_expr_operands (local, t);
487
      *walk_subtrees = 0;
488
      break;
489
 
490
    default:
491
      break;
492
    }
493
  return NULL;
494
}
495
 
496
/* This is the main routine for finding the reference patterns for
497
   global variables within a function FN.  */
498
 
499
static void
500
analyze_function (struct cgraph_node *fn)
501
{
502
  funct_state l = XCNEW (struct funct_state_d);
503
  tree decl = fn->decl;
504
  struct ipa_dfs_info * w_info = fn->aux;
505
 
506
  w_info->aux = l;
507
 
508
  l->pure_const_state = IPA_CONST;
509
  l->state_set_in_source = false;
510
 
511
  /* If this function does not return normally or does not bind local,
512
     do not touch this unless it has been marked as const or pure by the
513
     front end.  */
514
  if (TREE_THIS_VOLATILE (decl)
515
      || !targetm.binds_local_p (decl))
516
    {
517
      l->pure_const_state = IPA_NEITHER;
518
      return;
519
    }
520
 
521
  if (TREE_READONLY (decl))
522
    {
523
      l->pure_const_state = IPA_CONST;
524
      l->state_set_in_source = true;
525
    }
526
  if (DECL_IS_PURE (decl))
527
    {
528
      l->pure_const_state = IPA_PURE;
529
      l->state_set_in_source = true;
530
    }
531
 
532
  if (dump_file)
533
    {
534
      fprintf (dump_file, "\n local analysis of %s with initial value = %d\n ",
535
               cgraph_node_name (fn),
536
               l->pure_const_state);
537
    }
538
 
539
  if (!l->state_set_in_source)
540
    {
541
      struct function *this_cfun = DECL_STRUCT_FUNCTION (decl);
542
      basic_block this_block;
543
 
544
      FOR_EACH_BB_FN (this_block, this_cfun)
545
        {
546
          block_stmt_iterator bsi;
547
          for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
548
            {
549
              walk_tree (bsi_stmt_ptr (bsi), scan_function,
550
                         fn, visited_nodes);
551
              if (l->pure_const_state == IPA_NEITHER)
552
                goto end;
553
            }
554
        }
555
 
556
      if (l->pure_const_state != IPA_NEITHER)
557
        {
558
          tree old_decl = current_function_decl;
559
          /* Const functions cannot have back edges (an
560
             indication of possible infinite loop side
561
             effect.  */
562
 
563
          current_function_decl = fn->decl;
564
 
565
          /* The C++ front end, has a tendency to some times jerk away
566
             a function after it has created it.  This should have
567
             been fixed.  */
568
          gcc_assert (DECL_STRUCT_FUNCTION (fn->decl));
569
 
570
          push_cfun (DECL_STRUCT_FUNCTION (fn->decl));
571
 
572
          if (mark_dfs_back_edges ())
573
            l->pure_const_state = IPA_NEITHER;
574
 
575
          current_function_decl = old_decl;
576
          pop_cfun ();
577
        }
578
    }
579
 
580
end:
581
  if (dump_file)
582
    {
583
      fprintf (dump_file, "after local analysis of %s with initial value = %d\n ",
584
               cgraph_node_name (fn),
585
               l->pure_const_state);
586
    }
587
}
588
 
589
 
590
/* Produce the global information by preforming a transitive closure
591
   on the local information that was produced by ipa_analyze_function
592
   and ipa_analyze_variable.  */
593
 
594
static unsigned int
595
static_execute (void)
596
{
597
  struct cgraph_node *node;
598
  struct cgraph_node *w;
599
  struct cgraph_node **order =
600
    XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
601
  int order_pos = order_pos = ipa_utils_reduced_inorder (order, true, false);
602
  int i;
603
  struct ipa_dfs_info * w_info;
604
 
605
  if (!memory_identifier_string)
606
    memory_identifier_string = build_string(7, "memory");
607
 
608
  /* There are some shared nodes, in particular the initializers on
609
     static declarations.  We do not need to scan them more than once
610
     since all we would be interested in are the addressof
611
     operations.  */
612
  visited_nodes = pointer_set_create ();
613
 
614
  /* Process all of the functions.
615
 
616
     We do not want to process any of the clones so we check that this
617
     is a master clone.  However, we do NOT process any
618
     AVAIL_OVERWRITABLE functions (these are never clones) we cannot
619
     guarantee that what we learn about the one we see will be true
620
     for the one that overriders it.
621
  */
622
  for (node = cgraph_nodes; node; node = node->next)
623
    if (node->analyzed && cgraph_is_master_clone (node))
624
      analyze_function (node);
625
 
626
  pointer_set_destroy (visited_nodes);
627
  visited_nodes = NULL;
628
  if (dump_file)
629
    {
630
      dump_cgraph (dump_file);
631
      ipa_utils_print_order(dump_file, "reduced", order, order_pos);
632
    }
633
 
634
  /* Propagate the local information thru the call graph to produce
635
     the global information.  All the nodes within a cycle will have
636
     the same info so we collapse cycles first.  Then we can do the
637
     propagation in one pass from the leaves to the roots.  */
638
  for (i = 0; i < order_pos; i++ )
639
    {
640
      enum pure_const_state_e pure_const_state = IPA_CONST;
641
      node = order[i];
642
 
643
      /* Find the worst state for any node in the cycle.  */
644
      w = node;
645
      while (w)
646
        {
647
          funct_state w_l = get_function_state (w);
648
          if (pure_const_state < w_l->pure_const_state)
649
            pure_const_state = w_l->pure_const_state;
650
 
651
          if (pure_const_state == IPA_NEITHER)
652
            break;
653
 
654
          if (!w_l->state_set_in_source)
655
            {
656
              struct cgraph_edge *e;
657
              for (e = w->callees; e; e = e->next_callee)
658
                {
659
                  struct cgraph_node *y = e->callee;
660
                  /* Only look at the master nodes and skip external nodes.  */
661
                  y = cgraph_master_clone (y);
662
                  if (y)
663
                    {
664
                      funct_state y_l = get_function_state (y);
665
                      if (pure_const_state < y_l->pure_const_state)
666
                        pure_const_state = y_l->pure_const_state;
667
                      if (pure_const_state == IPA_NEITHER)
668
                        break;
669
                    }
670
                }
671
            }
672
          w_info = w->aux;
673
          w = w_info->next_cycle;
674
        }
675
 
676
      /* Copy back the region's pure_const_state which is shared by
677
         all nodes in the region.  */
678
      w = node;
679
      while (w)
680
        {
681
          funct_state w_l = get_function_state (w);
682
 
683
          /* All nodes within a cycle share the same info.  */
684
          if (!w_l->state_set_in_source)
685
            {
686
              w_l->pure_const_state = pure_const_state;
687
              switch (pure_const_state)
688
                {
689
                case IPA_CONST:
690
                  TREE_READONLY (w->decl) = 1;
691
                  if (dump_file)
692
                    fprintf (dump_file, "Function found to be const: %s\n",
693
                             lang_hooks.decl_printable_name(w->decl, 2));
694
                  break;
695
 
696
                case IPA_PURE:
697
                  DECL_IS_PURE (w->decl) = 1;
698
                  if (dump_file)
699
                    fprintf (dump_file, "Function found to be pure: %s\n",
700
                             lang_hooks.decl_printable_name(w->decl, 2));
701
                  break;
702
 
703
                default:
704
                  break;
705
                }
706
            }
707
          w_info = w->aux;
708
          w = w_info->next_cycle;
709
        }
710
    }
711
 
712
  /* Cleanup. */
713
  for (node = cgraph_nodes; node; node = node->next)
714
    /* Get rid of the aux information.  */
715
    if (node->aux)
716
      {
717
        w_info = node->aux;
718
        if (w_info->aux)
719
          free (w_info->aux);
720
        free (node->aux);
721
        node->aux = NULL;
722
      }
723
 
724
  free (order);
725
  return 0;
726
}
727
 
728
static bool
729
gate_pure_const (void)
730
{
731
  return (flag_unit_at_a_time != 0 && flag_ipa_pure_const
732
          /* Don't bother doing anything if the program has errors.  */
733
          && !(errorcount || sorrycount));
734
}
735
 
736
struct tree_opt_pass pass_ipa_pure_const =
737
{
738
  "pure-const",                         /* name */
739
  gate_pure_const,                      /* gate */
740
  static_execute,                       /* execute */
741
  NULL,                                 /* sub */
742
  NULL,                                 /* next */
743
  0,                                     /* static_pass_number */
744
  TV_IPA_PURE_CONST,                    /* tv_id */
745
  0,                                     /* properties_required */
746
  0,                                     /* properties_provided */
747
  0,                                     /* properties_destroyed */
748
  0,                                     /* todo_flags_start */
749
  0,                                    /* todo_flags_finish */
750
 
751
};
752
 
753
 

powered by: WebSVN 2.1.0

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