public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [cxx-mem-model 0/2] Support the legacy __sync libcalls
@ 2011-11-03 23:27 Richard Henderson
  2011-11-03 23:31 ` [cxx-mem-model 1/2] Allow libcalls to be installed for legacy __sync optabs Richard Henderson
  2011-11-03 23:37 ` [cxx-mem-model 2/2] arm: Install __sync libfuncs for Linux Richard Henderson
  0 siblings, 2 replies; 6+ messages in thread
From: Richard Henderson @ 2011-11-03 23:27 UTC (permalink / raw)
  To: gcc-patches; +Cc: rdsandiford, richard.earnshaw, dave.anglin, kkojima

Not installing to the branch because amacleod is busy preparing
the merge.  This can be committed after that's done.

Something similar to the second patch needs to be done for:

  sh[34]-linux
  hppa-linux
  mips16

Given that it's a matter of two lines for each target, the most
important of which is some port-specific condition, I'm going to
leave these to the respective port maintainers.


r~



Richard Henderson (2):
  Allow libcalls to be installed for legacy __sync optabs.
  arm: Install __sync libfuncs for Linux.

 gcc/builtins.c       |    2 +-
 gcc/config/arm/arm.c |    4 +
 gcc/genopinit.c      |   28 +++---
 gcc/omp-low.c        |    4 +-
 gcc/optabs.c         |  217 +++++++++++++++++++++++++++++++++++++++-----------
 gcc/optabs.h         |   99 ++++++++++++-----------
 6 files changed, 241 insertions(+), 113 deletions(-)

-- 
1.7.6.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [cxx-mem-model 1/2] Allow libcalls to be installed for legacy __sync optabs.
  2011-11-03 23:27 [cxx-mem-model 0/2] Support the legacy __sync libcalls Richard Henderson
@ 2011-11-03 23:31 ` Richard Henderson
  2011-11-03 23:37 ` [cxx-mem-model 2/2] arm: Install __sync libfuncs for Linux Richard Henderson
  1 sibling, 0 replies; 6+ messages in thread
From: Richard Henderson @ 2011-11-03 23:31 UTC (permalink / raw)
  To: gcc-patches

This allows a target which implements the __sync interfaces
in libgcc to continue to use them transparently with the
new __atomic builtins.

It is assumed that these libgcc routines DO NOT use spinlocks.
This is true of all extant libgcc instances.
---
 gcc/builtins.c  |    2 +-
 gcc/genopinit.c |   28 ++++----
 gcc/omp-low.c   |    4 +-
 gcc/optabs.c    |  217 +++++++++++++++++++++++++++++++++++++++++++------------
 gcc/optabs.h    |   99 +++++++++++++------------
 5 files changed, 237 insertions(+), 113 deletions(-)

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 39c0afb..08fb434 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5511,7 +5511,7 @@ fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
   /* 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.  */
-  if (can_compare_and_swap_p (mode))
+  if (can_compare_and_swap_p (mode, true))
     return integer_one_node;
   else
     return integer_zero_node;
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index 44eba24..63c58a8 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -228,20 +228,20 @@ static const char * const optabs[] =
   "set_direct_optab_handler (sync_and_optab, $A, CODE_FOR_$(sync_and$I$a$))",
   "set_direct_optab_handler (sync_xor_optab, $A, CODE_FOR_$(sync_xor$I$a$))",
   "set_direct_optab_handler (sync_nand_optab, $A, CODE_FOR_$(sync_nand$I$a$))",
