diff mbox

Fix issue in uninit analysis (PR middle-end/61112)

Message ID 1399866153-24670-1-git-send-email-patrick@parcs.ath.cx
State New
Headers show

Commit Message

Patrick Palka May 12, 2014, 3:42 a.m. UTC
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?

2014-05-10  Patrick Palka  <patrick@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

Comments

Richard Biener May 13, 2014, 9:09 a.m. UTC | #1
On Mon, May 12, 2014 at 5:42 AM, Patrick Palka <patrick@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  <patrick@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
>
Xinliang David Li May 13, 2014, 10:20 p.m. UTC | #2
I have concerns with the proposed this patch:

1) not sharing cd_root may lead to difficulties in later predication
simplication
2) the change to check post-dom may also lead to incomplete predicate chain.

I think the right fix to the problem is to realize that BBs with the
following conditions y_8 !=0, p.0_10 !=0, and x_5 !=0 are actually
control equivalent. This fact allows simplifying the USE predicates
from  (y_8 !=0 OR p.0_10 !=0 OR x_5 !=0) into just p.0_10 !=0 which is
the same as the condition for the definition.

David


On Tue, May 13, 2014 at 2:09 AM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Mon, May 12, 2014 at 5:42 AM, Patrick Palka <patrick@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  <patrick@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
>>
Xinliang David Li May 13, 2014, 11:12 p.m. UTC | #3
>
> I think the right fix to the problem is to realize that BBs with the
> following conditions y_8 !=0, p.0_10 !=0, and x_5 !=0 are actually
> control equivalent. This fact allows simplifying the USE predicates
> from  (y_8 !=0 OR p.0_10 !=0 OR x_5 !=0) into just p.0_10 !=0 which is
> the same as the condition for the definition.

Ignore above which is wrong.

For the fix, I wonder if we need to compute the cd_root for def PHI
from the use predicates (after simplication/normalization).

David

>
>
> On Tue, May 13, 2014 at 2:09 AM, Richard Biener
> <richard.guenther@gmail.com> wrote:
>> On Mon, May 12, 2014 at 5:42 AM, Patrick Palka <patrick@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  <patrick@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
>>>
diff mbox

Patch

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