OSDN Git Service

2009-04-09 Paolo Bonzini <bonzini@gnu.org>
authorbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Apr 2009 10:57:03 +0000 (10:57 +0000)
committerbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Apr 2009 10:57:03 +0000 (10:57 +0000)
        * config/i386/i386.md (cmpcc): New.
        * config/i386/sync.md (sync_compare_and_swap*): Set FLAGS_REG.
        (sync_compare_and_swap_cc*): Delete.

        * config/s390/s390.c (s390_compare_emitted): Remove.
        (s390_emit_compare): Handle MODE_CC s390_compare_op0 like
        s390_compare_emitted used to be handled.  Assert that modes match.
        (s390_emit_compare_and_swap): Use s390_emit_compare, do not
        refer to sync_compare_and_swap_ccsi.
        * config/s390/s390.h (s390_compare_emitted): Remove.
        * config/s390/s390.md (seq): Look for MODE_CC s390_compare_op0
        instead of s390_compare_emitted.
        (stack_protect_test, sync_compare_and_swap_cc): Set s390_compare_op0
        instead of s390_compare_emitted.
        * config/s390/s390.md (cmpcc): New.
        (sync_compare_and_swapqi, sync_compare_and_swaphi): Clobber
        CC_REGNUM, do not pretend it's set.
        (sync_compare_and_swap_cc*): Delete.
        * config/s390/predicates.md (cc_reg_operand): New.

        * expr.c (sync_compare_and_swap_cc): Delete.
        * optabs.h (sync_compare_and_swap_cc): Delete.
        * optabs.c (prepare_cmp_insn): Ignore which specific CCmode
        is being used with can_compare_p.
        (emit_cmp_and_jump_insn_1): Likewise when looking in the optab.
        (find_cc_set): New.
        (expand_bool_compare_and_swap): Do not use sync_compare_and_swap_cc,
        look for a MODE_CC set instead.  Use emit_store_flag.
        (expand_compare_and_swap_loop): Likewise, with some additional
        complication to avoid a force_reg when useless.  Use
        emit_cmp_and_jump_insns.
        * genopinit.c (optabs): Delete sync_compare_and_swap_cc.
        * doc/md.texi (sync_compare_and_swap_cc): Merge with
        sync_compare_and_swap documentation.

java:
2009-04-09  Paolo Bonzini  <bonzini@gnu.org>

        * builtins.c (compareAndSwapLong_builtin,
        compareAndSwapInt_builtin, compareAndSwapObject_builtin,
        VMSupportsCS8_builtin): Do not look at sync_compare_and_swap_cc.

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

14 files changed:
gcc/ChangeLog
gcc/config/i386/i386.md
gcc/config/i386/sync.md
gcc/config/s390/predicates.md
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md
gcc/doc/md.texi
gcc/expr.c
gcc/genopinit.c
gcc/java/ChangeLog
gcc/java/builtins.c
gcc/optabs.c
gcc/optabs.h

index 7433c61..5337055 100644 (file)
@@ -1,3 +1,40 @@
+2009-04-09  Paolo Bonzini  <bonzini@gnu.org>
+
+        * config/i386/i386.md (cmpcc): New.
+        * config/i386/sync.md (sync_compare_and_swap*): Set FLAGS_REG.
+        (sync_compare_and_swap_cc*): Delete.
+
+        * config/s390/s390.c (s390_compare_emitted): Remove.
+        (s390_emit_compare): Handle MODE_CC s390_compare_op0 like
+        s390_compare_emitted used to be handled.  Assert that modes match.
+        (s390_emit_compare_and_swap): Use s390_emit_compare, do not
+        refer to sync_compare_and_swap_ccsi.
+        * config/s390/s390.h (s390_compare_emitted): Remove.
+        * config/s390/s390.md (seq): Look for MODE_CC s390_compare_op0
+        instead of s390_compare_emitted.
+        (stack_protect_test, sync_compare_and_swap_cc): Set s390_compare_op0
+        instead of s390_compare_emitted.
+        * config/s390/s390.md (cmpcc): New.
+        (sync_compare_and_swapqi, sync_compare_and_swaphi): Clobber
+        CC_REGNUM, do not pretend it's set.
+        (sync_compare_and_swap_cc*): Delete.
+        * config/s390/predicates.md (cc_reg_operand): New.
+
+        * expr.c (sync_compare_and_swap_cc): Delete.
+        * optabs.h (sync_compare_and_swap_cc): Delete.
+        * optabs.c (prepare_cmp_insn): Ignore which specific CCmode
+        is being used with can_compare_p.
+        (emit_cmp_and_jump_insn_1): Likewise when looking in the optab.
+        (find_cc_set): New.
+        (expand_bool_compare_and_swap): Do not use sync_compare_and_swap_cc,
+        look for a MODE_CC set instead.  Use emit_store_flag.
+        (expand_compare_and_swap_loop): Likewise, with some additional
+        complication to avoid a force_reg when useless.  Use
+        emit_cmp_and_jump_insns.
+        * genopinit.c (optabs): Delete sync_compare_and_swap_cc.
+        * doc/md.texi (sync_compare_and_swap_cc): Merge with
+        sync_compare_and_swap documentation.
+
 2009-04-09  Jan Hubicka  <jh@suse.cz>
 
        * except.c (find_prev_try): Break out from ....