-  "set_direct_optab_handler (sync_old_add_optab, $A, CODE_FOR_$(sync_old_add$I$a$))",
-  "set_direct_optab_handler (sync_old_sub_optab, $A, CODE_FOR_$(sync_old_sub$I$a$))",
-  "set_direct_optab_handler (sync_old_ior_optab, $A, CODE_FOR_$(sync_old_ior$I$a$))",
-  "set_direct_optab_handler (sync_old_and_optab, $A, CODE_FOR_$(sync_old_and$I$a$))",
-  "set_direct_optab_handler (sync_old_xor_optab, $A, CODE_FOR_$(sync_old_xor$I$a$))",
-  "set_direct_optab_handler (sync_old_nand_optab, $A, CODE_FOR_$(sync_old_nand$I$a$))",
-  "set_direct_optab_handler (sync_new_add_optab, $A, CODE_FOR_$(sync_new_add$I$a$))",
-  "set_direct_optab_handler (sync_new_sub_optab, $A, CODE_FOR_$(sync_new_sub$I$a$))",
-  "set_direct_optab_handler (sync_new_ior_optab, $A, CODE_FOR_$(sync_new_ior$I$a$))",
-  "set_direct_optab_handler (sync_new_and_optab, $A, CODE_FOR_$(sync_new_and$I$a$))",
-  "set_direct_optab_handler (sync_new_xor_optab, $A, CODE_FOR_$(sync_new_xor$I$a$))",
-  "set_direct_optab_handler (sync_new_nand_optab, $A, CODE_FOR_$(sync_new_nand$I$a$))",
-  "set_direct_optab_handler (sync_compare_and_swap_optab, $A, CODE_FOR_$(sync_compare_and_swap$I$a$))",
-  "set_direct_optab_handler (sync_lock_test_and_set_optab, $A, CODE_FOR_$(sync_lock_test_and_set$I$a$))",
+  "set_optab_handler (sync_old_add_optab, $A, CODE_FOR_$(sync_old_add$I$a$))",
+  "set_optab_handler (sync_old_sub_optab, $A, CODE_FOR_$(sync_old_sub$I$a$))",
+  "set_optab_handler (sync_old_ior_optab, $A, CODE_FOR_$(sync_old_ior$I$a$))",
+  "set_optab_handler (sync_old_and_optab, $A, CODE_FOR_$(sync_old_and$I$a$))",
+  "set_optab_handler (sync_old_xor_optab, $A, CODE_FOR_$(sync_old_xor$I$a$))",
+  "set_optab_handler (sync_old_nand_optab, $A, CODE_FOR_$(sync_old_nand$I$a$))",
+  "set_optab_handler (sync_new_add_optab, $A, CODE_FOR_$(sync_new_add$I$a$))",
+  "set_optab_handler (sync_new_sub_optab, $A, CODE_FOR_$(sync_new_sub$I$a$))",
+  "set_optab_handler (sync_new_ior_optab, $A, CODE_FOR_$(sync_new_ior$I$a$))",
+  "set_optab_handler (sync_new_and_optab, $A, CODE_FOR_$(sync_new_and$I$a$))",
+  "set_optab_handler (sync_new_xor_optab, $A, CODE_FOR_$(sync_new_xor$I$a$))",
+  "set_optab_handler (sync_new_nand_optab, $A, CODE_FOR_$(sync_new_nand$I$a$))",
+  "set_optab_handler (sync_compare_and_swap_optab, $A, CODE_FOR_$(sync_compare_and_swap$I$a$))",
+  "set_optab_handler (sync_lock_test_and_set_optab, $A, CODE_FOR_$(sync_lock_test_and_set$I$a$))",
   "set_direct_optab_handler (sync_lock_release_optab, $A, CODE_FOR_$(sync_lock_release$I$a$))",
   "set_direct_optab_handler (atomic_exchange_optab, $A, CODE_FOR_$(atomic_exchange$I$a$))",
   "set_direct_optab_handler (atomic_compare_and_swap_optab, $A, CODE_FOR_$(atomic_compare_and_swap$I$a$))",
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index d8e7ce3..8145957 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -5097,7 +5097,7 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
      matter is that (with the exception of i486 vs i586 and xadd) all targets
      that support any atomic operaton optab also implements compare-and-swap.
      Let optabs.c take care of expanding any compare-and-swap loop.  */
-  if (!can_compare_and_swap_p (imode))
+  if (!can_compare_and_swap_p (imode, true))
     return false;
 
   gsi = gsi_last_bb (load_bb);
@@ -5168,7 +5168,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
   type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
   itype = TREE_TYPE (TREE_TYPE (cmpxchg));
 
-  if (!can_compare_and_swap_p (TYPE_MODE (itype)))
+  if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
     return false;
 
   /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD.  */
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 56608f8..980686c 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -6586,6 +6586,57 @@ init_optabs (void)
   targetm.init_libfuncs ();
 }
 
