diff options
author | Richard Henderson <rth@redhat.com> | 2012-03-03 10:21:06 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2012-03-03 10:21:06 -0800 |
commit | a6de595f94a9a1956f19124195b0c852fd9fde73 (patch) | |
tree | 96b4628bf6a7a2b7e88c64b5788289627c0d35dd | |
parent | 6ecbd3a745b94e379458f0f67745379c969bc569 (diff) | |
download | gcc-a6de595f94a9a1956f19124195b0c852fd9fde73.zip gcc-a6de595f94a9a1956f19124195b0c852fd9fde73.tar.gz gcc-a6de595f94a9a1956f19124195b0c852fd9fde73.tar.bz2 |
optabs.c (expand_atomic_test_and_set): Honor atomic_test_and_set_trueval even when atomic_test_and_set optab is not in use.
* optabs.c (expand_atomic_test_and_set): Honor
atomic_test_and_set_trueval even when atomic_test_and_set
optab is not in use.
From-SVN: r184862
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/optabs.c | 61 |
2 files changed, 48 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e2c179d..a9edea9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2012-03-02 Richard Henderson <rth@redhat.com> + + * optabs.c (expand_atomic_test_and_set): Honor + atomic_test_and_set_trueval even when atomic_test_and_set + optab is not in use. + 2012-03-02 Kaz Kojima <kkojima@gcc.gnu.org> PR target/48596 diff --git a/gcc/optabs.c b/gcc/optabs.c index b0ecdf0..fd353d7 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -7384,34 +7384,57 @@ rtx expand_atomic_test_and_set (rtx target, rtx mem, enum memmodel model) { enum machine_mode mode = GET_MODE (mem); - rtx ret; + rtx ret, trueval, subtarget; ret = maybe_emit_atomic_test_and_set (target, mem, model); if (ret) return ret; - if (target == NULL_RTX) - target = gen_reg_rtx (mode); + /* Be binary compatible with non-default settings of trueval, and different + cpu revisions. E.g. one revision may have atomic-test-and-set, but + another only has atomic-exchange. */ + if (targetm.atomic_test_and_set_trueval == 1) + { + trueval = const1_rtx; + subtarget = target ? target : gen_reg_rtx (mode); + } + else + { + trueval = gen_int_mode (targetm.atomic_test_and_set_trueval, mode); + subtarget = gen_reg_rtx (mode); + } - /* If there is no test and set, try exchange, then a compare_and_swap loop, - then __sync_test_and_set. */ - ret = maybe_emit_atomic_exchange (target, mem, const1_rtx, model); - if (ret) - return ret; + /* Try the atomic-exchange optab... */ + ret = maybe_emit_atomic_exchange (subtarget, mem, trueval, model); - ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, const1_rtx); - if (ret) - return ret; + /* ... then an atomic-compare-and-swap loop ... */ + if (!ret) + ret = maybe_emit_compare_and_swap_exchange_loop (subtarget, mem, trueval); - ret = maybe_emit_sync_lock_test_and_set (target, mem, const1_rtx, model); - if (ret) - return ret; + /* ... before trying the vaguely defined legacy lock_test_and_set. */ + if (!ret) + ret = maybe_emit_sync_lock_test_and_set (subtarget, mem, trueval, model); - /* Failing all else, assume a single threaded environment and simply perform - the operation. */ - emit_move_insn (target, mem); - emit_move_insn (mem, const1_rtx); - return target; + /* Recall that the legacy lock_test_and_set optab was allowed to do magic + things with the value 1. Thus we try again without trueval. */ + if (!ret && targetm.atomic_test_and_set_trueval != 1) + ret = maybe_emit_sync_lock_test_and_set (subtarget, mem, const1_rtx, model); + + /* Failing all else, assume a single threaded environment and simply + perform the operation. */ + if (!ret) + { + emit_move_insn (subtarget, mem); + emit_move_insn (mem, trueval); + ret = subtarget; + } + + /* Recall that have to return a boolean value; rectify if trueval + is not exactly one. */ + if (targetm.atomic_test_and_set_trueval != 1) + ret = emit_store_flag_force (target, NE, ret, const0_rtx, mode, 0, 1); + + return ret; } /* This function expands the atomic exchange operation: |