Richard Biener <rguent...@suse.de> writes:
> diff --git a/gcc/hwint.h b/gcc/hwint.h
> index 127b0130c66..8812bc7150f 100644
> --- a/gcc/hwint.h
> +++ b/gcc/hwint.h
> @@ -333,4 +333,46 @@ absu_hwi (HOST_WIDE_INT x)
>    return x >= 0 ? (unsigned HOST_WIDE_INT)x : -(unsigned HOST_WIDE_INT)x;
>  }
>  
> +/* Compute the sum of signed A and B and indicate in *OVERFLOW whether
> +   that operation overflowed.  */
> +
> +inline HOST_WIDE_INT
> +add_hwi (HOST_WIDE_INT a, HOST_WIDE_INT b, bool *overflow)
> +{
> +#if GCC_VERSION < 11000
> +  unsigned HOST_WIDE_INT result = a + b;

Sorry for the late comment, but shouldn't this cast a or b to
unsigned HOST_WIDE_INT?

Thanks,
Richard

> +  if ((((result ^ a) & (result ^ b))
> +       >> (HOST_BITS_PER_WIDE_INT - 1)) & 1)
> +    *overflow = true;
> +  else
> +    *overflow = false;
> +  return result;
> +#else
> +  HOST_WIDE_INT result;
> +  *overflow = __builtin_add_overflow (a, b, &result);
> +  return result;
> +#endif
> +}
> +
> +/* Compute the product of signed A and B and indicate in *OVERFLOW whether
> +   that operation overflowed.  */
> +
> +inline HOST_WIDE_INT
> +mul_hwi (HOST_WIDE_INT a, HOST_WIDE_INT b, bool *overflow)
> +{
> +#if GCC_VERSION < 11000
> +  unsigned HOST_WIDE_INT result = a * (unsigned HOST_WIDE_INT)b;
> +  if ((a == -1 && b == HOST_WIDE_INT_MIN)
> +      || (a != 0 && (HOST_WIDE_INT)result / a != b))
> +    *overflow = true;
> +  else
> +    *overflow = false;
> +  return result;
> +#else
> +  HOST_WIDE_INT result;
> +  *overflow = __builtin_mul_overflow (a, b, &result);
> +  return result;
> +#endif
> +}
> +
>  #endif /* ! GCC_HWINT_H */
> diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
> index 9d07b415e9d..d19c5eb51e4 100644
> --- a/gcc/tree-data-ref.c
> +++ b/gcc/tree-data-ref.c
> @@ -3924,9 +3924,25 @@ initialize_matrix_A (lambda_matrix A, tree chrec, 
> unsigned index, int mult)
>    switch (TREE_CODE (chrec))
>      {
>      case POLYNOMIAL_CHREC:
> -      if (!cst_and_fits_in_hwi (CHREC_RIGHT (chrec)))
> +      /* CHREC_RIGHT and its negated value should fit in a lambda_int.
> +      Pointer typed chrecs right are to be interpreted signed.  */
> +      HOST_WIDE_INT chrec_right;
> +      if (POINTER_TYPE_P (chrec_type (chrec)))
> +     {
> +       if (!cst_and_fits_in_hwi (CHREC_RIGHT (chrec)))
> +         return chrec_dont_know;
> +       chrec_right = int_cst_value (CHREC_RIGHT (chrec));
> +     }
> +      else
> +     {
> +       if (!tree_fits_shwi_p (CHREC_RIGHT (chrec)))
> +         return chrec_dont_know;
> +       chrec_right = tree_to_shwi (CHREC_RIGHT (chrec));
> +     }
> +      /* We want to be able to negate without overflow.  */
> +      if (chrec_right == HOST_WIDE_INT_MIN)
>       return chrec_dont_know;
> -      A[index][0] = mult * int_cst_value (CHREC_RIGHT (chrec));
> +      A[index][0] = mult * chrec_right;
>        return initialize_matrix_A (A, CHREC_LEFT (chrec), index + 1, mult);
>  
>      case PLUS_EXPR:
> @@ -4193,17 +4209,28 @@ lambda_vector_first_nz (lambda_vector vec1, int n, 
> int start)
>  /* Add a multiple of row R1 of matrix MAT with N columns to row R2:
>     R2 = R2 + CONST1 * R1.  */
>  
> -static void
> +static bool
>  lambda_matrix_row_add (lambda_matrix mat, int n, int r1, int r2,
>                      lambda_int const1)
>  {
>    int i;
>  
>    if (const1 == 0)
> -    return;
> +    return true;
>  
>    for (i = 0; i < n; i++)
> -    mat[r2][i] += const1 * mat[r1][i];
> +    {
> +      bool ovf;
> +      lambda_int tem = mul_hwi (mat[r1][i], const1, &ovf);
> +      if (ovf)
> +     return false;
> +      lambda_int tem2 = add_hwi (mat[r2][i], tem, &ovf);
> +      if (ovf || tem2 == HOST_WIDE_INT_MIN)
> +     return false;
> +      mat[r2][i] = tem2;
> +    }
> +
> +  return true;
>  }
>  
>  /* Multiply vector VEC1 of length SIZE by a constant CONST1,
> @@ -4258,7 +4285,7 @@ lambda_vector_equal (lambda_vector vec1, lambda_vector 
> vec2, int size)
>     Ref: Algorithm 2.1 page 33 in "Loop Transformations for
>     Restructuring Compilers" Utpal Banerjee.  */
>  
> -static void
> +static bool
>  lambda_matrix_right_hermite (lambda_matrix A, int m, int n,
>                            lambda_matrix S, lambda_matrix U)
>  {
> @@ -4276,24 +4303,26 @@ lambda_matrix_right_hermite (lambda_matrix A, int m, 
> int n,
>           {
>             while (S[i][j] != 0)
>               {
> -               lambda_int sigma, factor, a, b;
> +               lambda_int factor, a, b;
>  
>                 a = S[i-1][j];
>                 b = S[i][j];
> -               sigma = ((a < 0) ^ (b < 0)) ? -1: 1;
> -               unsigned HOST_WIDE_INT abs_a = absu_hwi (a);
> -               unsigned HOST_WIDE_INT abs_b = absu_hwi (b);
> -               factor = sigma * (lambda_int)(abs_a / abs_b);
> +               gcc_assert (a != HOST_WIDE_INT_MIN);
> +               factor = a / b;
>  
> -               lambda_matrix_row_add (S, n, i, i-1, -factor);
> +               if (!lambda_matrix_row_add (S, n, i, i-1, -factor))
> +                 return false;
>                 std::swap (S[i], S[i-1]);
>  
> -               lambda_matrix_row_add (U, m, i, i-1, -factor);
> +               if (!lambda_matrix_row_add (U, m, i, i-1, -factor))
> +                 return false;
>                 std::swap (U[i], U[i-1]);
>               }
>           }
>       }
>      }
> +
> +  return true;
>  }
>  
>  /* Determines the overlapping elements due to accesses CHREC_A and
> @@ -4410,7 +4439,13 @@ analyze_subscript_affine_affine (tree chrec_a,
>      }
>  
>    /* U.A = S */
> -  lambda_matrix_right_hermite (A, dim, 1, S, U);
> +  if (!lambda_matrix_right_hermite (A, dim, 1, S, U))
> +    {
> +      *overlaps_a = conflict_fn_not_known ();
> +      *overlaps_b = conflict_fn_not_known ();
> +      *last_conflicts = chrec_dont_know;
> +      goto end_analyze_subs_aa;
> +    }
>  
>    if (S[0][0] < 0)
>      {

Reply via email to