+/* A helper function for init_sync_libfuncs.  Using the basename BASE,
+   install libfuncs into TAB for BASE_N for 1 <= N <= MAX.  */
+
+static void
+init_sync_libfuncs_1 (optab tab, const char *base, int max)
+{
+  enum machine_mode mode;
+  char buf[64];
+  size_t len = strlen (base);
+  int i;
+
+  gcc_assert (max <= 8);
+  gcc_assert (len + 3 < sizeof (buf));
+
+  memcpy (buf, base, len);
+  buf[len] = '_';
+  buf[len + 1] = '0';
+  buf[len + 2] = '\0';
+
+  mode = QImode;
+  for (i = 1; i < max; i *= 2)
+    {
+      buf[len + 1] = '0' + i;
+      set_optab_libfunc (tab, mode, buf);
+      mode = GET_MODE_2XWIDER_MODE (mode);
+    }
+}
+
+void
+init_sync_libfuncs (int max)
+{
+  init_sync_libfuncs_1 (sync_compare_and_swap_optab,
+			"__sync_val_compare_and_swap", max);
+  init_sync_libfuncs_1 (sync_lock_test_and_set_optab,
+			"__sync_lock_test_and_set", max);
+
+  init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max);
+  init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max);
+  init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_ior", max);
+  init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max);
+  init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max);
+  init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max);
+
+  init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max);
+  init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max);
+  init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_ior_and_fetch", max);
+  init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max);
+  init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max);
+  init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max);
+}
+
 /* Print information about the current contents of the optabs on
    STDERR.  */
 
@@ -7165,19 +7216,21 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
 /* Return true if there is a compare_and_swap pattern.  */
 
 bool
-can_compare_and_swap_p (enum machine_mode mode)
+can_compare_and_swap_p (enum machine_mode mode, bool allow_libcall)
 {
   enum insn_code icode;
 
-  /* Check for __sync_compare_and_swap.  */
-  icode = direct_optab_handler (sync_compare_and_swap_optab, mode);
-  if (icode != CODE_FOR_nothing)
-      return true;
-
   /* Check for __atomic_compare_and_swap.  */
   icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
   if (icode != CODE_FOR_nothing)
-      return true;
+    return true;
+
+  /* Check for __sync_compare_and_swap.  */
+  icode = optab_handler (sync_compare_and_swap_optab, mode);
+  if (icode != CODE_FOR_nothing)
+    return true;
+  if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode))
+    return true;
 
   /* No inline compare and swap.  */
   return false;
