diff --git a/libavutil/attributes.h b/libavutil/attributes.h index ced108aa2c75afdf467f91a3faa1cb05af6e9726..ab2a1fdd0e176b93775953f92c7cb80afde515be 100644 --- a/libavutil/attributes.h +++ b/libavutil/attributes.h @@ -34,6 +34,12 @@ # define AV_GCC_VERSION_AT_MOST(x,y) 0 #endif +#ifdef __has_builtin +# define AV_HAS_BUILTIN(x) __has_builtin(x) +#else +# define AV_HAS_BUILTIN(x) false +#endif + #ifndef av_always_inline #if AV_GCC_VERSION_AT_LEAST(3,1) # define av_always_inline __attribute__((always_inline)) inline diff --git a/libavutil/common.h b/libavutil/common.h index 7a774fc448b74f4473240d9d5d1835527213cc49..2777cea9f9bbad7e3b5b46ec5dfc9524dcaf04bc 100644 --- a/libavutil/common.h +++ b/libavutil/common.h @@ -299,11 +299,16 @@ static av_always_inline int av_sat_dsub32_c(int a, int b) * @return sum with signed saturation */ static av_always_inline int64_t av_sat_add64_c(int64_t a, int64_t b) { +#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_add_overflow) + int64_t tmp; + return !__builtin_add_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN); +#else if (b >= 0 && a >= INT64_MAX - b) return INT64_MAX; if (b <= 0 && a <= INT64_MIN - b) return INT64_MIN; return a + b; +#endif } /** @@ -314,11 +319,16 @@ static av_always_inline int64_t av_sat_add64_c(int64_t a, int64_t b) { * @return difference with signed saturation */ static av_always_inline int64_t av_sat_sub64_c(int64_t a, int64_t b) { +#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_sub_overflow) + int64_t tmp; + return !__builtin_sub_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN); +#else if (b <= 0 && a >= INT64_MAX + b) return INT64_MAX; if (b >= 0 && a <= INT64_MIN + b) return INT64_MIN; return a - b; +#endif } /**