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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [ipa-pure-const.c] - Blame information for rev 20

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

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

powered by: WebSVN 2.1.0

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