sync.md (sync_clobber, [...]): New code attribute.
authorKen Werner <ken.werner@de.ibm.com>
Fri, 31 Dec 2010 13:25:33 +0000 (13:25 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Fri, 31 Dec 2010 13:25:33 +0000 (13:25 +0000)
gcc/
2010-12-15  Ken Werner  <ken.werner@de.ibm.com>

* config/arm/sync.md (sync_clobber, sync_t2_reqd): New code attribute.
(arm_sync_old_<sync_optab>si, arm_sync_old_<sync_optab><mode>): Use
the sync_clobber and sync_t2_reqd code attributes.
* config/arm/arm.c (arm_output_sync_loop): Reverse the operation if
the t2 argument is NULL.

From-SVN: r168375

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/sync.md

index 2f31cb840b16075627a85606eeac4c93c508a4f6..39fd47a378e50b082b516b4d62dc2b18fdf4f6c9 100644 (file)
@@ -1,3 +1,11 @@
+2010-12-31  Ken Werner  <ken.werner@de.ibm.com>
+
+       * config/arm/sync.md (sync_clobber, sync_t2_reqd): New code attribute.
+       (arm_sync_old_<sync_optab>si, arm_sync_old_<sync_optab><mode>): Use
+       the sync_clobber and sync_t2_reqd code attributes.
+       * config/arm/arm.c (arm_output_sync_loop): Reverse the operation if
+       the t2 argument is NULL.
+
 2010-12-31  Gerald Pfeifer  <gerald@pfeifer.com>
 
        * doc/sourcebuild.texi (Top Level): Adjust link to libgo.
index 2aaec8c9eb21d50ae692c824b2a062024d6dd213..3e75d7c9c4d89b6bb0c1b7ad1a69fb4d18f3b8b5 100644 (file)
@@ -23266,10 +23266,46 @@ arm_output_sync_loop (emit_f emit,
       break;
     }
 
-  arm_output_strex (emit, mode, "", t2, t1, memory);
-  operands[0] = t2;
-  arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
-  arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=", LOCAL_LABEL_PREFIX);
+  if (t2)
+    {
+       arm_output_strex (emit, mode, "", t2, t1, memory);
+       operands[0] = t2;
+       arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
+       arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=",
+                           LOCAL_LABEL_PREFIX);
+    }
+  else
+    {
+      /* Use old_value for the return value because for some operations
+        the old_value can easily be restored.  This saves one register.  */
+      arm_output_strex (emit, mode, "", old_value, t1, memory);
+      operands[0] = old_value;
+      arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
+      arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=",
+                          LOCAL_LABEL_PREFIX);
+
+      switch (sync_op)
+       {
+       case SYNC_OP_ADD:
+         arm_output_op3 (emit, "sub", old_value, t1, new_value);
+         break;
+
+       case SYNC_OP_SUB:
+         arm_output_op3 (emit, "add", old_value, t1, new_value);
+         break;
+
+       case SYNC_OP_XOR:
+         arm_output_op3 (emit, "eor", old_value, t1, new_value);
+         break;
+
+       case SYNC_OP_NONE:
+         arm_output_op2 (emit, "mov", old_value, required_value);
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+    }
 
   arm_process_output_memory_barrier (emit, NULL);
   arm_output_asm_insn (emit, 1, operands, "%sLSYB%%=:", LOCAL_LABEL_PREFIX);
index 4c4b4fa106bdf86cc06f5eb2b34d58a54ca2ae6f..689a235c16f5e141eedf4acd08956b2e2b6ca697 100644 (file)
                              (plus "add")
                              (minus "sub")])
 
+(define_code_attr sync_clobber [(ior "=&r")
+                               (and "=&r")
+                               (xor "X")
+                               (plus "X")
+                               (minus "X")])
+
+(define_code_attr sync_t2_reqd [(ior "4")
+                               (and "4")
+                               (xor "*")
+                               (plus "*")
+                               (minus "*")])
+
 (define_expand "sync_<sync_optab>si"
   [(match_operand:SI 0 "memory_operand")
    (match_operand:SI 1 "s_register_operand")
          VUNSPEC_SYNC_COMPARE_AND_SWAP))
    (set (match_dup 1) (unspec_volatile:SI [(match_dup 2)]
                                           VUNSPEC_SYNC_COMPARE_AND_SWAP))
-   (clobber:SI (match_scratch:SI 4 "=&r"))
    (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
                                                 VUNSPEC_SYNC_COMPARE_AND_SWAP))
    ]
    (set_attr "sync_required_value"  "2")
    (set_attr "sync_new_value"       "3")
    (set_attr "sync_t1"              "0")
-   (set_attr "sync_t2"              "4")
    (set_attr "conds" "clob")
    (set_attr "predicable" "no")])
 
            VUNSPEC_SYNC_COMPARE_AND_SWAP)))
    (set (match_dup 1) (unspec_volatile:NARROW [(match_dup 2)]
                                           VUNSPEC_SYNC_COMPARE_AND_SWAP))
-   (clobber:SI (match_scratch:SI 4 "=&r"))
    (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
                                                 VUNSPEC_SYNC_COMPARE_AND_SWAP))
    ]
    (set_attr "sync_required_value"  "2")
    (set_attr "sync_new_value"       "3")
    (set_attr "sync_t1"              "0")
-   (set_attr "sync_t2"              "4")
    (set_attr "conds" "clob")
    (set_attr "predicable" "no")])
 
                            VUNSPEC_SYNC_OLD_OP))
    (clobber (reg:CC CC_REGNUM))
    (clobber (match_scratch:SI 3 "=&r"))
-   (clobber (match_scratch:SI 4 "=&r"))]
+   (clobber (match_scratch:SI 4 "<sync_clobber>"))]
   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
   {
     return arm_output_sync_insn (insn, operands);
    (set_attr "sync_memory"          "1")
    (set_attr "sync_new_value"       "2")
    (set_attr "sync_t1"              "3")
-   (set_attr "sync_t2"              "4")
+   (set_attr "sync_t2"              "<sync_t2_reqd>")
    (set_attr "sync_op"              "<sync_optab>")
    (set_attr "conds" "clob")
    (set_attr "predicable" "no")])
                            VUNSPEC_SYNC_OLD_OP))
    (clobber (reg:CC CC_REGNUM))
    (clobber (match_scratch:SI 3 "=&r"))
-   (clobber (match_scratch:SI 4 "=&r"))]
+   (clobber (match_scratch:SI 4 "<sync_clobber>"))]
   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
   {
     return arm_output_sync_insn (insn, operands);
    (set_attr "sync_memory"          "1")
    (set_attr "sync_new_value"       "2")
    (set_attr "sync_t1"              "3")
-   (set_attr "sync_t2"              "4")
+   (set_attr "sync_t2"              "<sync_t2_reqd>")
    (set_attr "sync_op"              "<sync_optab>")
    (set_attr "conds"               "clob")
    (set_attr "predicable" "no")])