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