index b388cd1..a72c1b7 100644 (file)
   DONE;
 })
 
+(define_expand "cmpcc"
+  [(set (reg:CC FLAGS_REG)
+        (compare:CC (match_operand 0 "flags_reg_operand" "")
+                    (match_operand 1 "general_operand" "")))]
+  ""
+{
+  ix86_compare_op0 = operands[0];
+  ix86_compare_op1 = operands[1];
+  DONE;
+})
+
 ;; FP compares, step 1:
 ;; Set the FP condition codes.
 ;;
index 7f92c14..7167a71 100644 (file)
             (match_operand:CASMODE 2 "register_operand" "")
             (match_operand:CASMODE 3 "register_operand" "")]
            UNSPECV_CMPXCHG))
-     (clobber (reg:CC FLAGS_REG))])]
+   (set (reg:CCZ FLAGS_REG)
+        (compare:CCZ
+          (unspec_volatile:CASMODE
+            [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG)
+          (match_dup 2)))])]
   "TARGET_CMPXCHG"
 {
   if ((<MODE>mode == DImode && !TARGET_64BIT) || <MODE>mode == TImode)
           (match_operand:IMODE 2 "register_operand" "a")
           (match_operand:IMODE 3 "register_operand" "<modeconstraint>")]
          UNSPECV_CMPXCHG))
-   (clobber (reg:CC FLAGS_REG))]
+   (set (reg:CCZ FLAGS_REG)
+        (compare:CCZ
+          (unspec_volatile:IMODE
+            [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG)
+          (match_dup 2)))]
   "TARGET_CMPXCHG"
   "lock{%;| }cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}")
 
           (match_operand:<DCASHMODE> 3 "register_operand" "b")
           (match_operand:<DCASHMODE> 4 "register_operand" "c")]
          UNSPECV_CMPXCHG))
-   (clobber (reg:CC FLAGS_REG))]
+   (set (reg:CCZ FLAGS_REG)
+        (compare:CCZ
+          (unspec_volatile:DCASMODE
+            [(match_dup 1) (match_dup 2) (match_dup 3) (match_dup 4)]
+           UNSPECV_CMPXCHG)
+          (match_dup 2)))]
   ""
   "lock{%;| }cmpxchg<doublemodesuffix>b\t%1")
 
           (match_operand:SI 3 "register_operand" "SD")
           (match_operand:SI 4 "register_operand" "c")]
          UNSPECV_CMPXCHG))
