TODO for 5.2 v3
Marc Glisse
marc.glisse at inria.fr
Wed Jan 15 21:02:11 UTC 2014
On Wed, 15 Jan 2014, Niels Möller wrote:
> Torbjorn Granlund <tg at gmplib.org> writes:
>
>> The volatile qualifier makes sure the number of memory reads and memory
>> writes remain unchanged from the source code.
>
> Question is, when is it useful for our purposes? First example,
> mpn_sec_add_1:
>
> mp_limb_t
> mpn_sec_add_1 (mp_limb_t *rp, mp_limb_t *ap, mp_size_t n, mp_limb_t b,
> mp_ptr scratch)
> {
> scratch[0] = b;
> MPN_ZERO (scratch + 1, n-1);
> return mpn_add_n (rp, ap, scratch, n);
> }
>
> volatile probably makes no difference here, as far as I see (except
> possibly if there's some global optimization which inlines mpn_add_n).
> But maybe we should still declare some or all of the parameters (rp, ap,
> scratch) as pointing to volatile data?
I doubt that it would help, but I could be wrong.
> Or would that give type conversion warnings when calling mpn_add_n, with
> parameters which aren't volatile-declared? I'm not entirely sure what
> volatile means, if it's only giving the compiler some constraints for
> the *implementation* of a function, or if volatile in a function
> *prototype* also affects type checking or code generation in callers in
> some way.
>From a type POV, volatile works like 'const', you can't strip it away.
> Second example,
>
> void
> mpn_cnd_swap (mp_limb_t cnd,
> mp_limb_t *ap, mp_limb_t *bp, mp_size_t n)
> {
> mp_limb_t mask = - (mp_limb_t) (cnd != 0);
> mp_size_t i;
> for (i = 0; i < n; i++)
> {
> mp_limb_t a, b, t;
> a = ap[i];
> b = bp[i];
> t = (a ^ b) & mask;
> ap[i] = a ^ t;
> bp[i] = b ^ t;
> }
> }
>
> Here a compiler might be tempted to do an initial branch on cnd != 0,
> and skip the loop if cnd is false. Using volatile for ap and bp gives it
> less reason to do so, but I guess even with volatile it may still
> generate code equivalent to
>
> if (cnd)
> for (i = 0; i < n; i++)
> {
> mp_limb_t a, b, t;
> a = ap[i];
> b = bp[i];
> ap[i] = b;
> bp[i] = a;
> }
> else
> for (i = 0; i < n; i++)
> {
> mp_limb_t a, b, t;
> a = ap[i];
> b = bp[i];
> ap[i] = a;
> bp[i] = b;
> }
>
> which leaks through the cache.
>
> So is it useful or not to volatile-declare ap and bp here?
volatile mp_limb_t b = cnd != 0;
mp_limb_t mask = -b;
The compiler is still allowed to do b=cnd?1:0 with a branch, but the
volatile blocks any kind of constant propagation, the compiler can't
assume that the value it reads from b is in any way related to what it
just wrote there.
Note that even if mask doesn't come from a condition, the compiler is
allowed to test if mask is 0 or -1 and generate special code for those
cases, so you can't escape either writing asm or compiling with
not-too-extreme optimizations with your fingers crossed.
--
Marc Glisse
More information about the gmp-devel
mailing list