[cxx-mem-model] use alignment when available to determine lock-free ness

2011-11-02 Thread Andrew MacLeod


Lock free routines are not guaranteed to work if they are not aligned 
properly.  Until now, the __atmoic_is_lock_free property has simply 
relied on the size of an object to determine lockfreeness.  This works 
when you assume a certain alignment.


The library takes generic pointers and with structure packing and such, 
alignment is not guaranteed.  This means its possible to have a 4 byte 
object which is lock free, and another which is not.   Up until now I've 
simply punted on it and claimed it was undefined if not properly 
aligned.  By adding the address of the object to the function, it easy 
enough to check alignment at runtime, as well as at compile time, 
usually.  The library will need this in the future so might as well take 
care of it now.


Simply adds an optional parameter to __atomic_{is_always}_lock_free 
which is used to check alignment against the size parameter.   NULL as 
the object pointer produces the same behaviour as today, lockfreeness 
based on proper alignment for an integral value of the specified size.


Bootstrapped and tested on x86_64-unknown-linux-gnu.

Andrew










gcc
* builtins.c (fold_builtin_atomic_always_lock_free): Add object param
and check alignment if present.
(expand_builtin_atomic_always_lock_free): Expect 2nd argument.
(fold_builtin_atomic_is_lock_free): Expect 2nd argument.
(expand_builtin_atomic_is_lock_free): Expect 2nd argument.
(fold_builtin_1): Remove LOCK_FREE builtins.
(fold_builtin_2): Add LOCK_FREE builtins.
* sync-builtins.def (BUILT_IN_ATOMIC_{IS,ALWAYS}_LOCK_FREE): Add param.
* builtin-types.def (BT_FN_BOOL_SIZE): Remove.
(BT_FN_BOOL_SIZE_CONST_VPTR): Add.

fortran
* types.def (BT_FN_BOOL_SIZE): Remove.
(BT_FN_BOOL_SIZE_CONST_VPTR): Add.

libstdc++-v3
* include/std/atomic (is_lock_free): Add object pointer to 
__atomic_is_lock_free.
* include/bits/atomic_base.h (LOCKFREE_PROP): Add 0 for object ptr.
(is_lock_free): Add object pointer to __atomic_is_lock_free.

testsuite
* gcc.dg/atomic-lockfree-aux.c: Add extra lock-free parameter.
* gcc.dg/atomic-invalid.c: Add extra lock-free parameter.
* gcc.dg/atomic-lockfree.c: Add extra lock-free parameter.

Index: gcc/builtins.c
===
*** gcc/builtins.c  (revision 180699)
--- gcc/builtins.c  (working copy)
*** expand_builtin_atomic_fetch_op (enum mac
*** 5448,5502 
return ret;
  }
  
! /* Return true if size ARG is always lock free on this architecture.  */
  static tree
! fold_builtin_atomic_always_lock_free (tree arg)
  {
int size;
enum machine_mode mode;
  
!   if (TREE_CODE (arg) != INTEGER_CST)
  return NULL_TREE;
  
/* Check if a compare_and_swap pattern exists for the mode which represents
   the required size.  The pattern is not allowed to fail, so the existence
   of the pattern indicates support is present.  */
-   size = INTVAL (expand_normal (arg)) * BITS_PER_UNIT;
-   mode = mode_for_size (size, MODE_INT, 0);
- 
if (can_compare_and_swap_p (mode))
  return integer_one_node;
else
  return integer_zero_node;
  }
  
! /* Return true if the first argument to call EXP represents a size of
!object than will always generate lock-free instructions on this target.
!Otherwise return false.  */
  static rtx
  expand_builtin_atomic_always_lock_free (tree exp)
  {
tree size;
!   tree arg = CALL_EXPR_ARG (exp, 0);
  
!   if (TREE_CODE (arg) != INTEGER_CST)
  {
!   error (non-constant argument to __atomic_always_lock_free);
return const0_rtx;
  }
  
!   size = fold_builtin_atomic_always_lock_free (arg);
if (size == integer_one_node)
  return const1_rtx;
return const0_rtx;
  }
  
! /* Return a one or zero if it can be determined that size ARG is lock free on
!this architecture.  */
  static tree
! fold_builtin_atomic_is_lock_free (tree arg)
  {
!   tree always = fold_builtin_atomic_always_lock_free (arg);
  
/* If it isnt always lock free, don't generate a result.  */
if (always == integer_one_node)
--- 5448,5539 
return ret;
  }
  
! /* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
!this architecture.  If ARG1 is NULL, use typical alignment for size ARG0.  
*/
! 
  static tree
! fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
  {
int size;
enum machine_mode mode;
+   unsigned int mode_align, type_align;
  
!   if (TREE_CODE (arg0) != INTEGER_CST)
  return NULL_TREE;
  
+   size = INTVAL (expand_normal (arg0)) * BITS_PER_UNIT;
+   mode = mode_for_size (size, MODE_INT, 0);
+   mode_align = GET_MODE_ALIGNMENT (mode);
+ 
+   /* If a pointer is provided, check that alignment matches OK.  Otherwise a 
+  zero must be provided to indicate normal alignment for an object size.  

Re: [cxx-mem-model] use alignment when available to determine lock-free ness

2011-11-02 Thread Richard Henderson
On 11/02/2011 07:59 AM, Andrew MacLeod wrote:
 Simply adds an optional parameter to __atomic_{is_always}_lock_free
 which is used to check alignment against the size parameter. NULL as
 the object pointer produces the same behaviour as today, lockfreeness
 based on proper alignment for an integral value of the specified size.

Why a pointer to the object?  Are you really going to check the real
object alignment in the library __atomic_lock_free?

Seems to me that another integer argument does just as well:

  __atomic_is_always_lock_free (sizeof(T), __alignof(T))


r~


Re: [cxx-mem-model] use alignment when available to determine lock-free ness

2011-11-02 Thread Andrew MacLeod

On 11/02/2011 11:22 AM, Richard Henderson wrote:

On 11/02/2011 07:59 AM, Andrew MacLeod wrote:

Simply adds an optional parameter to __atomic_{is_always}_lock_free
which is used to check alignment against the size parameter. NULL as
the object pointer produces the same behaviour as today, lockfreeness
based on proper alignment for an integral value of the specified size.

Why a pointer to the object?  Are you really going to check the real
object alignment in the library __atomic_lock_free?

Seems to me that another integer argument does just as well:

   __atomic_is_always_lock_free (sizeof(T), __alignof(T))



Well that could be an option. I'm just thinking about how the C1x call 
works.   its   'is_lock_free (object *)'  (which is more or less what 
c++ is as well.)


The standards are very specific that it is individual object specific, 
and that objects of the same size may not share the lock free property.
I was thinking of when someone uses a slice of memory that is say 4 
bytes.  1 in 4 of those are aligned properly at runtime :-)  The library 
can simply check the address passed into it an say, yeah, thats aligned, 
use the lock-free routine.


Im guessing thats their intent, it seems reasonable...

if you are passing a second value in, alignof(T) is more limiting than 
an actual object pointer, so I figure just let the library decide what 
to do with it..


Andrew


Re: [cxx-mem-model] use alignment when available to determine lock-free ness

2011-11-02 Thread Richard Henderson
On 11/02/2011 07:59 AM, Andrew MacLeod wrote:
   gcc
   * builtins.c (fold_builtin_atomic_always_lock_free): Add object param
   and check alignment if present.
   (expand_builtin_atomic_always_lock_free): Expect 2nd argument.
   (fold_builtin_atomic_is_lock_free): Expect 2nd argument.
   (expand_builtin_atomic_is_lock_free): Expect 2nd argument.
   (fold_builtin_1): Remove LOCK_FREE builtins.
   (fold_builtin_2): Add LOCK_FREE builtins.
   * sync-builtins.def (BUILT_IN_ATOMIC_{IS,ALWAYS}_LOCK_FREE): Add param.
   * builtin-types.def (BT_FN_BOOL_SIZE): Remove.
   (BT_FN_BOOL_SIZE_CONST_VPTR): Add.
 
   fortran
   * types.def (BT_FN_BOOL_SIZE): Remove.
   (BT_FN_BOOL_SIZE_CONST_VPTR): Add.
 
   libstdc++-v3
   * include/std/atomic (is_lock_free): Add object pointer to 
   __atomic_is_lock_free.
   * include/bits/atomic_base.h (LOCKFREE_PROP): Add 0 for object ptr.
   (is_lock_free): Add object pointer to __atomic_is_lock_free.
 
   testsuite
   * gcc.dg/atomic-lockfree-aux.c: Add extra lock-free parameter.
   * gcc.dg/atomic-invalid.c: Add extra lock-free parameter.
   * gcc.dg/atomic-lockfree.c: Add extra lock-free parameter.

Ok.


r~


Re: [cxx-mem-model] use alignment when available to determine lock-free ness

2011-11-02 Thread Andrew MacLeod

On 11/02/2011 12:28 PM, Richard Henderson wrote:

On 11/02/2011 07:59 AM, Andrew MacLeod wrote:

+   /* Parameters at this point are usually cast to void *, so check for 
that
+and look past the cast.  */
+   if (TREE_CODE (arg1) == NOP_EXPR  POINTER_TYPE_P (ttype)
+ VOID_TYPE_P (TREE_TYPE (ttype)))
+ arg1 = TREE_OPERAND (arg1, 0);
+
+   ttype = TREE_TYPE (arg1);
+   gcc_assert (POINTER_TYPE_P (ttype));
+
+   /* Get the underlying type of the object.  */
+   ttype = TREE_TYPE (ttype);
+   type_align = TYPE_ALIGN (ttype);

I take that back.  Does this really work?  It certainly doesn't seem like
it would work in SSA mode.  You'd need to look back to the def.


it did in  my simply trials as I figured this out in the debugger :-)   
i only did basic tests.  OK,  Is there a simple way to get to the def?


what happens to the alignment of something if its say 'char *'  type and 
its cast to an (int *) oir something with more strict alignment... or 
will the compiler complain about that?


Andrew


Re: [cxx-mem-model] use alignment when available to determine lock-free ness

2011-11-02 Thread Richard Henderson
On 11/02/2011 09:30 AM, Andrew MacLeod wrote:
 it did in my simply trials as I figured this out in the debugger :-)
 i only did basic tests. OK, Is there a simple way to get to the def?

You should know.  You wrote most of that stuff.

 what happens to the alignment of something if its say 'char *'  type
 and its cast to an (int *) oir something with more strict
 alignment... or will the compiler complain about that?

The compiler certainly won't complain.

I guess the absolute best thing is to look at the ptr_info_def
of the SSA name.  In theory this will have been solved for you.


r~


Re: [cxx-mem-model] use alignment when available to determine lock-free ness

2011-11-02 Thread Andrew MacLeod

On 11/02/2011 12:37 PM, Richard Henderson wrote:

On 11/02/2011 09:30 AM, Andrew MacLeod wrote:

it did in my simply trials as I figured this out in the debugger :-)
i only did basic tests. OK, Is there a simple way to get to the def?

You should know.  You wrote most of that stuff.

HA. years ago. I have a 6 month term memory.  Now I have to go look it 
up :-)


Andrew