struct obj_symbol { struct obj_symbol *next; unsigned int size; }; struct common_entry { struct common_entry *next; struct obj_symbol *sym; }; extern void do_something(struct obj_symbol *sym); void obj_allocate_commons(struct obj_symbol *sym) { struct common_entry *common_head = ((void *)0); for (; sym ; sym = sym->next) { struct common_entry **p, *n; for (p = &common_head; *p ; p = &(*p)->next) if (sym->size <= (*p)->sym->size) break; n = __builtin_alloca (sizeof(*n)); n->next = *p; n->sym = sym; *p = n; } { struct common_entry *p; for (p = common_head; p ; p = p->next) do_something(p->sym); } } is miscompiled on gcc-4_1-branch at least on x84_64-linux, with -O2 and above (but not with -fno-strict-aliasing). The common_head = NULL initialization is removed as dead during 1st DCE pass, but from quick skimming the reason for that seems to be incorrect aliasing information.
Confirmed. Maybe related to PR30088. The first alias dump at -O2 (-O -fstrict-aliasing is fine) has <bb 0>: # common_head_5 = V_MUST_DEF <common_head_4>; common_head = 0B; ... <L0>:; p_10 = &common_head; goto <bb 4> (<L3>); <L1>:; # VUSE <TMT.6_24>; D.1631_16 = sym_1->size; # VUSE <HEAP.5_22>; D.1632_17 = *p_2; ... # p_2 = PHI <p_10(1), p_21(3)>; <L3>:; # VUSE <HEAP.5_22>; D.1632_11 = *p_2; if (D.1632_11 != 0B) goto <L1>; else goto <L4>; so we have both HEAP.5 and common_head_5 used as tags for common_heap.
Closing 4.1 branch.