This patch provides a flag that allows atomics operation in-lining to be turned off. The default is on, which is what we have today.

by specifying -fno-inline-atomics, none of the new __atomic routines will be inlined, and will be left as external function calls. The __sync routines are not affected by the flag.

This will facilitate building and testing a library to be associated with the new atomics as well as testing the compiler's ability to generate these calls for targets which do not have built in atomics.

testcases are provided which demonstrate it is functioning as expected.

Bootstrapped and now new regressions on  x86_64-unknown-linux-gnu.

Andrew


        * common.opt (finline-atomics): New. Flag to disable atomic inlining.
        * builtins.c (expand_builtin_atomic_exchange,
        expand_builtin_atomic_compare_exchange, expand_builtin_atomic_load,
        expand_builtin_atomic_store, expand_builtin_atomic_fetch_op,
        fold_builtin_atomic_is_lock_free, expand_builtin_atomic_is_lock_free):
        Don't attempt instruction expansion if inlining atomics is disabled.

        testsuite
        * gcc.dg/atomic-noinline.c: New.  Make a variety of atomics calls.
        * gcc.dg/atomic-noinline-aux.c: New.  Provide some entry points.


Index: common.opt
===================================================================
*** common.opt  (revision 180570)
--- common.opt  (working copy)
*************** finline-limit=
*** 1266,1271 ****
--- 1266,1275 ----
  Common RejectNegative Joined UInteger
  -finline-limit=<number>       Limit the size of inlined functions to <number>
  
+ finline-atomics
+ Common Report Var(flag_inline_atomics) Init(1) Optimization
+ Inline __atomic operations when a lock free instruction sequence is available.
+ 
  finstrument-functions
  Common Report Var(flag_instrument_function_entry_exit)
  Instrument function entry and exit with profiling calls
Index: builtins.c
===================================================================
*** builtins.c  (revision 180570)
--- builtins.c  (working copy)
*************** expand_builtin_atomic_exchange (enum mac
*** 5274,5279 ****
--- 5274,5282 ----
        return NULL_RTX;
      }
  
+   if (!flag_inline_atomics)
+     return NULL_RTX;
+ 
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
*************** expand_builtin_atomic_compare_exchange (
*** 5311,5316 ****
--- 5314,5322 ----
        return NULL_RTX;
      }
    
+   if (!flag_inline_atomics)
+     return NULL_RTX;
+ 
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
  
*************** expand_builtin_atomic_load (enum machine
*** 5346,5351 ****
--- 5352,5360 ----
        return NULL_RTX;
      }
  
+   if (!flag_inline_atomics)
+     return NULL_RTX;
+ 
    /* Expand the operand.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
  
*************** expand_builtin_atomic_store (enum machin
*** 5373,5378 ****
--- 5382,5390 ----
        return NULL_RTX;
      }
  
+   if (!flag_inline_atomics)
+     return NULL_RTX;
+ 
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
*************** expand_builtin_atomic_fetch_op (enum mac
*** 5407,5415 ****
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
  
!   ret = expand_atomic_fetch_op (target, mem, val, code, model, fetch_after);
!   if (ret)
!     return ret;
  
    /* Return if a different routine isn't needed for the library call.  */
    if (ext_call == BUILT_IN_NONE)
--- 5419,5431 ----
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
    val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
  
!   /* Only try generating instructions if inlining is turned on.  */
!   if (flag_inline_atomics)
!     {
!       ret = expand_atomic_fetch_op (target, mem, val, code, model, 
fetch_after);
!       if (ret)
!       return ret;
!     }
  
    /* Return if a different routine isn't needed for the library call.  */
    if (ext_call == BUILT_IN_NONE)
*************** expand_builtin_atomic_always_lock_free (
*** 5486,5496 ****
  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)
!     return always;
  
    return NULL_TREE;
  }
--- 5502,5513 ----
  static tree
  fold_builtin_atomic_is_lock_free (tree arg)
  {
!   if (!flag_inline_atomics)
!     return NULL_TREE;
!   
    /* If it isnt always lock free, don't generate a result.  */
!   if (fold_builtin_atomic_always_lock_free (arg) == integer_one_node)
!     return integer_one_node;
  
    return NULL_TREE;
  }
