diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-12-31 13:25:33 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-12-31 13:25:33 +0000 |
commit | 2b53b78468e28758402e81afcfedce480cc6904c (patch) | |
tree | 094341de3abe504189a7db587384ee3137c66926 | |
parent | 88d4bd29039fc400e0e18f7a8a708fe28fa8b6f7 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 44 | ||||
-rw-r--r-- | gcc/config/arm/sync.md | 24 |
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")]) |