diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/sh/sh.h | 6 | ||||
-rw-r--r-- | gcc/config/sh/sh.opt | 4 | ||||
-rw-r--r-- | gcc/config/sh/sync.md | 58 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 12 |
5 files changed, 87 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b19d883..f101f7c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2012-03-05 Oleg Endo <olegendo@gcc.gnu.org> + + * config/sh/sh.h (TARGET_ATOMIC_TEST_AND_SET_TRUEVAL): New hook. + * config/sh/sync.md (atomic_test_and_set): New expander. + (tasb, atomic_test_and_set_soft): New insns. + * config/sh/sh.opt (menable-tas): New option. + * doc/invoke.texi (SH Options): Document it. + 2012-03-05 Richard Guenther <rguenther@suse.de> * cfgloop.c (verify_loop_structure): Verify dominators before diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 7a2af0a..7e729478 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -2473,4 +2473,10 @@ extern int current_function_interrupt; /* FIXME: middle-end support for highpart optimizations is missing. */ #define high_life_started reload_in_progress +/* The tas.b instruction sets the 7th bit in the byte, i.e. 0x80. + This value is used by optabs.c atomic op expansion code as well as in + sync.md. */ +#undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL +#define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 0x80 + #endif /* ! GCC_SH_H */ diff --git a/gcc/config/sh/sh.opt b/gcc/config/sh/sh.opt index ea87d25..37b9990 100644 --- a/gcc/config/sh/sh.opt +++ b/gcc/config/sh/sh.opt @@ -323,6 +323,10 @@ msoft-atomic Target Report Mask(SOFT_ATOMIC) Use software atomic sequences supported by kernel +menable-tas +Target Report RejectNegative Var(TARGET_ENABLE_TAS) +Use tas.b instruction for __atomic_test_and_set + mspace Target RejectNegative Alias(Os) Deprecated. Use -Os instead diff --git a/gcc/config/sh/sync.md b/gcc/config/sh/sync.md index 5e55947..113288c 100644 --- a/gcc/config/sh/sync.md +++ b/gcc/config/sh/sync.md @@ -404,3 +404,61 @@ "1: mov r1,r15"; } [(set_attr "length" "18")]) + +(define_expand "atomic_test_and_set" + [(match_operand:SI 0 "register_operand" "") ;; bool result output + (match_operand:QI 1 "memory_operand" "") ;; memory + (match_operand:SI 2 "const_int_operand" "")] ;; model + "(TARGET_SOFT_ATOMIC || TARGET_ENABLE_TAS) && !TARGET_SHMEDIA" +{ + rtx addr = force_reg (Pmode, XEXP (operands[1], 0)); + + if (TARGET_ENABLE_TAS) + emit_insn (gen_tasb (addr)); + else + { + rtx val = force_reg (QImode, + gen_int_mode (TARGET_ATOMIC_TEST_AND_SET_TRUEVAL, + QImode)); + emit_insn (gen_atomic_test_and_set_soft (addr, val)); + } + + /* The result of the test op is the inverse of what we are + supposed to return. Thus invert the T bit. The inversion will be + potentially optimized away and integrated into surrounding code. */ + emit_insn (gen_movnegt (operands[0])); + DONE; +}) + +(define_insn "tasb" + [(set (reg:SI T_REG) + (eq:SI (mem:QI (match_operand:SI 0 "register_operand" "r")) + (const_int 0))) + (set (mem:QI (match_dup 0)) + (unspec:QI [(const_int 128)] UNSPEC_ATOMIC))] + "TARGET_ENABLE_TAS && !TARGET_SHMEDIA" + "tas.b @%0" + [(set_attr "insn_class" "co_group")]) + +(define_insn "atomic_test_and_set_soft" + [(set (reg:SI T_REG) + (eq:SI (mem:QI (match_operand:SI 0 "register_operand" "u")) + (const_int 0))) + (set (mem:QI (match_dup 0)) + (unspec:QI [(match_operand:QI 1 "register_operand" "u")] UNSPEC_ATOMIC)) + (clobber (match_scratch:QI 2 "=&u")) + (clobber (reg:SI R0_REG)) + (clobber (reg:SI R1_REG))] + "TARGET_SOFT_ATOMIC && !TARGET_ENABLE_TAS && !TARGET_SHMEDIA" +{ + return "mova 1f,r0" "\n" + " .align 2" "\n" + " mov r15,r1" "\n" + " mov #(0f-1f),r15" "\n" + "0: mov.b @%0,%2" "\n" + " mov.b %1,@%0" "\n" + "1: mov r1,r15" "\n" + " tst %2,%2"; +} + [(set_attr "length" "16")]) + diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 067dca8..8d69284 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -887,7 +887,8 @@ See RS/6000 and PowerPC Options. -mdivsi3_libfunc=@var{name} -mfixed-range=@var{register-range} @gol -madjust-unroll -mindexed-addressing -mgettrcost=@var{number} -mpt-fixed @gol -maccumulate-outgoing-args -minvalid-symbols -msoft-atomic @gol --mbranch-cost=@var{num} -mcbranchdi -mcmpeqdi -mfused-madd -mpretend-cmove} +-mbranch-cost=@var{num} -mcbranchdi -mcmpeqdi -mfused-madd -mpretend-cmove @gol +-menable-tas} @emph{Solaris 2 Options} @gccoptlist{-mimpure-text -mno-impure-text @gol @@ -17934,6 +17935,15 @@ single-core systems. They will not perform correctly on multi-core systems. This option is enabled by default when the target is @code{sh-*-linux*}. For details on the atomic built-in functions see @ref{__atomic Builtins}. +@item -menable-tas +@opindex menable-tas +Generate the @code{tas.b} opcode for @code{__atomic_test_and_set}. +Notice that depending on the particular hardware and software configuration +this can degrade overall performance due to the operand cache line flushes +that are implied by the @code{tas.b} instruction. On multi-core SH4A +processors the @code{tas.b} instruction must be used with caution since it +can result in data corruption for certain cache configurations. + @item -mspace @opindex mspace Optimize for space instead of speed. Implied by @option{-Os}. |