On Mon, May 12, 2014 at 5:42 AM, Patrick Palka <patr...@parcs.ath.cx> wrote: > Hi, > > This patch fixes a bogus warning generated by -Wmaybe-uninitialized. > The problem is that we sometimes fail to acknowledge a defining edge > belonging to a control-dependence chain because we assume that each > defining edge shares the same control-dependence root. But this may not > be true if a defining edge flows into a PHI node that is different from > the root PHI node. This faulty assumption may result in an incomplete > control-dependency chain being computed, ultimately causing a > false-positive warning like in the test case. > > To fix this, this patch computes the control-dependency root on a > per-defining-edge basis, using the function nearest_common_dominator to > find a common dominator (i.e. a BB before which control flow is > irrelevant) between the control-dependency root of the root PHI node and > that of the edge's dest PHI node. > > However, that change alone is not enough. We must also tweak the > function collect_phi_def_edges to allow recursing on PHI nodes that are > not dominated by the root PHI node's control dependency root as we can > still figure out a control dependency chain in such cases as long the > PHI node postdominates the PHI argument, i.e. as long as the control > flow from the PHI argument edge down to the root PHI node is irrelevant. > > Both these changes are required to make the below test case compile > without emitting a bogus warning. > > I bootstrapped and regtested this change on x86_64-unknown-linux-gnu. > Is it OK for trunk?
CCing the author of the code. Given the lengthy comment above I miss comments in the code that reflect the complexity of this issue and explains the implementation. Other than that I defer to David, but any improvement to this pass is welcome! Can you assess the effect on compile-time this patch has? (from an algorithmic standpoint?) Thanks, Richard. > 2014-05-10 Patrick Palka <patr...@parcs.ath.cx> > > * tree-ssa-uninit.c (collect_phi_def_edges): Remove cd_root > parameter. Refactor to consolidate duplicate code. Tweak dump > message. > (find_def_preds): Add dump messages. Adjust call to > collect_phi_def_edges. Adjust the control dependency root on > a per-edge basis. > --- > gcc/testsuite/gcc.dg/uninit-pred-11.c | 20 ++++++++++ > gcc/tree-ssa-uninit.c | 75 > +++++++++++++++++++---------------- > 2 files changed, 60 insertions(+), 35 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/uninit-pred-11.c > > diff --git a/gcc/testsuite/gcc.dg/uninit-pred-11.c > b/gcc/testsuite/gcc.dg/uninit-pred-11.c > new file mode 100644 > index 0000000..493be68 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/uninit-pred-11.c > @@ -0,0 +1,20 @@ > +// PR middle-end/61112 > +// { dg-options "-Wuninitialized -O2" } > + > +int p; > + > +void > +foo (int x, int y, int z) > +{ > + int w; > + if (x) > + w = z; > + if (y) > + w = 10; > + if (p) > + w = 20; > + > + if (x || y || p) > + p = w; // { dg-bogus "uninitialized" } > +} > + > diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c > index 8b298fa..472b8e5 100644 > --- a/gcc/tree-ssa-uninit.c > +++ b/gcc/tree-ssa-uninit.c > @@ -641,13 +641,11 @@ find_predicates (pred_chain_union *preds, > > /* Computes the set of incoming edges of PHI that have non empty > definitions of a phi chain. The collection will be done > - recursively on operands that are defined by phis. CD_ROOT > - is the control dependence root. *EDGES holds the result, and > - VISITED_PHIS is a pointer set for detecting cycles. */ > + recursively on operands that are defined by phis. *EDGES holds > + the result, and VISITED_PHIS is a pointer set for detecting cycles. */ > > static void > -collect_phi_def_edges (gimple phi, basic_block cd_root, > - vec<edge> *edges, > +collect_phi_def_edges (gimple phi, vec<edge> *edges, > pointer_set_t *visited_phis) > { > size_t i, n; > @@ -663,34 +661,23 @@ collect_phi_def_edges (gimple phi, basic_block cd_root, > opnd_edge = gimple_phi_arg_edge (phi, i); > opnd = gimple_phi_arg_def (phi, i); > > - if (TREE_CODE (opnd) != SSA_NAME) > - { > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - fprintf (dump_file, "\n[CHECK] Found def edge %d in ", (int)i); > - print_gimple_stmt (dump_file, phi, 0, 0); > - } > - edges->safe_push (opnd_edge); > - } > - else > - { > - gimple def = SSA_NAME_DEF_STMT (opnd); > - > - if (gimple_code (def) == GIMPLE_PHI > - && dominated_by_p (CDI_DOMINATORS, > - gimple_bb (def), cd_root)) > - collect_phi_def_edges (def, cd_root, edges, > - visited_phis); > - else if (!uninit_undefined_value_p (opnd)) > - { > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - fprintf (dump_file, "\n[CHECK] Found def edge %d in ", > (int)i); > - print_gimple_stmt (dump_file, phi, 0, 0); > - } > - edges->safe_push (opnd_edge); > - } > - } > + if (TREE_CODE (opnd) == SSA_NAME > + && gimple_code (SSA_NAME_DEF_STMT (opnd)) == GIMPLE_PHI > + && dominated_by_p (CDI_POST_DOMINATORS, > + gimple_bb (SSA_NAME_DEF_STMT (opnd)), > + gimple_bb (phi))) > + collect_phi_def_edges (SSA_NAME_DEF_STMT (opnd), edges, visited_phis); > + else if (TREE_CODE (opnd) != SSA_NAME > + || !uninit_undefined_value_p (opnd)) > + { > + if (dump_file && (dump_flags & TDF_DETAILS)) > + { > + fprintf (dump_file, "[CHECK] Found def edge %u in arg %d of ", > + edges->length (), (int)i); > + print_gimple_stmt (dump_file, phi, 0, 0); > + } > + edges->safe_push (opnd_edge); > + } > } > } > > @@ -716,8 +703,12 @@ find_def_preds (pred_chain_union *preds, gimple phi) > if (!cd_root) > return false; > > + if (dump_file && (dump_flags & TDF_DETAILS)) > + fprintf (dump_file, "[CHECK] control dependence root is bb %d\n", > + cd_root->index); > + > visited_phis = pointer_set_create (); > - collect_phi_def_edges (phi, cd_root, &def_edges, visited_phis); > + collect_phi_def_edges (phi, &def_edges, visited_phis); > pointer_set_destroy (visited_phis); > > n = def_edges.length (); > @@ -728,11 +719,25 @@ find_def_preds (pred_chain_union *preds, gimple phi) > { > size_t prev_nc, j; > int num_calls = 0; > + basic_block adj_cd_root; > edge opnd_edge; > > opnd_edge = def_edges[i]; > prev_nc = num_chains; > - compute_control_dep_chain (cd_root, opnd_edge->src, dep_chains, > + > + if (opnd_edge->dest == phi_bb) > + adj_cd_root = cd_root; > + else > + adj_cd_root = nearest_common_dominator (CDI_DOMINATORS, > + cd_root, > + find_dom (opnd_edge->dest)); > + > + if (dump_file && (dump_flags & TDF_DETAILS)) > + fprintf (dump_file, > + "[CHECK] control dependence root of def edge %d is bb %d\n", > + (int)i, adj_cd_root->index); > + > + compute_control_dep_chain (adj_cd_root, opnd_edge->src, dep_chains, > &num_chains, &cur_chain, &num_calls); > > /* Now update the newly added chains with > -- > 2.0.0.rc0 >