qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 03/72] qemu/host-utils: Add wrappers for carry builtins


From: Alex Bennée
Subject: Re: [PATCH 03/72] qemu/host-utils: Add wrappers for carry builtins
Date: Mon, 10 May 2021 13:57:58 +0100
User-agent: mu4e 1.5.13; emacs 28.0.50

Richard Henderson <richard.henderson@linaro.org> writes:

> These builtins came in clang 3.8, but are not present in gcc through
> version 11.  Even in clang the optimization is not ideal except for
> x86_64, but no worse than the hand-coding that we currently do.

Given this statement....

<snip>
> +/**
> + * uadd64_carry - addition with carry-in and carry-out
> + * @x, @y: addends
> + * @pcarry: in-out carry value
> + *
> + * Computes @x + @y + *@pcarry, placing the carry-out back
> + * into *@pcarry and returning the 64-bit sum.
> + */
> +static inline uint64_t uadd64_carry(uint64_t x, uint64_t y, bool *pcarry)
> +{
> +#if __has_builtin(__builtin_addcll)
> +    unsigned long long c = *pcarry;
> +    x = __builtin_addcll(x, y, c, &c);

what happens when unsigned long long isn't the same as uint64_t? Doesn't
C99 only specify a minimum?

> +    *pcarry = c & 1;

Why do we need to clamp it here? Shouldn't the compiler automatically do
that due to the bool?

> +    return x;
> +#else
> +    bool c = *pcarry;
> +    /* This is clang's internal expansion of __builtin_addc. */
> +    c = uadd64_overflow(x, c, &x);
> +    c |= uadd64_overflow(x, y, &x);
> +    *pcarry = c;
> +    return x;
> +#endif

Either way if you aren't super happy with the compilers builtin and you
get equivalent code with the unambigious hand coded version then what is
the point of having a builtin leg?

> +}
> +
> +/**
> + * usub64_borrow - subtraction with borrow-in and borrow-out
> + * @x, @y: addends
> + * @pborrow: in-out borrow value
> + *
> + * Computes @x - @y - *@pborrow, placing the borrow-out back
> + * into *@pborrow and returning the 64-bit sum.
> + */
> +static inline uint64_t usub64_borrow(uint64_t x, uint64_t y, bool *pborrow)
> +{
> +#if __has_builtin(__builtin_subcll)
> +    unsigned long long b = *pborrow;
> +    x = __builtin_subcll(x, y, b, &b);
> +    *pborrow = b & 1;
> +    return x;
> +#else
> +    bool b = *pborrow;
> +    b = usub64_overflow(x, b, &x);
> +    b |= usub64_overflow(x, y, &x);
> +    *pborrow = b;
> +    return x;
> +#endif
> +}
> +
>  /* Host type specific sizes of these routines.  */
>  
>  #if ULONG_MAX == UINT32_MAX


-- 
Alex Bennée



reply via email to

[Prev in Thread] Current Thread [Next in Thread]