-   (clobber (reg:CC FLAGS_REG))]
-  "!TARGET_64BIT && TARGET_CMPXCHG8B && flag_pic"
-  "xchg{l}\t%%ebx, %3\;lock{%;| }cmpxchg8b\t%1\;xchg{l}\t%%ebx, %3")
-
-(define_expand "sync_compare_and_swap_cc<mode>"
-  [(parallel
-    [(set (match_operand:CASMODE 0 "register_operand" "")
-         (match_operand:CASMODE 1 "memory_operand" ""))
-     (set (match_dup 1)
-         (unspec_volatile:CASMODE
-           [(match_dup 1)
-            (match_operand:CASMODE 2 "register_operand" "")
-            (match_operand:CASMODE 3 "register_operand" "")]
-           UNSPECV_CMPXCHG))
-     (set (match_dup 4)
-         (compare:CCZ
-           (unspec_volatile:CASMODE
-             [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG)
-           (match_dup 2)))])]
-  "TARGET_CMPXCHG"
-{
-  operands[4] = gen_rtx_REG (CCZmode, FLAGS_REG);
-  ix86_compare_op0 = operands[4];
-  ix86_compare_op1 = const0_rtx;
-  if ((<MODE>mode == DImode && !TARGET_64BIT) || <MODE>mode == TImode)
-    {
-      enum machine_mode hmode = <MODE>mode == DImode ? SImode : DImode;
-      rtx low = simplify_gen_subreg (hmode, operands[3], <MODE>mode, 0);
-      rtx high = simplify_gen_subreg (hmode, operands[3], <MODE>mode,
-                                     GET_MODE_SIZE (hmode));
-      low = force_reg (hmode, low);
-      high = force_reg (hmode, high);
-      if (<MODE>mode == DImode)
-       {
-         if (flag_pic && !cmpxchg8b_pic_memory_operand (operands[1], DImode))
-           operands[1] = replace_equiv_address (operands[1],
-                                                force_reg (Pmode,
-                                                           XEXP (operands[1],
-                                                                 0)));
-         emit_insn (gen_sync_double_compare_and_swap_ccdi
-                    (operands[0], operands[1], operands[2], low, high));
-       }
-      else if (<MODE>mode == TImode)
-       emit_insn (gen_sync_double_compare_and_swap_ccti
-                  (operands[0], operands[1], operands[2], low, high));
-      else
-       gcc_unreachable ();
-      DONE;
-    }
-})
-
-(define_insn "*sync_compare_and_swap_cc<mode>"
-  [(set (match_operand:IMODE 0 "register_operand" "=a")
-       (match_operand:IMODE 1 "memory_operand" "+m"))
-   (set (match_dup 1)
-       (unspec_volatile:IMODE
-         [(match_dup 1)
-          (match_operand:IMODE 2 "register_operand" "a")
-          (match_operand:IMODE 3 "register_operand" "<modeconstraint>")]
-         UNSPECV_CMPXCHG))
-   (set (reg:CCZ FLAGS_REG)
-       (compare:CCZ
-         (unspec_volatile:IMODE
-           [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG)
-         (match_dup 2)))]
-  "TARGET_CMPXCHG"
-  "lock{%;| }cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}")
-
-(define_insn "sync_double_compare_and_swap_cc<mode>"
-  [(set (match_operand:DCASMODE 0 "register_operand" "=A")
-       (match_operand:DCASMODE 1 "memory_operand" "+m"))
-   (set (match_dup 1)
-       (unspec_volatile:DCASMODE
-         [(match_dup 1)
-          (match_operand:DCASMODE 2 "register_operand" "A")
-          (match_operand:<DCASHMODE> 3 "register_operand" "b")
-          (match_operand:<DCASHMODE> 4 "register_operand" "c")]
-         UNSPECV_CMPXCHG))
-   (set (reg:CCZ FLAGS_REG)
-       (compare:CCZ
-         (unspec_volatile:DCASMODE
-           [(match_dup 1) (match_dup 2) (match_dup 3) (match_dup 4)]
-           UNSPECV_CMPXCHG)
-         (match_dup 2)))]
-  ""
-  "lock{%;| }cmpxchg<doublemodesuffix>b\t%1")
-
-;; See above for the explanation of using the constraint "SD" for
-;; operand 3.
-(define_insn "*sync_double_compare_and_swap_ccdi_pic"
-  [(set (match_operand:DI 0 "register_operand" "=A")
-       (match_operand:DI 1 "cmpxchg8b_pic_memory_operand" "+m"))
-   (set (match_dup 1)
-       (unspec_volatile:DI
-         [(match_dup 1)
-          (match_operand:DI 2 "register_operand" "A")
-          (match_operand:SI 3 "register_operand" "SD")
-          (match_operand:SI 4 "register_operand" "c")]
-         UNSPECV_CMPXCHG))
    (set (reg:CCZ FLAGS_REG)
        (compare:CCZ
          (unspec_volatile:DI
index ca5d175..bb8fdf2 100644 (file)
   return (s390_branch_condition_mask (op) >= 0);
 })
 
+;; Return true if op is the cc register.
+(define_predicate "cc_reg_operand"
+  (and (match_code "reg")
+       (match_test "REGNO (op) == CC_REGNUM")))
+
 (define_predicate "s390_signed_integer_comparison"
   (match_code "eq, ne, lt, gt, le, ge")
 {
index eb08828..1cf9f8e 100644 (file)
@@ -224,13 +224,10 @@ struct processor_costs z10_cost =
 extern int reload_completed;
 
 /* Save information from a "cmpxx" operation until the branch or scc is
-   emitted.  */
+   emitted.  A pair of a MODE_CC register and a const0_rtx if a compare
+   has been emitted already.  */
 rtx s390_compare_op0, s390_compare_op1;
 
-/* Save the result of a compare_and_swap  until the branch or scc is
-   emitted.  */
-rtx s390_compare_emitted = NULL_RTX;
-
 /* Structure used to hold the components of a S/390 memory
    address.  A legitimate address on S/390 is of the general
    form
@@ -814,23 +811,23 @@ rtx
 s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
 {
   enum machine_mode mode = s390_select_ccmode (code, op0, op1);
-  rtx ret = NULL_RTX;
+  rtx cc;
 
   /* Do not output a redundant compare instruction if a compare_and_swap
      pattern already computed the result and the machine modes are compatible.  */
-  if (s390_compare_emitted 
-      && (s390_cc_modes_compatible (GET_MODE (s390_compare_emitted), mode)
-         == GET_MODE (s390_compare_emitted)))
-    ret = gen_rtx_fmt_ee (code, VOIDmode, s390_compare_emitted, const0_rtx); 
+  if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
+    {
+      gcc_assert (s390_cc_modes_compatible (GET_MODE (op0), mode)
+                 == GET_MODE (op0));
+      cc = op0;
+    }
   else
     {
-      rtx cc = gen_rtx_REG (mode, CC_REGNUM);
-      
+      cc = gen_rtx_REG (mode, CC_REGNUM);
       emit_insn (gen_rtx_SET (VOIDmode, cc, gen_rtx_COMPARE (mode, op0, op1)));
-      ret = gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx); 
     }
-  s390_compare_emitted = NULL_RTX;
-  return ret;
+
+  return gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx); 
 }
 
 /* Emit a SImode compare and swap instruction setting MEM to NEW_RTX if OLD
@@ -841,14 +838,8 @@ s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
 static rtx
 s390_emit_compare_and_swap (enum rtx_code code, rtx old, rtx mem, rtx cmp, rtx new_rtx)
 {
-  rtx ret;
-
-  emit_insn (gen_sync_compare_and_swap_ccsi (old, mem, cmp, new_rtx));
-  ret = gen_rtx_fmt_ee (code, VOIDmode, s390_compare_emitted, const0_rtx);
-
-  s390_compare_emitted = NULL_RTX;
-
-  return ret;
+  emit_insn (gen_sync_compare_and_swapsi (old, mem, cmp, new_rtx));
+  return s390_emit_compare (code, gen_rtx_REG (CCZ1mode, CC_REGNUM), const0_rtx);
 }
 
 /* Emit a jump instruction to TARGET.  If COND is NULL_RTX, emit an
index 449c1b6..bfe0268 100644 (file)
@@ -817,7 +817,7 @@ do {                                                                        \
 /* Define the information needed to generate branch and scc insns.  This is
    stored from the compare operation.  Note that we can't use "rtx" here
    since it hasn't been defined!  */
-extern struct rtx_def *s390_compare_op0, *s390_compare_op1, *s390_compare_emitted;
+extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
 
 
 /* Relative costs of operations.  */
index 7ecc3cc..16ed99e 100644 (file)
   DONE;
 })
 
+(define_expand "cmpcc"
+  [(set (reg:CC CC_REGNUM)
+        (compare:CC (match_operand 0 "cc_reg_operand" "")
+                    (match_operand 1 "general_operand" "")))]
+  ""
+{
+  s390_compare_op0 = operands[0];
+  s390_compare_op1 = operands[1];
+  DONE;
+})
 
 ; Test-under-Mask instructions
 
      (clobber (reg:CC CC_REGNUM))])]
   ""
 {
-  if (!s390_compare_emitted || GET_MODE (s390_compare_emitted) != CCZ1mode)
+  if (GET_MODE (s390_compare_op0) != CCZ1mode)
     FAIL;
   operands[1] = s390_emit_compare (NE, s390_compare_op0, s390_compare_op1);
   PUT_MODE (operands[1], SImode);
             (match_operand:HQI 2 "general_operand" "")
             (match_operand:HQI 3 "general_operand" "")]
            UNSPECV_CAS))
