aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel1@de.ibm.com>2006-11-24 13:30:59 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2006-11-24 13:30:59 +0000
commit8bb501bb101f74c9c02e949edad65f07615e27d0 (patch)
treea5a7094da9c34bd39de801a48073299a8a714627
parentaf1e323e93b86d33d9474dcdb64774b5e8c258e8 (diff)
downloadgcc-8bb501bb101f74c9c02e949edad65f07615e27d0.zip
gcc-8bb501bb101f74c9c02e949edad65f07615e27d0.tar.gz
gcc-8bb501bb101f74c9c02e949edad65f07615e27d0.tar.bz2
s390.c (s390_emit_compare_and_swap): New function.
2006-11-24 Andreas Krebbel <krebbel1@de.ibm.com> * config/s390.c (s390_emit_compare_and_swap): New function. (s390_expand_cs_hqi, s390_expand_atomic): Call s390_emit_compare_and_swap. 2006-11-24 Andreas Krebbel <krebbel1@de.ibm.com> * gcc.dg/20061124-1.c: New testcase. From-SVN: r119151
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/s390/s390.c32
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/20061124-1.c19
4 files changed, 51 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c671d35..a79d14b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2006-11-24 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * config/s390.c (s390_emit_compare_and_swap): New function.
+ (s390_expand_cs_hqi, s390_expand_atomic): Call
+ s390_emit_compare_and_swap.
+
2006-11-23 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* pa.c (return_addr_rtx): Change 0xe0400002 to -532676606.
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 59baba9..cfe959e 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -780,6 +780,24 @@ s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
return ret;
}
+/* Emit a SImode compare and swap instruction setting MEM to NEW if OLD
+ matches CMP.
+ Return the correct condition RTL to be placed in the IF_THEN_ELSE of the
+ conditional branch testing the result. */
+
+static rtx
+s390_emit_compare_and_swap (enum rtx_code code, rtx old, rtx mem, rtx cmp, rtx new)
+{
+ rtx ret;
+
+ emit_insn (gen_sync_compare_and_swap_ccsi (old, mem, cmp, new));
+ ret = gen_rtx_fmt_ee (code, VOIDmode, s390_compare_emitted, const0_rtx);
+
+ s390_compare_emitted = NULL_RTX;
+
+ return ret;
+}
+
/* Emit a jump instruction to TARGET. If COND is NULL_RTX, emit an
unconditional jump, else a conditional jump under condition COND. */
@@ -4187,11 +4205,9 @@ s390_expand_cs_hqi (enum machine_mode mode, rtx target, rtx mem, rtx cmp, rtx ne
newv = force_reg (SImode, expand_simple_binop (SImode, IOR, new, val,
NULL_RTX, 1, OPTAB_DIRECT));
- /* Emit compare_and_swap pattern. */
- emit_insn (gen_sync_compare_and_swap_ccsi (res, ac.memsi, cmpv, newv));
-
/* Jump to end if we're done (likely?). */
- s390_emit_jump (csend, s390_emit_compare (EQ, cmpv, ac.memsi));
+ s390_emit_jump (csend, s390_emit_compare_and_swap (EQ, res, ac.memsi,
+ cmpv, newv));
/* Check for changes outside mode. */
resv = expand_simple_binop (SImode, AND, res, ac.modemaski,
@@ -4284,13 +4300,9 @@ s390_expand_atomic (enum machine_mode mode, enum rtx_code code,
default:
gcc_unreachable ();
}
- /* Emit compare_and_swap pattern. */
- emit_insn (gen_sync_compare_and_swap_ccsi (cmp, ac.memsi, cmp, new));
- /* Loop until swapped (unlikely?). */
- s390_emit_jump (csloop, gen_rtx_fmt_ee (NE, CCZ1mode,
- gen_rtx_REG (CCZ1mode, CC_REGNUM),
- const0_rtx));
+ s390_emit_jump (csloop, s390_emit_compare_and_swap (NE, cmp,
+ ac.memsi, cmp, new));
/* Return the correct part of the bitfield. */
if (target)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ae246a1..b97aa16 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2006-11-24 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * gcc.dg/20061124-1.c: New testcase.
+
2006-11-23 Eric Christopher <echristo@apple.com>
* gcc.dg/inline-16.c: Use __SIZE_TYPE__.
diff --git a/gcc/testsuite/gcc.dg/20061124-1.c b/gcc/testsuite/gcc.dg/20061124-1.c
new file mode 100644
index 0000000..14d0439
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20061124-1.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sync_char_short } */
+
+/* This testcase failed on s390 because no compare instruction for
+ the check of FLAG was emitted. */
+
+unsigned short int count = 0;
+int flag = 1;
+
+extern void abort (void);
+
+int
+main ()
+{
+ __sync_add_and_fetch (&count, -1);
+
+ if (!flag)
+ abort ();
+}