*************** expand_builtin_atomic_is_lock_free (tree
*** 5509,5514 ****
--- 5526,5534 ----
        return NULL_RTX;
      }
  
+   if (!flag_inline_atomics)
+     return NULL_RTX; 
+ 
    /* If the value is known at compile time, return the RTX for it.  */
    size = fold_builtin_atomic_is_lock_free (arg);
    if (size == integer_one_node)
Index: testsuite/gcc.dg/atomic-noinline.c
===================================================================
*** testsuite/gcc.dg/atomic-noinline.c  (revision 0)
--- testsuite/gcc.dg/atomic-noinline.c  (revision 0)
***************
*** 0 ****
--- 1,56 ----
+ /* Test generic __atomic routines for proper function calling.
+    memory model.  */
+ /* { dg-options "-w -fno-inline-atomics" } */
+ /* { dg-do run } */
+ /* { dg-additional-sources "atomic-noinline-aux.c" } */
+ 
+ /* Test that -fno-inline-atomics works as expected.  
+    atomic-generic-aux provide the expected routines which simply set the
+    value of the first parameter to */
+ 
+ #include <stdlib.h>
+ #include <stdbool.h>
+ 
+ extern void abort();
+ 
+ short as,bs,cs;
+ char ac,bc,cc;
+ 
+ main ()
+ {
+ 
+   ac = __atomic_exchange_n (&bc, cc, __ATOMIC_RELAXED);
+   if (bc != 1)
+     abort ();
+ 
+   as = __atomic_load_n (&bs, __ATOMIC_SEQ_CST);
+   if (bs != 1)
+     abort ();
+ 
+   __atomic_store_n (&ac, bc, __ATOMIC_RELAXED);
+   if (ac != 1)
+     abort ();
+ 
+   __atomic_compare_exchange_n (&as, &bs, cs, 0, __ATOMIC_SEQ_CST, 
__ATOMIC_SEQ_CST);
+   if (as != 1)
+     abort ();
+ 
+   ac = __atomic_fetch_add (&cc, 15, __ATOMIC_SEQ_CST);
+   if (cc != 1)
+     abort ();
+ 
+   /* This should be translated to __atomic_fetch_add for the library */
+   as = __atomic_add_fetch (&cs, 10, __ATOMIC_RELAXED);
+ 
+   if (cs != 1)
+     abort ();
+ 
+   /* The fake external function should return 10.  */
+   if (__atomic_is_lock_free (4) != 10)
+     abort ();
+    
+   return 0;
+ }
+ 
+ 
+ 
Index: testsuite/gcc.dg/atomic-noinline-aux.c
===================================================================
*** testsuite/gcc.dg/atomic-noinline-aux.c      (revision 0)
--- testsuite/gcc.dg/atomic-noinline-aux.c      (revision 0)
***************
*** 0 ****
--- 1,51 ----
+ /* Supply a set of generic atomic functions to test the compiler make the
+    calls properly.  */
+ /* { dg-do compile } */
+ /* { dg-options "-w" } */
+ 
+ /* Test that the generic builtins make calls as expected.  This file provides
+    the exact entry points the test file will require.  All these routines
+    simply set the first parameter to 1, and the caller will test for that.  */
+ 
+ #include <stdlib.h>
+ #include <stdbool.h>
+ #include <string.h>
+ 
+ 
+ char 
+ __atomic_exchange_1 (char *p, char t, int i)
+ {
+   *p = 1;
+ }
+ 
+ short
+ __atomic_load_2 (short *p, int i)
+ { 
+   *p = 1;
+ }
+ 
+ void
+ __atomic_store_1 (char *p, char v, int i)
+ {
+   *p = 1;
+ }
+ 
+ int __atomic_compare_exchange_2 (short *p, short *a, short b, int x, int y, 
int z)
+ {
+   *p = 1;
+ }
+ 
+ char __atomic_fetch_add_1 (char *p, char v, int i)
+ {
+   *p = 1;
+ }
+ 
+ short __atomic_fetch_add_2 (short *p, short v, short i)
+ {
+   *p = 1;
+ }
+ 
+ int __atomic_is_lock_free (int i)
+ {
+   return 10;
+ }

Reply via email to