-     (set (reg:CCZ1 CC_REGNUM)
-         (compare:CCZ1 (match_dup 1) (match_dup 2)))])]
+     (clobber (reg:CC CC_REGNUM))])]
   ""
   "s390_expand_cs_hqi (<MODE>mode, operands[0], operands[1],
                       operands[2], operands[3]); DONE;")
 
-(define_expand "sync_compare_and_swap_cc<mode>"
-  [(parallel
-    [(set (match_operand:TDSI 0 "register_operand" "")
-         (match_operand:TDSI 1 "memory_operand" ""))
-     (set (match_dup 1)
-         (unspec_volatile:TDSI
-           [(match_dup 1)
-            (match_operand:TDSI 2 "register_operand" "")
-            (match_operand:TDSI 3 "register_operand" "")]
-           UNSPECV_CAS))
-     (set (match_dup 4)
-         (compare:CCZ1 (match_dup 1) (match_dup 2)))])]
-  ""
-{
-  /* Emulate compare.  */
-  operands[4] = gen_rtx_REG (CCZ1mode, CC_REGNUM);
-  s390_compare_op0 = operands[1];
-  s390_compare_op1 = operands[2];
-  s390_compare_emitted = operands[4];
-})
-
 ; cds, cdsg
 (define_insn "*sync_compare_and_swap<mode>"
   [(set (match_operand:DP 0 "register_operand" "=r")
     = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (),
                                         GEN_INT (TARGET_THREAD_SSP_OFFSET)));
 #endif
-  s390_compare_op0 = operands[0];
-  s390_compare_op1 = operands[1];
-  s390_compare_emitted = gen_rtx_REG (CCZmode, CC_REGNUM);
-
   if (TARGET_64BIT)
     emit_insn (gen_stack_protect_testdi (operands[0], operands[1]));
   else
     emit_insn (gen_stack_protect_testsi (operands[0], operands[1]));
 
+  s390_compare_op0 = gen_rtx_REG (CCZmode, CC_REGNUM);
+  s390_compare_op1 = const0_rtx;
   emit_jump_insn (gen_beq (operands[2]));
-
   DONE;
 })
 
