1 /* { dg-do compile { target { nonpic || pie_enabled } } } */ 2 /* { dg-options "-O2 -fdump-tree-pre-stats -fdump-tree-fre1" } */ 3 #include <stddef.h> 4 5 union tree_node; 6 typedef union tree_node *tree; 7 8 struct tree_common 9 { 10 tree chain; 11 }; 12 13 struct tree_list 14 { 15 struct tree_common common; 16 tree value; 17 }; 18 19 union tree_node 20 21 { 22 struct tree_common common; 23 struct tree_list list; 24 }; 25 26 extern void abort (void) __attribute__((noreturn)); 27 28 void __attribute__((noinline)) foo(void)29foo (void) 30 { 31 abort (); 32 } 33 34 /* There are some reloaded loads of *cell, and cell->common.chain on various 35 branches. */ 36 void __attribute__((noinline)) remove_useless_vars(tree * unexpanded_var_list,int dump_file)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 } 56 extern void *malloc (__SIZE_TYPE__) __attribute__ ((malloc)); 57 58 int main(void)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 76 /* { dg-final { scan-tree-dump-not "= unexpanded_var_list;" "fre1" } } */ 77 /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ 78 /* { dg-final { scan-tree-dump-times "Insertions: 1" 1 "pre" } } */ 79