alpha.c (emit_unlikely_jump, [...]): Split out from ...
authorRichard Henderson <rth@redhat.com>
Fri, 20 May 2005 02:38:56 +0000 (19:38 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 20 May 2005 02:38:56 +0000 (19:38 -0700)
        * config/alpha/alpha.c (emit_unlikely_jump, emit_load_locked,
        emit_store_conditional): Split out from ...
        (alpha_split_atomic_op): ... here.
        (alpha_split_compare_and_swap): New; extract from .md file.
        (alpha_split_lock_test_and_set): Likewise.
        * config/alpha/alpha-protos.h: Update.
        * config/alpha/sync.md (sync_compare_and_swap<I48MODE>): Move
        split code into alpha.c.
        (sync_lock_test_and_set<I48MODE>): Likewise.

From-SVN: r100005

gcc/ChangeLog
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/sync.md

index f799f7dc58865dc62665f1d9856fe988c955b2a3..8ddd13334b153b465d36ea496ec25b55c5032e5b 100644 (file)
@@ -1,3 +1,15 @@
+2005-05-19  Richard Henderson  <rth@redhat.com>
+
+       * config/alpha/alpha.c (emit_unlikely_jump, emit_load_locked,
+       emit_store_conditional): Split out from ...
+       (alpha_split_atomic_op): ... here.
+       (alpha_split_compare_and_swap): New; extract from .md file.
+       (alpha_split_lock_test_and_set): Likewise.
+       * config/alpha/alpha-protos.h: Update.
+       * config/alpha/sync.md (sync_compare_and_swap<I48MODE>): Move
+       split code into alpha.c.
+       (sync_lock_test_and_set<I48MODE>): Likewise.
+
 2005-05-19  Richard Henderson  <rth@redhat.com>
 
        * unwind.h, unwind-pe.h: Revert gcc_unreachable change of 05-17.
index dc2b027108bfd533565eb3f0ab85ac393899219c..ee14006f0e26ab3b8ed36843318eff27bccfa822 100644 (file)
@@ -102,6 +102,8 @@ extern int alpha_split_conditional_move (enum rtx_code, rtx, rtx, rtx, rtx);
 extern void alpha_emit_xfloating_arith (enum rtx_code, rtx[]);
 extern void alpha_emit_xfloating_cvt (enum rtx_code, rtx[]);
 extern void alpha_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
+extern void alpha_split_compare_and_swap (rtx, rtx, rtx, rtx, rtx);
+extern void alpha_split_lock_test_and_set (rtx, rtx, rtx, rtx);
 #endif
 
 extern rtx alpha_need_linkage (const char *, int);
index 66f9f48ea9464b83e7794453c7e02c5bdaeeefde..56e08c5339ab29c8603d28bd03327a6c4c5a0d47 100644 (file)
@@ -4448,6 +4448,48 @@ alpha_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx),
   emit_insn ((*gen) (op0, op1, op2));
 }
 
+/* A subroutine of the atomic operation splitters.  Jump to LABEL if
+   COND is true.  Mark the jump as unlikely to be taken.  */
+
+static void
+emit_unlikely_jump (rtx cond, rtx label)
+{
+  rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
+  rtx x;
+
+  x = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label, pc_rtx);
+  x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
+  REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
+}
+
+/* A subroutine of the atomic operation splitters.  Emit a load-locked
+   instruction in MODE.  */
+
+static void
+emit_load_locked (enum machine_mode mode, rtx reg, rtx mem)
+{
+  rtx (*fn) (rtx, rtx) = NULL;
+  if (mode == SImode)
+    fn = gen_load_locked_si;
+  else if (mode == DImode)
+    fn = gen_load_locked_di;
+  emit_insn (fn (reg, mem));
+}
+
+/* A subroutine of the atomic operation splitters.  Emit a store-conditional
+   instruction in MODE.  */
+
+static void
+emit_store_conditional (enum machine_mode mode, rtx res, rtx mem, rtx val)
+{
+  rtx (*fn) (rtx, rtx, rtx) = NULL;
+  if (mode == SImode)
+    fn = gen_store_conditional_si;
+  else if (mode == DImode)
+    fn = gen_store_conditional_di;
+  emit_insn (fn (res, mem, val));
+}
+
 /* Expand an an atomic fetch-and-operate pattern.  CODE is the binary operation
    to perform.  MEM is the memory on which to operate.  VAL is the second 
    operand of the binary operator.  BEFORE and AFTER are optional locations to
@@ -4459,8 +4501,7 @@ alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
                       rtx before, rtx after, rtx scratch)
 {
   enum machine_mode mode = GET_MODE (mem);
-  rtx label, cond, x;
-  rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
+  rtx label, x, cond = gen_rtx_REG (DImode, REGNO (scratch));
 
   emit_insn (gen_memory_barrier ());
 
@@ -4470,40 +4511,81 @@ alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
 
   if (before == NULL)
     before = scratch;
-
-  if (mode == SImode)
-    emit_insn (gen_load_locked_si (before, mem));
-  else if (mode == DImode)
-    emit_insn (gen_load_locked_di (before, mem));
-  else
-    gcc_unreachable ();
+  emit_load_locked (mode, before, mem);
 
   if (code == NOT)
-    {
-      x = gen_rtx_NOT (mode, before);
-      x = gen_rtx_AND (mode, x, val);
-    }
+    x = gen_rtx_AND (mode, gen_rtx_NOT (mode, before), val);
   else
     x = gen_rtx_fmt_ee (code, mode, before, val);
-
   if (after)
     emit_insn (gen_rtx_SET (VOIDmode, after, copy_rtx (x)));
   emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
 
-  cond = gen_rtx_REG (DImode, REGNO (scratch));
-  if (mode == SImode)
-    emit_insn (gen_store_conditional_si (cond, mem, scratch));
-  else if (mode == DImode)
-    emit_insn (gen_store_conditional_di (cond, mem, scratch));
+  emit_store_conditional (mode, cond, mem, scratch);
+
+  x = gen_rtx_EQ (DImode, cond, const0_rtx);
+  emit_unlikely_jump (x, label);
+
+  emit_insn (gen_memory_barrier ());
+}
+
+/* Expand a compare and swap operation.  */
+
+void
+alpha_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
+                             rtx scratch)
+{
+  enum machine_mode mode = GET_MODE (mem);
+  rtx label1, label2, x, cond = gen_lowpart (DImode, scratch);
+
+  emit_insn (gen_memory_barrier ());
+
+  label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+  label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+  emit_label (XEXP (label1, 0));
+
+  emit_load_locked (mode, retval, mem);
+
+  x = gen_lowpart (DImode, retval);
+  if (oldval == const0_rtx)
+    x = gen_rtx_NE (DImode, x, const0_rtx);
   else
-    gcc_unreachable ();
+    {
+      x = gen_rtx_EQ (DImode, x, oldval);
+      emit_insn (gen_rtx_SET (VOIDmode, cond, x));
+      x = gen_rtx_EQ (DImode, cond, const0_rtx);
+    }
+  emit_unlikely_jump (x, label2);
+
+  emit_move_insn (scratch, newval);
+  emit_store_conditional (mode, cond, mem, scratch);
 
   x = gen_rtx_EQ (DImode, cond, const0_rtx);
-  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label, pc_rtx);
-  x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
-  REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
+  emit_unlikely_jump (x, label1);
 
   emit_insn (gen_memory_barrier ());