index 25de8b1..a78233c 100644 (file)
@@ -5091,19 +5091,15 @@ memory operations before the atomic operation occur before the atomic
 operation and all memory operations after the atomic operation occur
 after the atomic operation.
 
-@cindex @code{sync_compare_and_swap_cc@var{mode}} instruction pattern
-@item @samp{sync_compare_and_swap_cc@var{mode}}
-
-This pattern is just like @code{sync_compare_and_swap@var{mode}}, except
-it should act as if compare part of the compare-and-swap were issued via
-@code{cmp@var{m}}.  This comparison will only be used with @code{EQ} and
-@code{NE} branches and @code{setcc} operations.
-
-Some targets do expose the success or failure of the compare-and-swap
-operation via the status flags.  Ideally we wouldn't need a separate
-named pattern in order to take advantage of this, but the combine pass
-does not handle patterns with multiple sets, which is required by
-definition for @code{sync_compare_and_swap@var{mode}}.
+For targets where the success or failure of the compare-and-swap
+operation is available via the status flags, it is possible
+to avoid a separate compare operation and issue the subsequent
+setcc or branch immediately after the compare-and-swap.  To this
+end, GCC will look for a @code{MODE_CC} set in the output of
+@code{sync_compare_and_swap@var{mode}}; if the machine description
+includes such a set, the target should also define a special @code{cmpcc}
+instruction.  GCC will then be able to take the destination of the
+@code{MODE_CC} set and use it as the first operand of @code{cmpcc}.
 
 @cindex @code{sync_add@var{mode}} instruction pattern
 @cindex @code{sync_sub@var{mode}} instruction pattern
index 5836e58..cd530d0 100644 (file)
@@ -234,7 +234,6 @@ enum insn_code sync_new_and_optab[NUM_MACHINE_MODES];
 enum insn_code sync_new_xor_optab[NUM_MACHINE_MODES];
 enum insn_code sync_new_nand_optab[NUM_MACHINE_MODES];
 enum insn_code sync_compare_and_swap[NUM_MACHINE_MODES];
-enum insn_code sync_compare_and_swap_cc[NUM_MACHINE_MODES];
 enum insn_code sync_lock_test_and_set[NUM_MACHINE_MODES];
 enum insn_code sync_lock_release[NUM_MACHINE_MODES];
 
