On 10/11/18 6:56 AM, Martin Liška wrote:
> Hi.
> 
> As seen in the PR, switch conversion can do better when we return equal 
> numbers
> based on index value. I implemented more than that, more precisely I support 
> all linear
> transformation based on index value. It's the same what clang is capable of.
> 
> Patch survives testing on x86_64-linux-gnu. I added various tests that should
> benefit of the transformation.
> 
> Thanks,
> Martin
> 
> gcc/ChangeLog:
> 
> 2018-10-11  Martin Liska  <mli...@suse.cz>
> 
>       PR tree-optimization/84436
>       * tree-switch-conversion.c (switch_conversion::contains_same_values_p):
>       Remove.
>       (switch_conversion::contains_linear_function_p): New.
>       (switch_conversion::build_one_array): Support linear
>       transformation on input.
>       * tree-switch-conversion.h (struct switch_conversion): Add
>       contains_linear_function_p declaration.
> 
> gcc/testsuite/ChangeLog:
> 
> 2018-10-11  Martin Liska  <mli...@suse.cz>
> 
>       PR tree-optimization/84436
>       * gcc.dg/tree-ssa/pr84436-1.c: New test.
>       * gcc.dg/tree-ssa/pr84436-2.c: New test.
>       * gcc.dg/tree-ssa/pr84436-3.c: New test.
>       * gcc.dg/tree-ssa/pr84436-4.c: New test.
>       * gcc.dg/tree-ssa/pr84436-5.c: New test.
> ---
> 
> 
> 
> diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
> index 64169a6cd3d..8f34ab45cb9 100644
> --- a/gcc/tree-switch-conversion.c
> +++ b/gcc/tree-switch-conversion.c
> @@ -439,25 +439,63 @@ switch_conversion::build_constructors ()
>      }
>  }
>  
> -/* If all values in the constructor vector are the same, return the value.
> -   Otherwise return NULL_TREE.  Not supposed to be called for empty
> -   vectors.  */
> +/* If all values in the constructor vector are products of a linear function
> +   a * x + b, then return true.  When true, COEFF_A and COEFF_B and
> +   coefficients of the linear function.  Note that equal values are special
> +   case of a linear function with a and b equal to zero.  */
>  
> -tree
> -switch_conversion::contains_same_values_p (vec<constructor_elt, va_gc> *vec)
> +bool
> +switch_conversion::contains_linear_function_p (vec<constructor_elt, va_gc> 
> *vec,
> +                                            wide_int *coeff_a,
> +                                            wide_int *coeff_b)
>  {
>    unsigned int i;
> -  tree prev = NULL_TREE;
>    constructor_elt *elt;
>  
> +  gcc_assert (vec->length () >= 2);
> +
> +  /* Let's try to find any linear function a.x + y that can apply to
> +     given values. 'a' can be calculated as follows:
> +
> +     a = (y2 - y1) / (x2 - x1) where x2 - x1 = 1 (consecutive case indices)
> +     a = y2 - y1
> +
> +     and
> +
> +     b = y2 - a * x2
> +
> +  */
> +
> +  tree elt0 = (*vec)[0].value;
> +  tree elt1 = (*vec)[1].value;
> +
> +  if (TREE_CODE (elt0) != INTEGER_CST || TREE_CODE (elt1) != INTEGER_CST)
> +    return false;
> +
> +  wide_int range_min = wi::to_wide (fold_convert (TREE_TYPE (elt0),
> +                                               m_range_min));
> +  wide_int y1 = wi::to_wide (elt0);
> +  wide_int y2 = wi::to_wide (elt1);
> +  wide_int a = y2 - y1;
> +  wide_int b = y2 - a * (range_min + 1);
> +
> +  /* Verify that all values fulfill the linear function.  */
>    FOR_EACH_VEC_SAFE_ELT (vec, i, elt)
>      {
> -      if (!prev)
> -     prev = elt->value;
> -      else if (!operand_equal_p (elt->value, prev, OEP_ONLY_CONST))
> -     return NULL_TREE;
> +      if (TREE_CODE (elt->value) != INTEGER_CST)
> +     return false;
> +
> +      wide_int value = wi::to_wide (elt->value);
> +      if (a * range_min + b != value)
> +     return false;
ISTM that if we overflow the ax + b, then we're not going to be equal to
value here, right?  I think Jakub and at least someone else was
concerned about that possibility.

Assuming overflow isn't a problem, this is OK.

jeff

Reply via email to