summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2010-12-31 13:25:33 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2010-12-31 13:25:33 +0000
commit2b53b78468e28758402e81afcfedce480cc6904c (patch)
tree094341de3abe504189a7db587384ee3137c66926
parent88d4bd29039fc400e0e18f7a8a708fe28fa8b6f7 (diff)
downloadgcc-2b53b78468e28758402e81afcfedce480cc6904c.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@168375 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/arm/arm.c44
-rw-r--r--gcc/config/arm/sync.md24
3 files changed, 64 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2f31cb840b1..39fd47a378e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 2aaec8c9eb2..3e75d7c9c4d 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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);
diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md
index 4c4b4fa106b..689a235c16f 100644
--- a/gcc/config/arm/sync.md
+++ b/gcc/config/arm/sync.md
@@ -103,6 +103,18 @@
(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")
@@ -286,7 +298,6 @@
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))
]
@@ -299,7 +310,6 @@
(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")])
@@ -313,7 +323,6 @@
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))
]
@@ -326,7 +335,6 @@
(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")])
@@ -487,7 +495,7 @@
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);
@@ -496,7 +504,7 @@
(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")])
@@ -540,7 +548,7 @@
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);
@@ -549,7 +557,7 @@
(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")])