261cdd2319
The following tries to handle overflow in the integer computations done by lambda ops of dependence analysis by failing instead of silently continuing with overflowed values. It also avoids treating large unsigned CHREC_RIGHT as negative unless the chrec is of pointer type and avoids the most negative integer value to avoid excessive overflow checking (with this the fix for PR98758 can be partly simplified as seen). I've added add_hwi and mul_hwi functions computing HOST_WIDE_INT signed sum and product with indicating overflow, they hopefully get matched to the appropriate internal functions. I don't have any testcases triggering overflow in any of the guarded computations. 2021-01-20 Richard Biener <rguenther@suse.de> * hwint.h (add_hwi): New function. (mul_hwi): Likewise. * tree-data-ref.c (initialize_matrix_A): Properly translate tree constants and avoid HOST_WIDE_INT_MIN. (lambda_matrix_row_add): Avoid undefined integer overflow and return true on such overflow. (lambda_matrix_right_hermite): Handle overflow from lambda_matrix_row_add gracefully. Simplify previous fix. (analyze_subscript_affine_affine): Likewise.
379 lines
11 KiB
C
379 lines
11 KiB
C
/* HOST_WIDE_INT definitions for the GNU compiler.
|
|
Copyright (C) 1998-2021 Free Software Foundation, Inc.
|
|
|
|
This file is part of GCC.
|
|
|
|
Provide definitions for macros which depend on HOST_BITS_PER_INT
|
|
and HOST_BITS_PER_LONG. */
|
|
|
|
#ifndef GCC_HWINT_H
|
|
#define GCC_HWINT_H
|
|
|
|
/* This describes the machine the compiler is hosted on. */
|
|
#define HOST_BITS_PER_CHAR CHAR_BIT
|
|
#define HOST_BITS_PER_SHORT (CHAR_BIT * SIZEOF_SHORT)
|
|
#define HOST_BITS_PER_INT (CHAR_BIT * SIZEOF_INT)
|
|
#define HOST_BITS_PER_LONG (CHAR_BIT * SIZEOF_LONG)
|
|
#define HOST_BITS_PER_PTR (CHAR_BIT * SIZEOF_VOID_P)
|
|
|
|
/* The string that should be inserted into a printf style format to
|
|
indicate a "long" operand. */
|
|
#ifndef HOST_LONG_FORMAT
|
|
#define HOST_LONG_FORMAT "l"
|
|
#endif
|
|
|
|
/* The string that should be inserted into a printf style format to
|
|
indicate a "long long" operand. */
|
|
#ifndef HOST_LONG_LONG_FORMAT
|
|
#define HOST_LONG_LONG_FORMAT "ll"
|
|
#endif
|
|
|
|
/* If HAVE_LONG_LONG and SIZEOF_LONG_LONG aren't defined, but
|
|
GCC_VERSION >= 3000, assume this is the second or later stage of a
|
|
bootstrap, we do have long long, and it's 64 bits. (This is
|
|
required by C99; we do have some ports that violate that assumption
|
|
but they're all cross-compile-only.) Just in case, force a
|
|
constraint violation if that assumption is incorrect. */
|
|
#if !defined HAVE_LONG_LONG
|
|
# if GCC_VERSION >= 3000
|
|
# define HAVE_LONG_LONG 1
|
|
# define SIZEOF_LONG_LONG 8
|
|
extern char sizeof_long_long_must_be_8[sizeof (long long) == 8 ? 1 : -1];
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef HAVE_LONG_LONG
|
|
# define HOST_BITS_PER_LONGLONG (CHAR_BIT * SIZEOF_LONG_LONG)
|
|
#endif
|
|
|
|
/* Set HOST_WIDE_INT, this should be always 64 bits.
|
|
The underlying type is matched to that of int64_t and assumed
|
|
to be either long or long long. */
|
|
|
|
#define HOST_BITS_PER_WIDE_INT 64
|
|
#if INT64_T_IS_LONG
|
|
# define HOST_WIDE_INT long
|
|
# define HOST_WIDE_INT_C(X) X ## L
|
|
#else
|
|
# if HOST_BITS_PER_LONGLONG == 64
|
|
# define HOST_WIDE_INT long long
|
|
# define HOST_WIDE_INT_C(X) X ## LL
|
|
# else
|
|
#error "Unable to find a suitable type for HOST_WIDE_INT"
|
|
# endif
|
|
#endif
|
|
|
|
#define HOST_WIDE_INT_UC(X) HOST_WIDE_INT_C (X ## U)
|
|
#define HOST_WIDE_INT_0 HOST_WIDE_INT_C (0)
|
|
#define HOST_WIDE_INT_0U HOST_WIDE_INT_UC (0)
|
|
#define HOST_WIDE_INT_1 HOST_WIDE_INT_C (1)
|
|
#define HOST_WIDE_INT_1U HOST_WIDE_INT_UC (1)
|
|
#define HOST_WIDE_INT_M1 HOST_WIDE_INT_C (-1)
|
|
#define HOST_WIDE_INT_M1U HOST_WIDE_INT_UC (-1)
|
|
|
|
/* This is a magic identifier which allows GCC to figure out the type
|
|
of HOST_WIDE_INT for %wd specifier checks. You must issue this
|
|
typedef before using the __asm_fprintf__ format attribute. */
|
|
typedef HOST_WIDE_INT __gcc_host_wide_int__;
|
|
|
|
/* Provide C99 <inttypes.h> style format definitions for 64bits. */
|
|
#ifndef HAVE_INTTYPES_H
|
|
#if INT64_T_IS_LONG
|
|
# define GCC_PRI64 HOST_LONG_FORMAT
|
|
#else
|
|
# define GCC_PRI64 HOST_LONG_LONG_FORMAT
|
|
#endif
|
|
#undef PRId64
|
|
#define PRId64 GCC_PRI64 "d"
|
|
#undef PRIi64
|
|
#define PRIi64 GCC_PRI64 "i"
|
|
#undef PRIo64
|
|
#define PRIo64 GCC_PRI64 "o"
|
|
#undef PRIu64
|
|
#define PRIu64 GCC_PRI64 "u"
|
|
#undef PRIx64
|
|
#define PRIx64 GCC_PRI64 "x"
|
|
#undef PRIX64
|
|
#define PRIX64 GCC_PRI64 "X"
|
|
#endif
|
|
|
|
/* Various printf format strings for HOST_WIDE_INT. */
|
|
|
|
#if INT64_T_IS_LONG
|
|
# define HOST_WIDE_INT_PRINT HOST_LONG_FORMAT
|
|
# define HOST_WIDE_INT_PRINT_C "L"
|
|
#else
|
|
# define HOST_WIDE_INT_PRINT HOST_LONG_LONG_FORMAT
|
|
# define HOST_WIDE_INT_PRINT_C "LL"
|
|
#endif
|
|
|
|
#define HOST_WIDE_INT_PRINT_DEC "%" PRId64
|
|
#define HOST_WIDE_INT_PRINT_DEC_C "%" PRId64 HOST_WIDE_INT_PRINT_C
|
|
#define HOST_WIDE_INT_PRINT_UNSIGNED "%" PRIu64
|
|
#define HOST_WIDE_INT_PRINT_HEX "%#" PRIx64
|
|
#define HOST_WIDE_INT_PRINT_HEX_PURE "%" PRIx64
|
|
#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%" PRIx64 "%016" PRIx64
|
|
#define HOST_WIDE_INT_PRINT_PADDED_HEX "%016" PRIx64
|
|
|
|
/* Define HOST_WIDEST_FAST_INT to the widest integer type supported
|
|
efficiently in hardware. (That is, the widest integer type that fits
|
|
in a hardware register.) Normally this is "long" but on some hosts it
|
|
should be "long long" or "__int64". This is no convenient way to
|
|
autodetect this, so such systems must set a flag in config.host; see there
|
|
for details. */
|
|
|
|
#ifdef USE_LONG_LONG_FOR_WIDEST_FAST_INT
|
|
# ifdef HAVE_LONG_LONG
|
|
# define HOST_WIDEST_FAST_INT long long
|
|
# define HOST_BITS_PER_WIDEST_FAST_INT HOST_BITS_PER_LONGLONG
|
|
# else
|
|
# error "Your host said it wanted to use long long but that does not exist"
|
|
# endif
|
|
#else
|
|
# define HOST_WIDEST_FAST_INT long
|
|
# define HOST_BITS_PER_WIDEST_FAST_INT HOST_BITS_PER_LONG
|
|
#endif
|
|
|
|
/* Inline functions operating on HOST_WIDE_INT. */
|
|
|
|
/* Return X with all but the lowest bit masked off. */
|
|
|
|
static inline unsigned HOST_WIDE_INT
|
|
least_bit_hwi (unsigned HOST_WIDE_INT x)
|
|
{
|
|
return (x & -x);
|
|
}
|
|
|
|
/* True if X is zero or a power of two. */
|
|
|
|
static inline bool
|
|
pow2_or_zerop (unsigned HOST_WIDE_INT x)
|
|
{
|
|
return least_bit_hwi (x) == x;
|
|
}
|
|
|
|
/* True if X is a power of two. */
|
|
|
|
static inline bool
|
|
pow2p_hwi (unsigned HOST_WIDE_INT x)
|
|
{
|
|
return x && pow2_or_zerop (x);
|
|
}
|
|
|
|
#if GCC_VERSION < 3004
|
|
|
|
extern int clz_hwi (unsigned HOST_WIDE_INT x);
|
|
extern int ctz_hwi (unsigned HOST_WIDE_INT x);
|
|
extern int ffs_hwi (unsigned HOST_WIDE_INT x);
|
|
|
|
/* Return the number of set bits in X. */
|
|
extern int popcount_hwi (unsigned HOST_WIDE_INT x);
|
|
|
|
/* Return log2, or -1 if not exact. */
|
|
extern int exact_log2 (unsigned HOST_WIDE_INT);
|
|
|
|
/* Return floor of log2, with -1 for zero. */
|
|
extern int floor_log2 (unsigned HOST_WIDE_INT);
|
|
|
|
/* Return the smallest n such that 2**n >= X. */
|
|
extern int ceil_log2 (unsigned HOST_WIDE_INT);
|
|
|
|
#else /* GCC_VERSION >= 3004 */
|
|
|
|
/* For convenience, define 0 -> word_size. */
|
|
static inline int
|
|
clz_hwi (unsigned HOST_WIDE_INT x)
|
|
{
|
|
if (x == 0)
|
|
return HOST_BITS_PER_WIDE_INT;
|
|
# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
|
|
return __builtin_clzl (x);
|
|
# elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
|
|
return __builtin_clzll (x);
|
|
# else
|
|
return __builtin_clz (x);
|
|
# endif
|
|
}
|
|
|
|
static inline int
|
|
ctz_hwi (unsigned HOST_WIDE_INT x)
|
|
{
|
|
if (x == 0)
|
|
return HOST_BITS_PER_WIDE_INT;
|
|
# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
|
|
return __builtin_ctzl (x);
|
|
# elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
|
|
return __builtin_ctzll (x);
|
|
# else
|
|
return __builtin_ctz (x);
|
|
# endif
|
|
}
|
|
|
|
static inline int
|
|
ffs_hwi (unsigned HOST_WIDE_INT x)
|
|
{
|
|
# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
|
|
return __builtin_ffsl (x);
|
|
# elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
|
|
return __builtin_ffsll (x);
|
|
# else
|
|
return __builtin_ffs (x);
|
|
# endif
|
|
}
|
|
|
|
static inline int
|
|
popcount_hwi (unsigned HOST_WIDE_INT x)
|
|
{
|
|
# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
|
|
return __builtin_popcountl (x);
|
|
# elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
|
|
return __builtin_popcountll (x);
|
|
# else
|
|
return __builtin_popcount (x);
|
|
# endif
|
|
}
|
|
|
|
static inline int
|
|
floor_log2 (unsigned HOST_WIDE_INT x)
|
|
{
|
|
return HOST_BITS_PER_WIDE_INT - 1 - clz_hwi (x);
|
|
}
|
|
|
|
static inline int
|
|
ceil_log2 (unsigned HOST_WIDE_INT x)
|
|
{
|
|
return x == 0 ? 0 : floor_log2 (x - 1) + 1;
|
|
}
|
|
|
|
static inline int
|
|
exact_log2 (unsigned HOST_WIDE_INT x)
|
|
{
|
|
return pow2p_hwi (x) ? ctz_hwi (x) : -1;
|
|
}
|
|
|
|
#endif /* GCC_VERSION >= 3004 */
|
|
|
|
#define HOST_WIDE_INT_MIN (HOST_WIDE_INT) \
|
|
(HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1))
|
|
#define HOST_WIDE_INT_MAX (~(HOST_WIDE_INT_MIN))
|
|
|
|
extern HOST_WIDE_INT abs_hwi (HOST_WIDE_INT);
|
|
extern unsigned HOST_WIDE_INT absu_hwi (HOST_WIDE_INT);
|
|
extern HOST_WIDE_INT gcd (HOST_WIDE_INT, HOST_WIDE_INT);
|
|
extern HOST_WIDE_INT pos_mul_hwi (HOST_WIDE_INT, HOST_WIDE_INT);
|
|
extern HOST_WIDE_INT mul_hwi (HOST_WIDE_INT, HOST_WIDE_INT);
|
|
extern HOST_WIDE_INT least_common_multiple (HOST_WIDE_INT, HOST_WIDE_INT);
|
|
|
|
/* Like ctz_hwi, except 0 when x == 0. */
|
|
|
|
static inline int
|
|
ctz_or_zero (unsigned HOST_WIDE_INT x)
|
|
{
|
|
return ffs_hwi (x) - 1;
|
|
}
|
|
|
|
/* Sign extend SRC starting from PREC. */
|
|
|
|
static inline HOST_WIDE_INT
|
|
sext_hwi (HOST_WIDE_INT src, unsigned int prec)
|
|
{
|
|
if (prec == HOST_BITS_PER_WIDE_INT)
|
|
return src;
|
|
else
|
|
#if defined (__GNUC__)
|
|
{
|
|
/* Take the faster path if the implementation-defined bits it's relying
|
|
on are implemented the way we expect them to be. Namely, conversion
|
|
from unsigned to signed preserves bit pattern, and right shift of
|
|
a signed value propagates the sign bit.
|
|
We have to convert from signed to unsigned and back, because when left
|
|
shifting signed values, any overflow is undefined behavior. */
|
|
gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT);
|
|
int shift = HOST_BITS_PER_WIDE_INT - prec;
|
|
return ((HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) src << shift)) >> shift;
|
|
}
|
|
#else
|
|
{
|
|
/* Fall back to the slower, well defined path otherwise. */
|
|
gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT);
|
|
HOST_WIDE_INT sign_mask = HOST_WIDE_INT_1 << (prec - 1);
|
|
HOST_WIDE_INT value_mask = (HOST_WIDE_INT_1U << prec) - HOST_WIDE_INT_1U;
|
|
return (((src & value_mask) ^ sign_mask) - sign_mask);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Zero extend SRC starting from PREC. */
|
|
static inline unsigned HOST_WIDE_INT
|
|
zext_hwi (unsigned HOST_WIDE_INT src, unsigned int prec)
|
|
{
|
|
if (prec == HOST_BITS_PER_WIDE_INT)
|
|
return src;
|
|
else
|
|
{
|
|
gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT);
|
|
return src & ((HOST_WIDE_INT_1U << prec) - 1);
|
|
}
|
|
}
|
|
|
|
/* Compute the absolute value of X. */
|
|
|
|
inline HOST_WIDE_INT
|
|
abs_hwi (HOST_WIDE_INT x)
|
|
{
|
|
gcc_checking_assert (x != HOST_WIDE_INT_MIN);
|
|
return x >= 0 ? x : -x;
|
|
}
|
|
|
|
/* Compute the absolute value of X as an unsigned type. */
|
|
|
|
inline unsigned HOST_WIDE_INT
|
|
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 + (unsigned HOST_WIDE_INT)b;
|
|
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 */
|