1/* { dg-do compile } */
2/* { dg-options "-O2 -fdump-tree-pre-stats" } */
3#include <stddef.h>
4
5union tree_node;
6typedef union tree_node *tree;
7
8struct tree_common
9{
10  tree chain;
11};
12
13struct tree_list
14{
15  struct tree_common common;
16  tree value;
17};
18
19union tree_node
20
21{
22  struct tree_common common;
23  struct tree_list list;
24};
25
26extern void abort (void) __attribute__((noreturn));
27
28void __attribute__((noinline))
29foo (void)
30{
31  abort ();
32}
33
34/* There are some reloaded loads of *cell, and cell->common.chain on various
35   branches.  */
36void __attribute__((noinline))
37remove_useless_vars (tree *unexpanded_var_list, int dump_file)
38{
39  tree var, *cell;
40  int c = 0;
41  for (cell = unexpanded_var_list; *cell; )
42    {
43      var = (*cell)->list.value;
44      if (var)
45        {
46          if (dump_file)
47            foo ();
48
49          *cell = ((*cell)->common.chain);
50          continue;
51        }
52
53      cell = &((*cell)->common.chain);
54    }
55}
56extern void *malloc (__SIZE_TYPE__) __attribute__ ((malloc));
57
58int
59main (void)
60{
61  int i;
62  tree unexpanded_var_list, last = (tree) 0;
63
64  for (i = 0; i < 2; i++)
65    {
66      unexpanded_var_list = malloc (sizeof (struct tree_list));
67      unexpanded_var_list->list.value = (tree) (ptrdiff_t) (i & 1);
68      unexpanded_var_list->common.chain = last;
69      last = unexpanded_var_list;
70    }
71
72  remove_useless_vars (&unexpanded_var_list, 0);
73  return 0;
74}
75/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre" } } */
76/* { dg-final { cleanup-tree-dump "pre" } } */
77
78