On Thu, Jan 14, 2016 at 8:38 AM, Jeff Law <l...@redhat.com> wrote:
>
> As noted in the BZ, DOM does not exploit VRP information to create
> additional equivalences in the arms of conditionals.
>
> This can cause DOM to miss relatively simple optimizations that show up in
> the adpcm benchmark as well as within GCC itself.
>
> The fix is quite simple -- we just need to extend the code which used the
> implicit range of booleans to propagate on both sides of equality
> conditionals to use VRP information as well.
>
> Once done we also need to make sure to convert the true/false value we're
> propagating to the right type.  Again, trivial.
>
> The testcase is derived from the adpcm benchmark.  It checks that we
> optimize away the bit-xor on both arms of the conditional and that in turn
> allows other values to be discovered as constants.
>
> Bootstrapped and regression tested on x86_64.  Installed on the trunk.
>
>
>
> Jeff
>
> commit e9d42e91d1e88ece5be38dbde81843e516b327e0
> Author: Jeff Law <l...@redhat.com>
> Date:   Thu Jan 14 00:37:37 2016 -0700
>
>     [PATCH][PR tree-optimization/69270] Exploit VRP information in DOM
>
>         PR tree-optimization/69270
>         * tree-ssa-dom.c (ssa_name_has_boolean_range): New function.
>         (record_edge_info): Use it.  Convert boolean_{true,false}_node
>         to the type of op0.
>
>         PR tree-optimization/69270
>         * gcc.dg/tree-ssa/pr69270.c: New test.
>
> diff --git a/gcc/ChangeLog b/gcc/ChangeLog
> index dc13621..40e3dfb 100644
> --- a/gcc/ChangeLog
> +++ b/gcc/ChangeLog
> @@ -1,3 +1,10 @@
> +2016-01-14  Jeff Law  <l...@redhat.com>
> +
> +       PR tree-optimization/69270
> +       * tree-ssa-dom.c (ssa_name_has_boolean_range): New function.
> +       (record_edge_info): Use it.  Convert boolean_{true,false}_node
> +       to the type of op0.
> +
>  2016-01-13  Jan Hubicka  <hubi...@ucw.cz>
>
>         PR ipa/66487
> diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
> index f393e25..63976ea 100644
> --- a/gcc/testsuite/ChangeLog
> +++ b/gcc/testsuite/ChangeLog
> @@ -1,3 +1,8 @@
> +2016-01-14  Jeff Law  <l...@redhat.com>
> +
> +       PR tree-optimization/69270
> +       * gcc.dg/tree-ssa/pr69270.c: New test.
> +
>  2016-01-13  Bernd Schmidt  <bschm...@redhat.com>
>
>         PR c/66208
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr69270.c
> b/gcc/testsuite/gcc.dg/tree-ssa/pr69270.c
> new file mode 100644
> index 0000000..529b521
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr69270.c
> @@ -0,0 +1,42 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fsplit-paths -fdump-tree-dom3-details" } */
> +
> +/* There should be two references to bufferstep that turn into
> +   constants.  */
> +/* { dg-final { scan-tree-dump-times "Replaced .bufferstep_\[0-9\]+. with
> constant .0." 1 "dom3"} } */
> +/* { dg-final { scan-tree-dump-times "Replaced .bufferstep_\[0-9\]+. with
> constant .1." 1 "dom3"} } */
> +
> +/* And some assignments ought to fold down to constants.  */
> +/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 1;" 2 "dom3"}
> } */
> +/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 0;" 2 "dom3"}
> } */
> +
> +/* The XOR operations should have been optimized to constants.  */
> +/* { dg-final { scan-tree-dump-not "bit_xor" "dom3"} } */
> +
> +
> +extern int *stepsizeTable;
> +
> +void
> +adpcm_coder (signed char *outdata, int len)
> +{
> +  signed char *outp;
> +  int delta;
> +  int outputbuffer;
> +  int bufferstep = 0;
> +  outp = (signed char *) outdata;
> +  int step = 0;
> +  int index = 0;
> +  int diff = 0;
> +  for (; len > 0; len--)
> +    {
> +      delta = 0;
> +      if (diff >= step)
> +       delta = 4;
> +      step = stepsizeTable[index];
> +      if (bufferstep)
> +       outputbuffer = (delta << 4) & 0xf0;
> +      else
> +       *outp++ = (delta & 0x0f) | outputbuffer;
> +      bufferstep = !bufferstep;
> +    }
> +}
> diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
> index 9d2e189..a9abed9 100644
> --- a/gcc/tree-ssa-dom.c
> +++ b/gcc/tree-ssa-dom.c
> @@ -316,6 +316,38 @@ record_conditions (struct edge_info *edge_info, tree
> cond, tree inverted)
>    edge_info->cond_equivalences.safe_push (c);
>  }
>
> +/* Return TRUE is OP, an SSA_NAME has a range of values [0..1], false
> +   otherwise.
> +
> +   This can be because it is a boolean type, any type with
> +   a single bit of precision, or has known range of values
> +   it might old of [0..1] via VRP analysis.  */
> +
> +static bool
> +ssa_name_has_boolean_range (tree op)
> +{
> +  /* Boolean types always have a range [0..1].  */
> +  if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE)
> +    return true;
> +
> +  /* An integral type with a single bit of precision.  */
> +  if (INTEGRAL_TYPE_P (TREE_TYPE (op))
> +      && TYPE_PRECISION (TREE_TYPE (op)) == 1)
> +    return true;
> +
> +  /* An integral type with more precision, but the object
> +     only takes on values [0..1] as determined by VRP
> +     analysis.  */
> +  wide_int min, max;
> +  if (INTEGRAL_TYPE_P (TREE_TYPE (op))
> +      && get_range_info (op, &min, &max) == VR_RANGE
> +      && wi::eq_p (min, 0)
> +      && wi::eq_p (max, 1))
> +    return true;
> +
> +  return false;
> +}
> +
>  /* We have finished optimizing BB, record any information implied by
>     taking a specific outgoing edge from BB.  */
>
> @@ -390,36 +422,32 @@ record_edge_info (basic_block bb)
>               can record an equivalence for OP0 rather than COND.  */
>            if ((code == EQ_EXPR || code == NE_EXPR)
>                && TREE_CODE (op0) == SSA_NAME
> -              && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE
> +             && ssa_name_has_boolean_range (op0)
>                && is_gimple_min_invariant (op1))
>              {
> +             tree true_val = fold_convert (TREE_TYPE (op0),
> +                                           boolean_true_node);
> +             tree false_val = fold_convert (TREE_TYPE (op0),
> +                                            boolean_false_node);

Apart from what Jakub said we have constant_boolean_node for this,

  true_val = constant_boolean_node (true, TREE_TYPE (op0));
...

>                if (code == EQ_EXPR)
>                  {
>                    edge_info = allocate_edge_info (true_edge);
>                    edge_info->lhs = op0;
> -                  edge_info->rhs = (integer_zerop (op1)
> -                                    ? boolean_false_node
> -                                    : boolean_true_node);
> +                  edge_info->rhs = (integer_zerop (op1) ? false_val :
> true_val);
>
>                    edge_info = allocate_edge_info (false_edge);
>                    edge_info->lhs = op0;
> -                  edge_info->rhs = (integer_zerop (op1)
> -                                    ? boolean_true_node
> -                                    : boolean_false_node);
> +                  edge_info->rhs = (integer_zerop (op1) ? true_val :
> false_val);
>                  }
>                else
>                  {
>                    edge_info = allocate_edge_info (true_edge);
>                    edge_info->lhs = op0;
> -                  edge_info->rhs = (integer_zerop (op1)
> -                                    ? boolean_true_node
> -                                    : boolean_false_node);
> +                  edge_info->rhs = (integer_zerop (op1) ? true_val :
> false_val);
>
>                    edge_info = allocate_edge_info (false_edge);
>                    edge_info->lhs = op0;
> -                  edge_info->rhs = (integer_zerop (op1)
> -                                    ? boolean_false_node
> -                                    : boolean_true_node);
> +                  edge_info->rhs = (integer_zerop (op1) ? false_val :
> true_val);
>                  }
>              }
>            else if (is_gimple_min_invariant (op0)
>

Reply via email to