index 1e778ba..8e13d1c 100644 (file)
@@ -234,7 +234,6 @@ static const char * const optabs[] =
   "sync_new_xor_optab[$A] = CODE_FOR_$(sync_new_xor$I$a$)",
   "sync_new_nand_optab[$A] = CODE_FOR_$(sync_new_nand$I$a$)",
   "sync_compare_and_swap[$A] = CODE_FOR_$(sync_compare_and_swap$I$a$)",
-  "sync_compare_and_swap_cc[$A] = CODE_FOR_$(sync_compare_and_swap_cc$I$a$)",
   "sync_lock_test_and_set[$A] = CODE_FOR_$(sync_lock_test_and_set$I$a$)",
   "sync_lock_release[$A] = CODE_FOR_$(sync_lock_release$I$a$)",
   "optab_handler (vec_set_optab, $A)->insn_code = CODE_FOR_$(vec_set$a$)",
index 62c76a7..c4479f2 100644 (file)
@@ -1,3 +1,9 @@
+2009-04-09  Paolo Bonzini  <bonzini@gnu.org>
+
+        * builtins.c (compareAndSwapLong_builtin,
+        compareAndSwapInt_builtin, compareAndSwapObject_builtin,
+        VMSupportsCS8_builtin): Do not look at sync_compare_and_swap_cc.
+
 2009-03-31  Richard Guenther  <rguenther@suse.de>
 
        * java-gimplify.c (java_gimplify_expr): Do not manually gimplify
