---
 gcc/config/arm/arm.c   |   52 +++++++++++++++++++++-------------------
 gcc/config/arm/arm.md  |    4 +-
 gcc/config/arm/sync.md |   62 +++++++++++++++++++++++++----------------------
 3 files changed, 62 insertions(+), 56 deletions(-)

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index da99496..c02d294 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -24562,9 +24562,9 @@ emit_unlikely_jump (rtx insn)
 void
 arm_expand_compare_and_swap (rtx operands[])
 {
-  rtx bval, rval, mem, oldval, newval, is_weak, mod_s, mod_f;
+  rtx bval, rval, mem, oldval, newval, is_weak, mod_s, mod_f, x;
   enum machine_mode mode;
-  rtx (*gen) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  rtx (*gen) (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
 
   bval = operands[0];
   rval = operands[1];
@@ -24612,10 +24612,17 @@ arm_expand_compare_and_swap (rtx operands[])
       gcc_unreachable ();
     }
 
-  emit_insn (gen (bval, rval, mem, oldval, newval, is_weak, mod_s, mod_f));
+  emit_insn (gen (rval, mem, oldval, newval, is_weak, mod_s, mod_f));
 
   if (mode == QImode || mode == HImode)
     emit_move_insn (operands[1], gen_lowpart (mode, rval));
+
+  /* In all cases, we arrange for success to be signaled by Z set.
+     This arrangement allows for the boolean result to be used directly
+     in a subsequent branch, post optimization.  */
+  x = gen_rtx_REG (CCmode, CC_REGNUM);
+  x = gen_rtx_EQ (SImode, x, const0_rtx);
+  emit_insn (gen_rtx_SET (VOIDmode, bval, x));
 }
 
 /* Split a compare and swap pattern.  It is IMPLEMENTATION DEFINED whether
@@ -24627,24 +24634,22 @@ arm_expand_compare_and_swap (rtx operands[])
 void
 arm_split_compare_and_swap (rtx operands[])
 {
-  rtx bval, rval, mem, oldval, newval;
+  rtx rval, mem, oldval, newval, scratch;
   enum machine_mode mode;
   enum memmodel mod_s, mod_f;
   bool is_weak;
   rtx label1, label2, x, cond;
 
-  bval = operands[0];
-  rval = operands[1];
-  mem = operands[2];
-  oldval = operands[3];
-  newval = operands[4];
-  is_weak = (operands[5] != const0_rtx);
-  mod_s = (enum memmodel) INTVAL (operands[6]);
-  mod_f = (enum memmodel) INTVAL (operands[7]);
+  rval = operands[0];
+  mem = operands[1];
+  oldval = operands[2];
+  newval = operands[3];
+  is_weak = (operands[4] != const0_rtx);
+  mod_s = (enum memmodel) INTVAL (operands[5]);
+  mod_f = (enum memmodel) INTVAL (operands[6]);
+  scratch = operands[7];
   mode = GET_MODE (mem);
 
-  emit_move_insn (bval, const0_rtx);
-
   arm_pre_atomic_barrier (mod_s);
 
   label1 = NULL_RTX;
@@ -24664,20 +24669,17 @@ arm_split_compare_and_swap (rtx operands[])
     x = gen_cbranchsi4 (x, rval, oldval, label2);
   emit_unlikely_jump (x);
 
-  arm_emit_store_exclusive (mode, bval, mem, newval);
+  arm_emit_store_exclusive (mode, scratch, mem, newval);
 
-  /* Thumb1 does not have LDREX, so we do not need to consider that
-     when it comes to computing the below.  */
-  gcc_assert (TARGET_32BIT);
+  /* Weak or strong, we want EQ to be true for success, so that we
+     match the flags that we got from the compare above.  Thus we
+     prefer to use TEQ instead of TST here.  */
+  emit_insn (gen_xorsi3_compare0_scratch (scratch, const1_rtx));
 