+  emit_label (XEXP (label2, 0));
+}
+
+/* Expand an atomic exchange operation.  */
+
+void
+alpha_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
+{
+  enum machine_mode mode = GET_MODE (mem);
+  rtx label, x, cond = gen_lowpart (DImode, scratch);
+
+  emit_insn (gen_memory_barrier ());
+
+  label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+  emit_label (XEXP (label, 0));
+
+  emit_load_locked (mode, retval, mem);
+  emit_move_insn (scratch, val);
+  emit_store_conditional (mode, cond, mem, scratch);
+
+  x = gen_rtx_EQ (DImode, cond, const0_rtx);
+  emit_unlikely_jump (x, label);
 }
 \f
 /* Adjust the cost of a scheduling dependency.  Return the new cost of
index 8f67a4e255d2a461cdc52d37efc3416df0ef4c48..2cba9e372f232c8e1989c862c883b6aadf858e5a 100644 (file)
   "reload_completed"
   [(const_int 0)]
 {
-  rtx retval, mem, oldval, newval, scratch;
-  rtx cond, label1, label2, x;
-  rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
-
-  retval = operands[0];
-  mem = operands[1];
-  oldval = operands[2];
-  newval = operands[3];
-  scratch = operands[4];
-  cond = gen_lowpart (DImode, scratch);
-
-  emit_insn (gen_memory_barrier ());
-
-  label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
-  label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
-  emit_label (XEXP (label1, 0));
-
-  emit_insn (gen_load_locked_<mode> (retval, mem));
-
-  x = gen_lowpart (DImode, retval);
-  if (oldval == const0_rtx)
-    x = gen_rtx_NE (DImode, x, const0_rtx);
-  else
-    {
-      x = gen_rtx_EQ (DImode, x, oldval);
-      emit_insn (gen_rtx_SET (VOIDmode, cond, x));
-      x = gen_rtx_EQ (DImode, cond, const0_rtx);
-    }
-  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label2, pc_rtx);
-  x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
-  REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
-    
-  emit_move_insn (scratch, newval);
-
-  emit_insn (gen_store_conditional_<mode> (cond, mem, scratch));
-
-  x = gen_rtx_EQ (DImode, cond, const0_rtx);
-  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label1, pc_rtx);
-  x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
-  REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
-
-  emit_insn (gen_memory_barrier ());
-  emit_label (XEXP (label2, 0));
+  alpha_split_compare_and_swap (operands[0], operands[1], operands[2],
+                               operands[3], operands[4]);
   DONE;
 }
   [(set_attr "type" "multi")])
   "reload_completed"
   [(const_int 0)]
 {
-  rtx retval, mem, val, scratch;
-  rtx cond, label1, x;
-  rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
-
-  retval = operands[0];
-  mem = operands[1];
-  val = operands[2];
-  scratch = operands[3];
-  cond = gen_lowpart (DImode, scratch);
-
-  emit_insn (gen_memory_barrier ());
-
-  label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
-  emit_label (XEXP (label1, 0));
-
-  emit_insn (gen_load_locked_<mode> (retval, mem));
-
-  emit_move_insn (scratch, val);
-  
-  emit_insn (gen_store_conditional_<mode> (cond, mem, scratch));
-
-  x = gen_rtx_EQ (DImode, cond, const0_rtx);
-  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label1, pc_rtx);
-  x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
-  REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
-
+  alpha_split_lock_test_and_set (operands[0], operands[1],
+                                operands[2], operands[3]);
   DONE;
 }
   [(set_attr "type" "multi")])