OSDN Git Service

2006-11-24 Andreas Krebbel <krebbel1@de.ibm.com>
authorkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 24 Nov 2006 13:30:59 +0000 (13:30 +0000)
committerkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 24 Nov 2006 13:30:59 +0000 (13:30 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119151 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/s390/s390.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/20061124-1.c [new file with mode: 0644]

index c671d35..a79d14b 100644 (file)
@@ -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.
index 59baba9..cfe959e 100644 (file)
@@ -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)
index ae246a1..b97aa16 100644 (file)
@@ -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 (file)
index 0000000..14d0439
--- /dev/null
@@ -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 ();
+}