Hi! On the attached testcase we started to give false positive warnings when critedge has been changed to only use SSA_NAME_VAR for PHI result if all PHI arguments use that SSA_NAME_VAR.
The fn3 function (inlined) contains a retval variable which has false positive uninit warning disabled through the int retval = retval; trick, so we set TREE_NO_WARNING on the VAR_DECL. Previously the PHI result was also result_NN and the uninit pass doesn't warn for vars that are used possibly uninitialized and that are TREE_NO_WARNING. But since the changes, the PHI result is just an anonymous SSA_NAME and later on merged with the err var, which isn't TREE_NO_WARNING, the only thing that is TREE_NO_WARNING is the result_NN(D) used in one of the PHIs. The following patch fixes it by not considering TREE_NO_WARNING SSA_NAME_VARs as undefined for the purposes of uninit pass (other passes still IMHO want the previous ssa_undefined_value_p behavior, which is why I haven't changed ssa_undefined_value_p directly). Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.8? 2013-05-07 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/57149 * tree-ssa-uninit.c (uninit_undefined_value_p): New inline. (can_skip_redundant_opnd, compute_uninit_opnds_pos, collect_phi_def_edges, execute_late_warn_uninitialized): Use uninit_undefined_value_p instead of ssa_undefined_value_p. * gcc.dg/pr57149.c: New test. --- gcc/tree-ssa-uninit.c.jj 2013-04-26 15:14:19.000000000 +0200 +++ gcc/tree-ssa-uninit.c 2013-05-07 08:57:37.538444516 +0200 @@ -101,6 +101,19 @@ ssa_undefined_value_p (tree t) && pointer_set_contains (possibly_undefined_names, t))); } +/* Like ssa_undefined_value_p, but don't return true if TREE_NO_WARNING + is set on SSA_NAME_VAR. */ + +static inline bool +uninit_undefined_value_p (tree t) +{ + if (!ssa_undefined_value_p (t)) + return false; + if (SSA_NAME_VAR (t) && TREE_NO_WARNING (SSA_NAME_VAR (t))) + return false; + return true; +} + /* Checks if the operand OPND of PHI is defined by another phi with one operand defined by this PHI, but the rest operands are all defined. If yes, @@ -124,7 +137,7 @@ can_skip_redundant_opnd (tree opnd, gimp tree op = gimple_phi_arg_def (op_def, i); if (TREE_CODE (op) != SSA_NAME) continue; - if (op != phi_def && ssa_undefined_value_p (op)) + if (op != phi_def && uninit_undefined_value_p (op)) return false; } @@ -149,7 +162,7 @@ compute_uninit_opnds_pos (gimple phi) { tree op = gimple_phi_arg_def (phi, i); if (TREE_CODE (op) == SSA_NAME - && ssa_undefined_value_p (op) + && uninit_undefined_value_p (op) && !can_skip_redundant_opnd (op, phi)) { /* Ignore SSA_NAMEs on abnormal edges to setjmp @@ -518,7 +531,7 @@ collect_phi_def_edges (gimple phi, basic gimple_bb (def), cd_root)) collect_phi_def_edges (def, cd_root, edges, visited_phis); - else if (!ssa_undefined_value_p (opnd)) + else if (!uninit_undefined_value_p (opnd)) { if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -2002,7 +2015,7 @@ execute_late_warn_uninitialized (void) { tree op = gimple_phi_arg_def (phi, i); if (TREE_CODE (op) == SSA_NAME - && ssa_undefined_value_p (op)) + && uninit_undefined_value_p (op)) { worklist.safe_push (phi); pointer_set_insert (added_to_worklist, phi); --- gcc/testsuite/gcc.dg/pr57149.c.jj 2013-05-07 09:00:02.253621530 +0200 +++ gcc/testsuite/gcc.dg/pr57149.c 2013-05-07 08:59:42.000000000 +0200 @@ -0,0 +1,50 @@ +/* PR tree-optimization/57149 */ +/* { dg-do compile } */ +/* { dg-options "-Os -Wuninitialized" } */ + +struct A { struct A *a, *b; }; +struct D { struct A e; }; +struct E { unsigned char f; struct { struct A e; } g; }; +struct F { struct E i[32]; }; + +extern int fn0 (void); +extern int fn1 (struct E *, struct D *); + +static inline __attribute__ ((always_inline)) int +fn2 (const struct A *x) +{ + return x->a == x; +} + +static int +fn3 (struct E *x) +{ + struct D *l, *m; + int retval = retval; + if (fn2 (&x->g.e)) + return 0; + for (l = (struct D *) x->g.e.a, m = (struct D *) l->e.a; + &l->e != &x->g.e; + l = m, m = (struct D *) m->e.a) + retval = fn1 (x, l); + return retval; +} + +void +fn4 (struct F *x, unsigned k) +{ + unsigned i; + for (i = 0; i < k; i++) + { + struct E *y = &x->i[i]; + int err = -22; + err = fn3 (y); + if (y->f == 0) + { + if (err > 0) + err = fn0 (); + if (err < 0) /* { dg-bogus "may be used uninitialized in this function" } */ + fn0 (); + } + } +} Jakub