aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2005-05-19 19:38:56 -0700
committerRichard Henderson <rth@gcc.gnu.org>2005-05-19 19:38:56 -0700
commitb686c48cd835838dad36de39d3e297e8d236c338 (patch)
tree752fb067b665acf9c4d281f624aeb5714431f180 /gcc
parentce88799c37e930e0b5e760119ea73237c43b5f61 (diff)
downloadgcc-b686c48cd835838dad36de39d3e297e8d236c338.zip
gcc-b686c48cd835838dad36de39d3e297e8d236c338.tar.gz
gcc-b686c48cd835838dad36de39d3e297e8d236c338.tar.bz2
alpha.c (emit_unlikely_jump, [...]): Split out from ...
* 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/alpha/alpha-protos.h2
-rw-r--r--gcc/config/alpha/alpha.c128
-rw-r--r--gcc/config/alpha/sync.md73
4 files changed, 123 insertions, 92 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f799f7d..8ddd133 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,17 @@
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.
2005-05-19 Richard Henderson <rth@redhat.com>
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index dc2b027..ee14006 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -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);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 66f9f48e..56e08c5 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -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);
}
/* Adjust the cost of a scheduling dependency. Return the new cost of
diff --git a/gcc/config/alpha/sync.md b/gcc/config/alpha/sync.md
index 8f67a4e..2cba9e3 100644
--- a/gcc/config/alpha/sync.md
+++ b/gcc/config/alpha/sync.md
@@ -221,49 +221,8 @@
"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")])
@@ -281,32 +240,8 @@
"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")])