On Wed, 15 Jan 2014, Niels Möller wrote:

Torbjorn Granlund <t...@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
_______________________________________________
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel

Reply via email to