The second "if" statement is not optimized away until CSE. /* Reduced from reload_combine() in postreload.c. */ struct s { int c; struct s *next; }; int global; extern void bar (void); void foo (struct s *p) { for (; p; p = p->next) { if (p->c != 0) continue; global++; if (p->c == 0) bar (); } } To give you sense of where this comes from, think of the first "if" as !INSN_P and think of the second one as INSN_P with bar() being single_set_2.
Confirmed, Variable: p, UID 1, type memory tag: TMT.3, default def: p_5 Variable: TMT.3, UID 5, is global, call clobbered, may aliases: { global }
Reduced to: struct s { int c; struct s *next; }; int global; extern void bar (void); void foo (struct s *p) { if (p->c != 0) return; global++; if (p->c == 0) bar (); }
Another similar testcase reduced from web.c. extern void abort (void) __attribute__ ((__noreturn__)); struct s { int a; int b; }; void bar (struct s *p) { if (p->a) abort (); p->b = 0; if (p->a) abort (); }
The reduced case from web.c is also PR 13761.
Looks like food for DannyB.
FWIW, here is the last SSA form I get with vops. foo (p) { int D.1241; int global.0; int D.1239; <bb 0>: # VUSE <global_3>; D.1239_2 = p_1->c; if (D.1239_2 != 0) goto <L2>; else goto <L0>; <L0>:; # VUSE <global_3>; global.0_4 = global; D.1241_5 = global.0_4 + 1; # global_6 = V_MUST_DEF <global_3>; global = D.1241_5; # VUSE <global_6>; D.1239_7 = p_1->c; if (D.1239_7 == 0) goto <L1>; else goto <L2>; <L1>:; # global_8 = V_MAY_DEF <global_6>; bar () [tail call]; <L2>:; return; }
Comment #0 and #2 are fixed now by: 2006-02-16 Daniel Berlin <dberlin@dberlin.org> * tree-ssa-operands.c (access_can_touch_variable): Fix typo in previous change. 2006-02-15 Daniel Berlin <dberlin@dberlin.org> * tree.c (init_ttree): Add STRUCT_FIELD_TAG handling. (tree_code_size): Ditto. * tree.h (struct tree_memory_tag): Remove parent_var. (struct tree_struct_field_tag): New. (SFT_OFFSET): New. (SFT_SIZE): New. (union tree_node): Add sft member. * tree-ssa-alias.c (get_tmt_for): Don't handle TYPE_READONLY specially here. (create_sft): Add size and offset argument, set SFT_OFFSET and SFT_SIZE. (create_overlap_variables_for): Update for SFT_OFFSET/SFT_SIZE. * treestruct.def: Add TS_STRUCT_FIELD_TAG. * tree-flow-inline.h (get_subvar_at): Update for SFT_OFFSET/SFT_SIZE. (var_can_have_subvars): Ditto. (overlap_subvar): Ditto. * print-tree.c (print_node): Print out interesting things for SFT's. * tree-flow.h (struct subvar): Remove offset and size members. * tree-ssa-operands.c (get_expr_operands): Update for get_indirect_ref_operands changes. (get_indirect_ref_operands): Call add_virtual_operand instead of add_stmt_operand. Only recurse on base var if requested. (access_can_touch_variable): New function. (add_stmt_operand): Split virtual operand handling into ... (add_virtual_operand): Here. Add offset, size, and for_clobber arguments. Prune alias sets. (add_call_clobber_ops): Call add_virtual_operand. Comment #3 as mentioned it PR 13761.