@@ -7263,7 +7316,6 @@ expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
 {
   enum machine_mode mode = GET_MODE (mem);
   enum insn_code icode;
-  rtx last_insn;
 
   /* If the target supports the exchange directly, great.  */
   icode = direct_optab_handler (atomic_exchange_optab, mode);
@@ -7286,16 +7338,16 @@ expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
      The barrier is not needed if sync_lock_test_and_set doesn't exist since
      it will expand into a compare-and-swap loop.  */
 
-  icode = direct_optab_handler (sync_lock_test_and_set_optab, mode);
-  last_insn = get_last_insn ();
-  if ((icode != CODE_FOR_nothing) && (model == MEMMODEL_SEQ_CST || 
-				      model == MEMMODEL_RELEASE ||
-				      model == MEMMODEL_ACQ_REL))
-    expand_builtin_mem_thread_fence (model);
-
+  icode = optab_handler (sync_lock_test_and_set_optab, mode);
   if (icode != CODE_FOR_nothing)
     {
       struct expand_operand ops[3];
+      rtx last_insn = get_last_insn ();
+
+      if (model == MEMMODEL_SEQ_CST
+	  || model == MEMMODEL_RELEASE
+	  || model == MEMMODEL_ACQ_REL)
+	expand_builtin_mem_thread_fence (model);
 
       create_output_operand (&ops[0], target, mode);
       create_fixed_operand (&ops[1], mem);
@@ -7303,15 +7355,33 @@ expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
       create_convert_operand_to (&ops[2], val, mode, true);
       if (maybe_expand_insn (icode, 3, ops))
 	return ops[0].value;
+
+      delete_insns_since (last_insn);
     }
 
-  /* Remove any fence we may have inserted since a compare and swap loop is a
-     full memory barrier.  */
-  if (last_insn != get_last_insn ())
-    delete_insns_since (last_insn);
+  /* If an external test-and-set libcall is provided, use that instead of
+     any external compare-and-swap that we might get from the compare-and-
+     swap-loop expansion below.  */
+  if (!can_compare_and_swap_p (mode, false))
+    {
+      rtx libfunc = optab_libfunc (sync_lock_test_and_set_optab, mode);
+      if (libfunc != NULL)
+	{
+	  rtx addr;
+
+	  if (model == MEMMODEL_SEQ_CST
+	      || model == MEMMODEL_RELEASE
+	      || model == MEMMODEL_ACQ_REL)
+	    expand_builtin_mem_thread_fence (model);
+
+	  addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
+	  return emit_library_call_value (libfunc, target, LCT_NORMAL, mode,
+					  2, addr, ptr_mode, val, mode);
+	}
+    }
 
   /* Otherwise, use a compare-and-swap loop for the exchange.  */
-  if (can_compare_and_swap_p (mode))
+  if (can_compare_and_swap_p (mode, true))
     {
       if (!target || !register_operand (target, mode))
 	target = gen_reg_rtx (mode);
@@ -7345,7 +7415,8 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
   enum machine_mode mode = GET_MODE (mem);
   struct expand_operand ops[8];
   enum insn_code icode;
-  rtx target_bool, target_oval;
+  rtx target_oval, target_bool = NULL_RTX;
+  rtx libfunc;
 
   /* Load expected into a register for the compare and swap.  */
   if (MEM_P (expected))
@@ -7389,7 +7460,7 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
 
   /* Otherwise fall back to the original __sync_val_compare_and_swap
      which is always seq-cst.  */
-  icode = direct_optab_handler (sync_compare_and_swap_optab, mode);
+  icode = optab_handler (sync_compare_and_swap_optab, mode);
   if (icode != CODE_FOR_nothing)
     {
       rtx cc_reg;
@@ -7402,7 +7473,6 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
 	return false;
 
       target_oval = ops[0].value;
-      target_bool = NULL_RTX;
 
       /* If the caller isn't interested in the boolean return value,
 	 skip the computation of it.  */
@@ -7413,17 +7483,37 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
       cc_reg = NULL_RTX;
       if (have_insn_for (COMPARE, CCmode))
 	note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
+      if (cc_reg)
+	{
+	  target_bool = emit_store_flag_force (target_bool, EQ, cc_reg,
+					       const0_rtx, VOIDmode, 0, 1);
+	  goto success;
+	}
+      goto success_bool_from_val;
+    }
 
-      target_bool
-	= (cc_reg
-	   ? emit_store_flag_force (target_bool, EQ, cc_reg,
-				    const0_rtx, VOIDmode, 0, 1)
-	   : emit_store_flag_force (target_bool, EQ, target_oval,
-				    expected, VOIDmode, 1, 1));
-      goto success;
+  /* Also check for library support for __sync_val_compare_and_swap.  */
+  libfunc = optab_libfunc (sync_compare_and_swap_optab, mode);
+  if (libfunc != NULL)
+    {
+      rtx addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
+      target_oval = emit_library_call_value (libfunc, target_oval, LCT_NORMAL,
+					     mode, 3, addr, ptr_mode,
+					     expected, mode, desired, mode);
+
+      /* Compute the boolean return value only if requested.  */
+      if (ptarget_bool)
+	goto success_bool_from_val;
+      else
+	goto success;
     }
+
+  /* Failure.  */
   return false;
 
+ success_bool_from_val:
+   target_bool = emit_store_flag_force (target_bool, EQ, target_oval,
+					expected, VOIDmode, 1, 1);
  success:
   /* Make sure that the oval output winds up where the caller asked.  */
   if (ptarget_oval)
@@ -7533,12 +7623,12 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model)
 
 struct atomic_op_functions
 {
-  struct direct_optab_d *mem_fetch_before;
-  struct direct_optab_d *mem_fetch_after;
-  struct direct_optab_d *mem_no_result;
-  struct direct_optab_d *fetch_before;
-  struct direct_optab_d *fetch_after;
-  struct direct_optab_d *no_result;
+  direct_optab mem_fetch_before;
+  direct_optab mem_fetch_after;
+  direct_optab mem_no_result;
+  optab fetch_before;
+  optab fetch_after;
+  direct_optab no_result;
   enum rtx_code reverse_code;
 };
 
@@ -7598,7 +7688,6 @@ maybe_emit_op (const struct atomic_op_functions *optab, rtx target, rtx mem,
 	       rtx val, bool use_memmodel, enum memmodel model, bool after)
 {
   enum machine_mode mode = GET_MODE (mem);
-  struct direct_optab_d *this_optab;
   struct expand_operand ops[4];
   enum insn_code icode;
   int op_counter = 0;
@@ -7609,13 +7698,13 @@ maybe_emit_op (const struct atomic_op_functions *optab, rtx target, rtx mem,
     {
       if (use_memmodel)
         {
-	  this_optab = optab->mem_no_result;
+	  icode = direct_optab_handler (optab->mem_no_result, mode);
 	  create_integer_operand (&ops[2], model);
 	  num_ops = 3;
 	}
       else
         {
-	  this_optab = optab->no_result;
+	  icode = direct_optab_handler (optab->no_result, mode);
 	  num_ops = 2;
 	}
     }
@@ -7624,19 +7713,19 @@ maybe_emit_op (const struct atomic_op_functions *optab, rtx target, rtx mem,
     {
       if (use_memmodel)
         {
-	  this_optab = after ? optab->mem_fetch_after : optab->mem_fetch_before;
+	  icode = direct_optab_handler (after ? optab->mem_fetch_after
+					: optab->mem_fetch_before, mode);
 	  create_integer_operand (&ops[3], model);
-	  num_ops= 4;
+	  num_ops = 4;
 	}
       else
 	{
-	  this_optab = after ? optab->fetch_after : optab->fetch_before;
+	  icode = optab_handler (after ? optab->fetch_after
+				 : optab->fetch_before, mode);
 	  num_ops = 3;
 	}
       create_output_operand (&ops[op_counter++], target, mode);
     }
-
-  icode = direct_optab_handler (this_optab, mode);
   if (icode == CODE_FOR_nothing)
     return NULL_RTX;
 
@@ -7645,7 +7734,7 @@ maybe_emit_op (const struct atomic_op_functions *optab, rtx target, rtx mem,
   create_convert_operand_to (&ops[op_counter++], val, mode, true);
 
   if (maybe_expand_insn (icode, num_ops, ops))
-    return ((target == const0_rtx) ? const0_rtx : ops[0].value);
+    return (target == const0_rtx ? const0_rtx : ops[0].value);
 
   return NULL_RTX;
 } 
@@ -7699,7 +7788,7 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
 
   /* If the fetch value can be calculated from the other variation of fetch,
      try that operation.  */
-  if (after || optab->reverse_code != UNKNOWN || target == const0_rtx) 
+  if (after || unused_result || optab->reverse_code != UNKNOWN)
     {
       /* Try the __atomic version, then the older __sync version.  */
       result = maybe_emit_op (optab, target, mem, val, true, model, !after);
@@ -7716,14 +7805,46 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
 	     Fetch_before == after REVERSE_OP val.  */
 	  if (!after)
 	    code = optab->reverse_code;
-	  result = expand_simple_binop (mode, code, result, val, NULL_RTX, true,
+	  result = expand_simple_binop (mode, code, result, val, target, true,
 					OPTAB_LIB_WIDEN);
 	  return result;
 	}
     }
 
+  /* Try the __sync libcalls only if we can't do compare-and-swap inline.  */
+  if (can_compare_and_swap_p (mode, false))
+    {
+      rtx libfunc;
+      bool fixup = false;
+
+      libfunc = optab_libfunc (after ? optab->fetch_after
+			       : optab->fetch_before, mode);
+      if (libfunc == NULL
+	  && (after || unused_result || optab->reverse_code != UNKNOWN))
+	{
+	  fixup = true;
+	  if (!after)
+	    code = optab->reverse_code;
+	  libfunc = optab_libfunc (after ? optab->fetch_before
+				   : optab->fetch_after, mode);
+	}
+      if (libfunc != NULL)
+	{
+	  rtx addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
+	  result = emit_library_call_value (libfunc, NULL, LCT_NORMAL, mode,
+					    2, addr, ptr_mode, val, mode);
+
+	  if (unused_result)
+	    return target;
+	  if (fixup)
+	    result = expand_simple_binop (mode, code, result, val, target,
+					  true, OPTAB_LIB_WIDEN);
+	  return result;
+	}
+    }
+
   /* If nothing else has succeeded, default to a compare and swap loop.  */
-  if (can_compare_and_swap_p (mode))
+  if (can_compare_and_swap_p (mode, true))
     {
       rtx insn;
       rtx t0 = gen_reg_rtx (mode), t1;
diff --git a/gcc/optabs.h b/gcc/optabs.h
index d70b3fa..bc705dc 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -386,6 +386,30 @@ enum optab_index
   /* Perform a raise to the power of integer.  */
   OTI_powi,
 
+  /* Atomic compare and swap.  */
+  OTI_sync_compare_and_swap,
+
+  /* Atomic exchange with acquire semantics.  */
+  OTI_sync_lock_test_and_set,
+
+  /* This second set is atomic operations in which we return the value
+     that existed in memory before the operation.  */
+  OTI_sync_old_add,
+  OTI_sync_old_sub,
+  OTI_sync_old_ior,
+  OTI_sync_old_and,
+  OTI_sync_old_xor,
+  OTI_sync_old_nand,
+
+  /* This third set is atomic operations in which we return the value
+     that resulted after performing the operation.  */
+  OTI_sync_new_add,
+  OTI_sync_new_sub,
+  OTI_sync_new_ior,
+  OTI_sync_new_and,
+  OTI_sync_new_xor,
+  OTI_sync_new_nand,
+
   OTI_MAX
 };
 
@@ -570,6 +594,23 @@ enum optab_index
 
 #define powi_optab (&optab_table[OTI_powi])
 
+#define sync_compare_and_swap_optab \
+  (&optab_table[(int) OTI_sync_compare_and_swap])
+#define sync_lock_test_and_set_optab \
+  (&optab_table[(int) OTI_sync_lock_test_and_set])
+#define sync_old_add_optab (&optab_table[(int) OTI_sync_old_add])
+#define sync_old_sub_optab (&optab_table[(int) OTI_sync_old_sub])
+#define sync_old_ior_optab (&optab_table[(int) OTI_sync_old_ior])
+#define sync_old_and_optab (&optab_table[(int) OTI_sync_old_and])
+#define sync_old_xor_optab (&optab_table[(int) OTI_sync_old_xor])
+#define sync_old_nand_optab (&optab_table[(int) OTI_sync_old_nand])
+#define sync_new_add_optab (&optab_table[(int) OTI_sync_new_add])
+#define sync_new_sub_optab (&optab_table[(int) OTI_sync_new_sub])
+#define sync_new_ior_optab (&optab_table[(int) OTI_sync_new_ior])
+#define sync_new_and_optab (&optab_table[(int) OTI_sync_new_and])
+#define sync_new_xor_optab (&optab_table[(int) OTI_sync_new_xor])
+#define sync_new_nand_optab (&optab_table[(int) OTI_sync_new_nand])
+
 /* Conversion optabs have their own table and indexes.  */
 enum convert_optab_index
 {
@@ -659,8 +700,10 @@ enum direct_optab_index
   DOI_cmpstrn,
   DOI_cmpmem,
 
-  /* Synchronization primitives.  This first set is atomic operation for
-     which we don't care about the resulting value.  */
+  /* Atomic clear with release semantics.  */
+  DOI_sync_lock_release,
+
+  /* Atomic operation with no resulting value.  */
   DOI_sync_add,
   DOI_sync_sub,
   DOI_sync_ior,
@@ -668,33 +711,6 @@ enum direct_optab_index
   DOI_sync_xor,
   DOI_sync_nand,
 
-  /* This second set is atomic operations in which we return the value
-     that existed in memory before the operation.  */
-  DOI_sync_old_add,
-  DOI_sync_old_sub,
-  DOI_sync_old_ior,
-  DOI_sync_old_and,
-  DOI_sync_old_xor,
-  DOI_sync_old_nand,
-
-  /* This third set is atomic operations in which we return the value
-     that resulted after performing the operation.  */
-  DOI_sync_new_add,
-  DOI_sync_new_sub,
-  DOI_sync_new_ior,
-  DOI_sync_new_and,
-  DOI_sync_new_xor,
-  DOI_sync_new_nand,
-
-  /* Atomic compare and swap.  */
-  DOI_sync_compare_and_swap,
-
-  /* Atomic exchange with acquire semantics.  */
-  DOI_sync_lock_test_and_set,
-
-  /* Atomic clear with release semantics.  */
-  DOI_sync_lock_release,
-
   /* Atomic operations with memory model parameters. */
   DOI_atomic_exchange,
   DOI_atomic_compare_and_swap,
@@ -748,30 +764,14 @@ typedef struct direct_optab_d *direct_optab;
 #define cmpstr_optab (&direct_optab_table[(int) DOI_cmpstr])
 #define cmpstrn_optab (&direct_optab_table[(int) DOI_cmpstrn])
 #define cmpmem_optab (&direct_optab_table[(int) DOI_cmpmem])
+#define sync_lock_release_optab \
+  (&direct_optab_table[(int) DOI_sync_lock_release])
 #define sync_add_optab (&direct_optab_table[(int) DOI_sync_add])
 #define sync_sub_optab (&direct_optab_table[(int) DOI_sync_sub])
 #define sync_ior_optab (&direct_optab_table[(int) DOI_sync_ior])
 #define sync_and_optab (&direct_optab_table[(int) DOI_sync_and])
 #define sync_xor_optab (&direct_optab_table[(int) DOI_sync_xor])
 #define sync_nand_optab (&direct_optab_table[(int) DOI_sync_nand])
-#define sync_old_add_optab (&direct_optab_table[(int) DOI_sync_old_add])
-#define sync_old_sub_optab (&direct_optab_table[(int) DOI_sync_old_sub])
-#define sync_old_ior_optab (&direct_optab_table[(int) DOI_sync_old_ior])
-#define sync_old_and_optab (&direct_optab_table[(int) DOI_sync_old_and])
-#define sync_old_xor_optab (&direct_optab_table[(int) DOI_sync_old_xor])
-#define sync_old_nand_optab (&direct_optab_table[(int) DOI_sync_old_nand])
-#define sync_new_add_optab (&direct_optab_table[(int) DOI_sync_new_add])
-#define sync_new_sub_optab (&direct_optab_table[(int) DOI_sync_new_sub])
-#define sync_new_ior_optab (&direct_optab_table[(int) DOI_sync_new_ior])
-#define sync_new_and_optab (&direct_optab_table[(int) DOI_sync_new_and])
-#define sync_new_xor_optab (&direct_optab_table[(int) DOI_sync_new_xor])
-#define sync_new_nand_optab (&direct_optab_table[(int) DOI_sync_new_nand])
-#define sync_compare_and_swap_optab \
-  (&direct_optab_table[(int) DOI_sync_compare_and_swap])
-#define sync_lock_test_and_set_optab \
-  (&direct_optab_table[(int) DOI_sync_lock_test_and_set])
-#define sync_lock_release_optab \
-  (&direct_optab_table[(int) DOI_sync_lock_release])
 
 #define atomic_exchange_optab \
   (&direct_optab_table[(int) DOI_atomic_exchange])
@@ -956,6 +956,9 @@ extern void set_optab_libfunc (optab, enum machine_mode, const char *);
 extern void set_conv_libfunc (convert_optab, enum machine_mode,
 			      enum machine_mode, const char *);
 
+/* Call this to install all of the __sync libcalls up to size MAX.  */
+extern void init_sync_libfuncs (int max);
+
 /* Generate code for a FIXED_CONVERT_EXPR.  */
 extern void expand_fixed_convert (rtx, rtx, int, int);
 
@@ -966,7 +969,7 @@ extern void expand_float (rtx, rtx, int);
 enum insn_code can_float_p (enum machine_mode, enum machine_mode, int);
 
 /* Return true if there is an inline compare and swap pattern.  */
-extern bool can_compare_and_swap_p (enum machine_mode);
+extern bool can_compare_and_swap_p (enum machine_mode, bool);
 
 /* Generate code for a compare and swap.  */
 extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
-- 
1.7.6.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [cxx-mem-model 2/2] arm: Install __sync libfuncs for Linux.
  2011-11-03 23:27 [cxx-mem-model 0/2] Support the legacy __sync libcalls Richard Henderson
  2011-11-03 23:31 ` [cxx-mem-model 1/2] Allow libcalls to be installed for legacy __sync optabs Richard Henderson
@ 2011-11-03 23:37 ` Richard Henderson
  2011-11-24  1:10   ` Richard Henderson
  1 sibling, 1 reply; 6+ messages in thread
From: Richard Henderson @ 2011-11-03 23:37 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw

Cc: Richard Earnshaw <richard.earnshaw@arm.com>
---
 gcc/config/arm/arm.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 5f0d562..9963faa 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -1096,6 +1096,10 @@ arm_set_fixed_conv_libfunc (convert_optab optable, enum machine_mode to,
 static void
 arm_init_libfuncs (void)
 {
+  /* For Linux, we have access to kernel support for atomic operations.  */
+  if (arm_abi == ARM_ABI_AAPCS_LINUX)
+    init_sync_libfuncs (8);
+
   /* There are no special library functions unless we are using the
      ARM BPABI.  */
   if (!TARGET_BPABI)
-- 
1.7.6.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [cxx-mem-model 2/2] arm: Install __sync libfuncs for Linux.
  2011-11-03 23:37 ` [cxx-mem-model 2/2] arm: Install __sync libfuncs for Linux Richard Henderson
@ 2011-11-24  1:10   ` Richard Henderson
  2011-11-24 10:43     ` Richard Earnshaw
  0 siblings, 1 reply; 6+ messages in thread
From: Richard Henderson @ 2011-11-24  1:10 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Earnshaw, ramana.radhakrishnan

Ping 2.

r~

On 11/03/2011 04:24 PM, Richard Henderson wrote:
> Cc: Richard Earnshaw <richard.earnshaw@arm.com>
> ---
>  gcc/config/arm/arm.c |    4 ++++
>  1 files changed, 4 insertions(+), 0 deletions(-)
> 
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index 5f0d562..9963faa 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -1096,6 +1096,10 @@ arm_set_fixed_conv_libfunc (convert_optab optable, enum machine_mode to,
>  static void
>  arm_init_libfuncs (void)
>  {
> +  /* For Linux, we have access to kernel support for atomic operations.  */
> +  if (arm_abi == ARM_ABI_AAPCS_LINUX)
> +    init_sync_libfuncs (8);
> +
>    /* There are no special library functions unless we are using the
>       ARM BPABI.  */
>    if (!TARGET_BPABI)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [cxx-mem-model 2/2] arm: Install __sync libfuncs for Linux.
  2011-11-24  1:10   ` Richard Henderson
@ 2011-11-24 10:43     ` Richard Earnshaw
  2011-11-24 20:33       ` Richard Henderson
  0 siblings, 1 reply; 6+ messages in thread
From: Richard Earnshaw @ 2011-11-24 10:43 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Ramana Radhakrishnan

On 23/11/11 23:37, Richard Henderson wrote:
> Ping 2.
> 
> r~
> 
> On 11/03/2011 04:24 PM, Richard Henderson wrote:
>> Cc: Richard Earnshaw <richard.earnshaw@arm.com>
>> ---
>>  gcc/config/arm/arm.c |    4 ++++
>>  1 files changed, 4 insertions(+), 0 deletions(-)
>>
>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>> index 5f0d562..9963faa 100644
>> --- a/gcc/config/arm/arm.c
>> +++ b/gcc/config/arm/arm.c
>> @@ -1096,6 +1096,10 @@ arm_set_fixed_conv_libfunc (convert_optab optable, enum machine_mode to,
>>  static void
>>  arm_init_libfuncs (void)
>>  {
>> +  /* For Linux, we have access to kernel support for atomic operations.  */
>> +  if (arm_abi == ARM_ABI_AAPCS_LINUX)
>> +    init_sync_libfuncs (8);
>> +
>>    /* There are no special library functions unless we are using the
>>       ARM BPABI.  */
>>    if (!TARGET_BPABI)
> 
> 


What's the '8' for?  If it's the size of an object, then shouldn't this
really be something like GET_MODE_SIZE (DImode)?

Otherwise OK.

R.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [cxx-mem-model 2/2] arm: Install __sync libfuncs for Linux.
  2011-11-24 10:43     ` Richard Earnshaw
@ 2011-11-24 20:33       ` Richard Henderson
  0 siblings, 0 replies; 6+ messages in thread
From: Richard Henderson @ 2011-11-24 20:33 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: gcc-patches, Ramana Radhakrishnan

On 11/24/2011 02:06 AM, Richard Earnshaw wrote:
>>> >> +  /* For Linux, we have access to kernel support for atomic operations.  */
>>> >> +  if (arm_abi == ARM_ABI_AAPCS_LINUX)
>>> >> +    init_sync_libfuncs (8);
>>> >> +
>>> >>    /* There are no special library functions unless we are using the
>>> >>       ARM BPABI.  */
>>> >>    if (!TARGET_BPABI)
>> > 
>> > 
> 
> What's the '8' for?  If it's the size of an object, then shouldn't this
> really be something like GET_MODE_SIZE (DImode)?

Yes it's an object size.


r~

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-11-24 17:09 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-03 23:27 [cxx-mem-model 0/2] Support the legacy __sync libcalls Richard Henderson
2011-11-03 23:31 ` [cxx-mem-model 1/2] Allow libcalls to be installed for legacy __sync optabs Richard Henderson
2011-11-03 23:37 ` [cxx-mem-model 2/2] arm: Install __sync libfuncs for Linux Richard Henderson
2011-11-24  1:10   ` Richard Henderson
2011-11-24 10:43     ` Richard Earnshaw
2011-11-24 20:33       ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).