index c9f9f4a..7ba12d3 100644 (file)
@@ -304,8 +304,7 @@ compareAndSwapInt_builtin (tree method_return_type ATTRIBUTE_UNUSED,
                           tree orig_call)
 {
   enum machine_mode mode = TYPE_MODE (int_type_node);
-  if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing 
-      || sync_compare_and_swap[mode] != CODE_FOR_nothing)
+  if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
     {
       tree addr, stmt;
       UNMARSHAL5 (orig_call);
@@ -324,8 +323,7 @@ compareAndSwapLong_builtin (tree method_return_type ATTRIBUTE_UNUSED,
                            tree orig_call)
 {
   enum machine_mode mode = TYPE_MODE (long_type_node);
-  if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing 
-      || sync_compare_and_swap[mode] != CODE_FOR_nothing)
+  if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
     {
       tree addr, stmt;
       UNMARSHAL5 (orig_call);
@@ -343,8 +341,7 @@ compareAndSwapObject_builtin (tree method_return_type ATTRIBUTE_UNUSED,
                              tree orig_call)
 {
   enum machine_mode mode = TYPE_MODE (ptr_type_node);
-  if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing 
-      || sync_compare_and_swap[mode] != CODE_FOR_nothing)
+  if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
   {
     tree addr, stmt;
     int builtin;
@@ -422,8 +419,7 @@ VMSupportsCS8_builtin (tree method_return_type,
 {
   enum machine_mode mode = TYPE_MODE (long_type_node);
   gcc_assert (method_return_type == boolean_type_node);
-  if (sync_compare_and_swap_cc[mode] != CODE_FOR_nothing 
-      || sync_compare_and_swap[mode] != CODE_FOR_nothing)
+  if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
     return boolean_true_node;
   else
     return boolean_false_node;
index 7057d9f..058cebe 100644 (file)
@@ -4143,11 +4143,15 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size,
 
   *px = x;
   *py = y;
-  if (can_compare_p (*pcomparison, mode, purpose))
+  if (GET_MODE_CLASS (mode) == MODE_CC)
+    {
+      gcc_assert (can_compare_p (*pcomparison, CCmode, purpose));
+      return;
+    }
+  else if (can_compare_p (*pcomparison, mode, purpose))
     return;
 
   /* Handle a lib call just for the mode we are using.  */
-
   libfunc = optab_libfunc (cmp_optab, mode);
   if (libfunc && !SCALAR_FLOAT_MODE_P (mode))
     {
@@ -4231,12 +4235,13 @@ emit_cmp_and_jump_insn_1 (rtx x, rtx y, enum machine_mode mode,
   /* Try combined insns first.  */
   do
     {
+      enum machine_mode optab_mode = mclass == MODE_CC ? CCmode : wider_mode;
       enum insn_code icode;
       PUT_MODE (test, wider_mode);
 
       if (label)
        {
-         icode = optab_handler (cbranch_optab, wider_mode)->insn_code;
+         icode = optab_handler (cbranch_optab, optab_mode)->insn_code;
 
          if (icode != CODE_FOR_nothing
              && insn_data[icode].operand[0].predicate (test, wider_mode))
@@ -4249,7 +4254,7 @@ emit_cmp_and_jump_insn_1 (rtx x, rtx y, enum machine_mode mode,
        }
 
       /* Handle some compares against zero.  */
-      icode = (int) optab_handler (tst_optab, wider_mode)->insn_code;
+      icode = (int) optab_handler (tst_optab, optab_mode)->insn_code;
       if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing)
        {
          x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
@@ -4261,7 +4266,7 @@ emit_cmp_and_jump_insn_1 (rtx x, rtx y, enum machine_mode mode,
 
       /* Handle compares for which there is a directly suitable insn.  */
 
-      icode = (int) optab_handler (cmp_optab, wider_mode)->insn_code;
+      icode = (int) optab_handler (cmp_optab, optab_mode)->insn_code;
       if (icode != CODE_FOR_nothing)
        {
          x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
@@ -6399,7 +6404,6 @@ init_optabs (void)
       sync_new_xor_optab[i] = CODE_FOR_nothing;
       sync_new_nand_optab[i] = CODE_FOR_nothing;
       sync_compare_and_swap[i] = CODE_FOR_nothing;
-      sync_compare_and_swap_cc[i] = CODE_FOR_nothing;
       sync_lock_test_and_set[i] = CODE_FOR_nothing;
       sync_lock_release[i] = CODE_FOR_nothing;
 
@@ -6970,6 +6974,21 @@ expand_val_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
   return expand_val_compare_and_swap_1 (mem, old_val, new_val, target, icode);
 }
 
+/* Helper function to find the MODE_CC set in a sync_compare_and_swap
+   pattern.  */
+
+static void
+find_cc_set (rtx x, const_rtx pat, void *data)
+{
+  if (REG_P (x) && GET_MODE_CLASS (GET_MODE (x)) == MODE_CC
+      && GET_CODE (pat) == SET)
+    {
+      rtx *p_cc_reg = (rtx *) data;
+      gcc_assert (!*p_cc_reg);
+      *p_cc_reg = x;
+    }
+}
+
 /* Expand a compare-and-swap operation and store true into the result if
    the operation was successful and false otherwise.  Return the result.
    Unlike other routines, TARGET is not optional.  */
@@ -6979,84 +6998,46 @@ expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
 {
   enum machine_mode mode = GET_MODE (mem);
   enum insn_code icode;
-  rtx subtarget, label0, label1;
+  rtx subtarget, seq, cc_reg;
 
   /* If the target supports a compare-and-swap pattern that simultaneously
      sets some flag for success, then use it.  Otherwise use the regular
      compare-and-swap and follow that immediately with a compare insn.  */
-  icode = sync_compare_and_swap_cc[mode];
-  switch (icode)
-    {
-    default:
-      subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val,
-                                                NULL_RTX, icode);
-      if (subtarget != NULL_RTX)
-       break;
-
-      /* FALLTHRU */
-    case CODE_FOR_nothing:
-      icode = sync_compare_and_swap[mode];
-      if (icode == CODE_FOR_nothing)
-       return NULL_RTX;
-
-      /* Ensure that if old_val == mem, that we're not comparing
-        against an old value.  */
-      if (MEM_P (old_val))
-       old_val = force_reg (mode, old_val);
+  icode = sync_compare_and_swap[mode];
+  if (icode == CODE_FOR_nothing)
+    return NULL_RTX;
 
+  do
+    {
+      start_sequence ();
       subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val,
-                                                NULL_RTX, icode);
+                                                NULL_RTX, icode);
+      cc_reg = NULL_RTX;
       if (subtarget == NULL_RTX)
-       return NULL_RTX;
-
-      emit_cmp_insn (subtarget, old_val, EQ, const0_rtx, mode, true);
-    }
-
-  /* If the target has a sane STORE_FLAG_VALUE, then go ahead and use a
-     setcc instruction from the beginning.  We don't work too hard here,
-     but it's nice to not be stupid about initial code gen either.  */
-  if (STORE_FLAG_VALUE == 1)
-    {
-      icode = setcc_gen_code[EQ];
-      if (icode != CODE_FOR_nothing)
        {
-         enum machine_mode cmode = insn_data[icode].operand[0].mode;
-         rtx insn;
-
-         subtarget = target;
-         if (!insn_data[icode].operand[0].predicate (target, cmode))
-           subtarget = gen_reg_rtx (cmode);
-
-         insn = GEN_FCN (icode) (subtarget);
-         if (insn)
-           {
-             emit_insn (insn);
-             if (GET_MODE (target) != GET_MODE (subtarget))
-               {
-                 convert_move (target, subtarget, 1);
-                 subtarget = target;
-               }
-             return subtarget;
-           }
+         end_sequence ();
+         return NULL_RTX;
        }
-    }
-
-  /* Without an appropriate setcc instruction, use a set of branches to
-     get 1 and 0 stored into target.  Presumably if the target has a
-     STORE_FLAG_VALUE that isn't 1, then this will get cleaned up by ifcvt.  */
 
-  label0 = gen_label_rtx ();
-  label1 = gen_label_rtx ();
+      if (have_insn_for (COMPARE, CCmode))
+       note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
+      seq = get_insns ();
+      end_sequence ();
 
-  emit_jump_insn (bcc_gen_fctn[EQ] (label0));
-  emit_move_insn (target, const0_rtx);
-  emit_jump_insn (gen_jump (label1));
-  emit_barrier ();
-  emit_label (label0);
-  emit_move_insn (target, const1_rtx);
-  emit_label (label1);
+      /* We might be comparing against an old value.  Try again. :-(  */
+      if (!cc_reg && MEM_P (old_val))
+       {
+         seq = NULL_RTX;
+         old_val = force_reg (mode, old_val);
+        }
+    }
+  while (!seq);
 
-  return target;
+  emit_insn (seq);
+  if (cc_reg)
+    return emit_store_flag (target, EQ, cc_reg, const0_rtx, VOIDmode, 0, 1);
+  else
+    return emit_store_flag (target, EQ, subtarget, old_val, VOIDmode, 1, 1);
 }
 
 /* This is a helper function for the other atomic operations.  This function
@@ -7073,7 +7054,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
 {
   enum machine_mode mode = GET_MODE (mem);
   enum insn_code icode;
-  rtx label, cmp_reg, subtarget;
+  rtx label, cmp_reg, subtarget, cc_reg;
 
   /* The loop we want to generate looks like
 
@@ -7100,37 +7081,32 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
   /* If the target supports a compare-and-swap pattern that simultaneously
      sets some flag for success, then use it.  Otherwise use the regular
      compare-and-swap and follow that immediately with a compare insn.  */
-  icode = sync_compare_and_swap_cc[mode];
-  switch (icode)
-    {
-    default:
-      subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg,
-                                                cmp_reg, icode);
-      if (subtarget != NULL_RTX)
-       {
-         gcc_assert (subtarget == cmp_reg);
-         break;
-       }
+  icode = sync_compare_and_swap[mode];
+  if (icode == CODE_FOR_nothing)
+    return false;
 
-      /* FALLTHRU */
-    case CODE_FOR_nothing:
-      icode = sync_compare_and_swap[mode];
-      if (icode == CODE_FOR_nothing)
-       return false;
+  subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg,
+                                            cmp_reg, icode);
+  if (subtarget == NULL_RTX)
+    return false;
 
-      subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg,
-                                                cmp_reg, icode);
-      if (subtarget == NULL_RTX)
-       return false;
+  cc_reg = NULL_RTX;
+  if (have_insn_for (COMPARE, CCmode))
+    note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
+  if (cc_reg)
+    {
+      cmp_reg = cc_reg;
+      old_reg = const0_rtx;
+    }
+  else
+    {
       if (subtarget != cmp_reg)
        emit_move_insn (cmp_reg, subtarget);
-
-      emit_cmp_insn (cmp_reg, old_reg, EQ, const0_rtx, mode, true);
     }
 
   /* ??? Mark this jump predicted not taken?  */
-  emit_jump_insn (bcc_gen_fctn[NE] (label));
-
+  emit_cmp_and_jump_insns (cmp_reg, old_reg, NE, const0_rtx, GET_MODE (cmp_reg), 1,
+                          label);
   return true;
 }
 
index 4d0ce52..a518dc6 100644 (file)
@@ -670,7 +670,6 @@ extern enum insn_code sync_new_nand_optab[NUM_MACHINE_MODES];
 
 /* Atomic compare and swap.  */
 extern enum insn_code sync_compare_and_swap[NUM_MACHINE_MODES];
-extern enum insn_code sync_compare_and_swap_cc[NUM_MACHINE_MODES];
 
 /* Atomic exchange with acquire semantics.  */
 extern enum insn_code sync_lock_test_and_set[NUM_MACHINE_MODES];