-  if (is_weak)
-    emit_insn (gen_xorsi3 (bval, bval, const1_rtx));
-  else
+  if (!is_weak)
     {
-      emit_insn (gen_xorsi3_compare0 (bval, bval, const1_rtx));
-
-      cond = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
-      x = gen_rtx_EQ (VOIDmode, cond, const0_rtx);
+      cond = gen_rtx_REG (CCmode, CC_REGNUM);
+      x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
       x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
                                gen_rtx_LABEL_REF (Pmode, label1), pc_rtx);
       emit_unlikely_jump (gen_rtx_SET (VOIDmode, pc_rtx, x));
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index f006495..b01343c 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -3062,7 +3062,7 @@
   [(set_attr "length" "2")
    (set_attr "conds" "set")])
 
-(define_insn "xorsi3_compare0"
+(define_insn "*xorsi3_compare0"
   [(set (reg:CC_NOOV CC_REGNUM)
        (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
                                 (match_operand:SI 2 "arm_rhs_operand" "rI"))
@@ -3074,7 +3074,7 @@
   [(set_attr "conds" "set")]
 )
 
-(define_insn "*xorsi3_compare0_scratch"
+(define_insn "xorsi3_compare0_scratch"
   [(set (reg:CC_NOOV CC_REGNUM)
        (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
                                 (match_operand:SI 1 "arm_rhs_operand" "rI"))
diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md
index 72e7181..492fadc 100644
--- a/gcc/config/arm/sync.md
+++ b/gcc/config/arm/sync.md
@@ -85,20 +85,20 @@
 })
 
 (define_insn_and_split "atomic_compare_and_swap<mode>_1"
-  [(set (match_operand:SI 0 "s_register_operand" "=&r")                ;; bool 
out
-       (unspec_volatile:SI [(const_int 0)] VUNSPEC_ATOMIC_CAS))
-   (set (match_operand:SI 1 "s_register_operand" "=&r")                ;; val 
out
+  [(set (reg:CC_Z CC_REGNUM)                                   ;; bool out
+       (unspec_volatile:CC_Z [(const_int 0)] VUNSPEC_ATOMIC_CAS))
+   (set (match_operand:SI 0 "s_register_operand" "=&r")                ;; val 
out
        (zero_extend:SI
-         (match_operand:NARROW 2 "mem_noofs_operand" "+Ua")))  ;; memory
-   (set (match_dup 2)
+         (match_operand:NARROW 1 "mem_noofs_operand" "+Ua")))  ;; memory
+   (set (match_dup 1)
        (unspec_volatile:NARROW
-         [(match_operand:SI 3 "arm_add_operand" "rIL")         ;; expected
-          (match_operand:NARROW 4 "s_register_operand" "r")    ;; desired
-          (match_operand:SI 5 "const_int_operand")             ;; is_weak
-          (match_operand:SI 6 "const_int_operand")             ;; mod_s
-          (match_operand:SI 7 "const_int_operand")]            ;; mod_f
+         [(match_operand:SI 2 "arm_add_operand" "rIL")         ;; expected
+          (match_operand:NARROW 3 "s_register_operand" "r")    ;; desired
+          (match_operand:SI 4 "const_int_operand")             ;; is_weak
+          (match_operand:SI 5 "const_int_operand")             ;; mod_s
+          (match_operand:SI 6 "const_int_operand")]            ;; mod_f
          VUNSPEC_ATOMIC_CAS))
-   (clobber (reg:CC CC_REGNUM))]
+   (clobber (match_scratch:SI 7 "=&r"))]
   "<sync_predtab>"
   "#"
   "&& reload_completed"
@@ -114,19 +114,19 @@
   [(SI "rIL") (DI "rDi")])
 
 (define_insn_and_split "atomic_compare_and_swap<mode>_1"
-  [(set (match_operand:SI 0 "s_register_operand" "=&r")                ;; bool 
out
-       (unspec_volatile:SI [(const_int 0)] VUNSPEC_ATOMIC_CAS))
-   (set (match_operand:SIDI 1 "s_register_operand" "=&r")      ;; val out
-       (match_operand:SIDI 2 "mem_noofs_operand" "+Ua"))       ;; memory
-   (set (match_dup 2)
+  [(set (reg:CC_Z CC_REGNUM)                                   ;; bool out
+       (unspec_volatile:CC_Z [(const_int 0)] VUNSPEC_ATOMIC_CAS))
+   (set (match_operand:SIDI 0 "s_register_operand" "=&r")      ;; val out
+       (match_operand:SIDI 1 "mem_noofs_operand" "+Ua"))       ;; memory
+   (set (match_dup 1)
        (unspec_volatile:SIDI
-         [(match_operand:SIDI 3 "<cas_cmp_operand>" "<cas_cmp_str>") ;; expect
-          (match_operand:SIDI 4 "s_register_operand" "r")      ;; desired
-          (match_operand:SI 5 "const_int_operand")             ;; is_weak
-          (match_operand:SI 6 "const_int_operand")             ;; mod_s
-          (match_operand:SI 7 "const_int_operand")]            ;; mod_f
+         [(match_operand:SIDI 2 "<cas_cmp_operand>" "<cas_cmp_str>") ;; expect
+          (match_operand:SIDI 3 "s_register_operand" "r")      ;; desired
+          (match_operand:SI 4 "const_int_operand")             ;; is_weak
+          (match_operand:SI 5 "const_int_operand")             ;; mod_s
+          (match_operand:SI 6 "const_int_operand")]            ;; mod_f
          VUNSPEC_ATOMIC_CAS))
-   (clobber (reg:CC CC_REGNUM))]
+   (clobber (match_scratch:SI 7 "=&r"))]
   "<sync_predtab>"
   "#"
   "&& reload_completed"
@@ -360,7 +360,8 @@
            [(match_operand:NARROW 1 "mem_noofs_operand" "Ua")]
            VUNSPEC_LL)))]
   "TARGET_HAVE_LDREXBH"
-  "ldrex<sync_sfx>\t%0, %C1")
+  "ldrex<sync_sfx>%?\t%0, %C1"
+  [(set_attr "predicable" "yes")])
 
 (define_insn "arm_load_exclusivesi"
   [(set (match_operand:SI 0 "s_register_operand" "=r")
@@ -368,7 +369,8 @@
          [(match_operand:SI 1 "mem_noofs_operand" "Ua")]
          VUNSPEC_LL))]
   "TARGET_HAVE_LDREX"
-  "ldrex\t%0, %C1")
+  "ldrex%?\t%0, %C1"
+  [(set_attr "predicable" "yes")])
 
 (define_insn "arm_load_exclusivedi"
   [(set (match_operand:DI 0 "s_register_operand" "=r")
@@ -384,8 +386,9 @@
        Note that the 1st register always gets the lowest word in memory.  */
     gcc_assert ((REGNO (target) & 1) == 0);
     operands[2] = gen_rtx_REG (SImode, REGNO (target) + 1);
-    return "ldrexd\t%0, %2, %C1";
-  })
+    return "ldrexd%?\t%0, %2, %C1";
+  }
+  [(set_attr "predicable" "yes")])
 
 (define_insn "arm_store_exclusive<mode>"
   [(set (match_operand:SI 0 "s_register_operand" "=&r")
@@ -405,7 +408,8 @@
           Note that the 1st register always gets the lowest word in memory.  */
        gcc_assert ((REGNO (value) & 1) == 0 || TARGET_THUMB2);
        operands[3] = gen_rtx_REG (SImode, REGNO (value) + 1);
-       return "strexd\t%0, %2, %3, %C1";
+       return "strexd%?\t%0, %2, %3, %C1";
       }
-    return "strex<sync_sfx>\t%0, %2, %C1";
-  })
+    return "strex<sync_sfx>%?\t%0, %2, %C1";
+  }
+  [(set_attr "predicable" "yes")])
-- 
1.7.6.4

Reply via email to