Commit f12b785d by Richard Henderson Committed by Richard Henderson

builtins.c (expand_builtin_sync_operation): Revert last change.

        * builtins.c (expand_builtin_sync_operation): Revert last change.
        * optabs.c (expand_bool_compare_and_swap): Compare vs old value,
        not vs new value.
        (expand_compare_and_swap_loop): Likewise.
        (expand_sync_operation): Remove fallback from NAND to AND; invert
        memory operand when expanding from cmpxchg.
        (expand_sync_fetch_operation): Likewise.
        * doc/extend.texi (Atomic Builtins): Fix docs for nand and
        compare-and-swap.

        * config/alpha/alpha.c (alpha_split_atomic_op): Invert memory operand
        when implementing NAND.  Fix double-add for AFTER.
        * config/alpha/sync.md (sync_nand<I48MODE>): Invert memory operand.
        (sync_old_nand<I48MODE>, sync_new_nand<I48MODE>): Likewise.
        (sync_compare_and_swap<I48MODE>): Fix compare vs zero.  Return old
        memory value.
        (sync_lock_test_and_set<I48MODE>): Remove extra label and last
        memory barrier.

        * config/i386/sync.md (sync_compare_and_swap<IMODE>): Fix pattern
        to return old memory value.
        (sync_compare_and_swap_cc<IMODE>): Likewise.

        * config/ia64/ia64.c (ia64_dependencies_evaluation_hook): Early
        return pre-reload.  Don't consider output or anti dependencies.
        * config/ia64/sync.md (IMODE): New.
        (modesuffix): Add QI and HI.
        (memory_barrier): Simplify expansion.
        (sync_compare_and_swap<IMODE>): Use IMODE, not I48MODE.
        (cmpxchg_acq_<IMODE>): Likewise.
        (sync_lock_test_and_set<IMODE>): Likewise.
        (sync_lock_release<IMODE>): Likewise.

From-SVN: r98436
parent f242e769
2005-04-19 Richard Henderson <rth@redhat.com>
* builtins.c (expand_builtin_sync_operation): Revert last change.
* optabs.c (expand_bool_compare_and_swap): Compare vs old value,
not vs new value.
(expand_compare_and_swap_loop): Likewise.
(expand_sync_operation): Remove fallback from NAND to AND; invert
memory operand when expanding from cmpxchg.
(expand_sync_fetch_operation): Likewise.
* doc/extend.texi (Atomic Builtins): Fix docs for nand and
compare-and-swap.
* config/alpha/alpha.c (alpha_split_atomic_op): Invert memory operand
when implementing NAND. Fix double-add for AFTER.
* config/alpha/sync.md (sync_nand<I48MODE>): Invert memory operand.
(sync_old_nand<I48MODE>, sync_new_nand<I48MODE>): Likewise.
(sync_compare_and_swap<I48MODE>): Fix compare vs zero. Return old
memory value.
(sync_lock_test_and_set<I48MODE>): Remove extra label and last
memory barrier.
* config/i386/sync.md (sync_compare_and_swap<IMODE>): Fix pattern
to return old memory value.
(sync_compare_and_swap_cc<IMODE>): Likewise.
* config/ia64/ia64.c (ia64_dependencies_evaluation_hook): Early
return pre-reload. Don't consider output or anti dependencies.
* config/ia64/sync.md (IMODE): New.
(modesuffix): Add QI and HI.
(memory_barrier): Simplify expansion.
(sync_compare_and_swap<IMODE>): Use IMODE, not I48MODE.
(cmpxchg_acq_<IMODE>): Likewise.
(sync_lock_test_and_set<IMODE>): Likewise.
(sync_lock_release<IMODE>): Likewise.
2005-04-19 James A. Morrison <phython@gcc.gnu.org> 2005-04-19 James A. Morrison <phython@gcc.gnu.org>
* fold-const.c (fold_binary): Fold ~(X ^ Y) to ~X ^ Y or X ^ ~Y if * fold-const.c (fold_binary): Fold ~(X ^ Y) to ~X ^ Y or X ^ ~Y if
......
...@@ -5255,20 +5255,13 @@ expand_builtin_sync_operation (tree arglist, enum rtx_code code, bool after, ...@@ -5255,20 +5255,13 @@ expand_builtin_sync_operation (tree arglist, enum rtx_code code, bool after,
{ {
enum machine_mode mode; enum machine_mode mode;
rtx addr, val, mem; rtx addr, val, mem;
tree valt;
/* Expand the operands. */ /* Expand the operands. */
addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, EXPAND_SUM); addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, EXPAND_SUM);
mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_VALUE (arglist)))); mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_VALUE (arglist))));
arglist = TREE_CHAIN (arglist); arglist = TREE_CHAIN (arglist);
valt = TREE_VALUE (arglist); val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
if (code == NOT && TREE_CONSTANT (valt))
{
valt = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (valt), valt);
code = AND;
}
val = expand_expr (valt, NULL, mode, EXPAND_NORMAL);
/* Note that we explicitly do not want any alias information for this /* Note that we explicitly do not want any alias information for this
memory, so that we kill all other live memories. Otherwise we don't memory, so that we kill all other live memories. Otherwise we don't
......
...@@ -4502,15 +4502,15 @@ alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val, ...@@ -4502,15 +4502,15 @@ alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
if (code == NOT) if (code == NOT)
{ {
x = gen_rtx_NOT (mode, val); x = gen_rtx_NOT (mode, before);
x = gen_rtx_AND (mode, x, before); x = gen_rtx_AND (mode, x, val);
} }
else else
x = gen_rtx_fmt_ee (code, mode, before, val); x = gen_rtx_fmt_ee (code, mode, before, val);
emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
if (after) if (after)
emit_insn (gen_rtx_SET (VOIDmode, after, copy_rtx (x))); emit_insn (gen_rtx_SET (VOIDmode, after, copy_rtx (x)));
emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
cond = gen_rtx_REG (DImode, REGNO (scratch)); cond = gen_rtx_REG (DImode, REGNO (scratch));
if (mode == SImode) if (mode == SImode)
......
...@@ -94,10 +94,8 @@ ...@@ -94,10 +94,8 @@
(define_insn_and_split "sync_nand<mode>" (define_insn_and_split "sync_nand<mode>"
[(set (match_operand:I48MODE 0 "memory_operand" "+m") [(set (match_operand:I48MODE 0 "memory_operand" "+m")
(unspec_volatile:I48MODE (unspec_volatile:I48MODE
[(and:I48MODE [(and:I48MODE (not:I48MODE (match_dup 0))
(not:I48MODE (match_operand:I48MODE 1 "register_operand" "r"))]
(match_operand:I48MODE 1 "reg_or_8bit_operand" "rI"))
(match_dup 0))]
UNSPECV_ATOMIC)) UNSPECV_ATOMIC))
(clobber (match_scratch:I48MODE 2 "=&r"))] (clobber (match_scratch:I48MODE 2 "=&r"))]
"" ""
...@@ -136,10 +134,8 @@ ...@@ -136,10 +134,8 @@
(match_operand:I48MODE 1 "memory_operand" "+m")) (match_operand:I48MODE 1 "memory_operand" "+m"))
(set (match_dup 1) (set (match_dup 1)
(unspec_volatile:I48MODE (unspec_volatile:I48MODE
[(and:I48MODE [(and:I48MODE (not:I48MODE (match_dup 1))
(not:I48MODE (match_operand:I48MODE 2 "register_operand" "r"))]
(match_operand:I48MODE 2 "reg_or_8bit_operand" "rI"))
(match_dup 1))]
UNSPECV_ATOMIC)) UNSPECV_ATOMIC))
(clobber (match_scratch:I48MODE 3 "=&r"))] (clobber (match_scratch:I48MODE 3 "=&r"))]
"" ""
...@@ -177,12 +173,11 @@ ...@@ -177,12 +173,11 @@
(define_insn_and_split "sync_new_nand<mode>" (define_insn_and_split "sync_new_nand<mode>"
[(set (match_operand:I48MODE 0 "register_operand" "=&r") [(set (match_operand:I48MODE 0 "register_operand" "=&r")
(and:I48MODE (and:I48MODE
(not:I48MODE (not:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m"))
(match_operand:I48MODE 2 "reg_or_8bit_operand" "rI")) (match_operand:I48MODE 2 "reg_or_8bit_operand" "rI")))
(match_operand:I48MODE 1 "memory_operand" "+m")))
(set (match_dup 1) (set (match_dup 1)
(unspec_volatile:I48MODE (unspec_volatile:I48MODE
[(and:I48MODE (not:I48MODE (match_dup 2)) (match_dup 1))] [(and:I48MODE (not:I48MODE (match_dup 1)) (match_dup 2))]
UNSPECV_ATOMIC)) UNSPECV_ATOMIC))
(clobber (match_scratch:I48MODE 3 "=&r"))] (clobber (match_scratch:I48MODE 3 "=&r"))]
"" ""
...@@ -246,9 +241,11 @@ ...@@ -246,9 +241,11 @@
emit_insn (gen_load_locked_<mode> (retval, mem)); emit_insn (gen_load_locked_<mode> (retval, mem));
x = gen_lowpart (DImode, retval); x = gen_lowpart (DImode, retval);
x = gen_rtx_EQ (DImode, x, oldval); if (oldval == const0_rtx)
if (oldval != const0_rtx) x = gen_rtx_NE (DImode, x, const0_rtx);
else
{ {
x = gen_rtx_EQ (DImode, x, oldval);
emit_insn (gen_rtx_SET (VOIDmode, cond, x)); emit_insn (gen_rtx_SET (VOIDmode, cond, x));
x = gen_rtx_EQ (DImode, cond, const0_rtx); x = gen_rtx_EQ (DImode, cond, const0_rtx);
} }
...@@ -257,8 +254,7 @@ ...@@ -257,8 +254,7 @@
REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX); REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
emit_move_insn (scratch, newval); emit_move_insn (scratch, newval);
emit_move_insn (retval, newval);
emit_insn (gen_store_conditional_<mode> (cond, mem, scratch)); emit_insn (gen_store_conditional_<mode> (cond, mem, scratch));
x = gen_rtx_EQ (DImode, cond, const0_rtx); x = gen_rtx_EQ (DImode, cond, const0_rtx);
...@@ -266,8 +262,8 @@ ...@@ -266,8 +262,8 @@
x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x)); x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX); REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
emit_label (XEXP (label2, 0));
emit_insn (gen_memory_barrier ()); emit_insn (gen_memory_barrier ());
emit_label (XEXP (label2, 0));
DONE; DONE;
} }
[(set_attr "type" "multi")]) [(set_attr "type" "multi")])
...@@ -286,7 +282,7 @@ ...@@ -286,7 +282,7 @@
[(const_int 0)] [(const_int 0)]
{ {
rtx retval, mem, val, scratch; rtx retval, mem, val, scratch;
rtx cond, label1, label2, x; rtx cond, label1, x;
rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1); rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
retval = operands[0]; retval = operands[0];
...@@ -298,7 +294,6 @@ ...@@ -298,7 +294,6 @@
emit_insn (gen_memory_barrier ()); emit_insn (gen_memory_barrier ());
label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ()); label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
emit_label (XEXP (label1, 0)); emit_label (XEXP (label1, 0));
emit_insn (gen_load_locked_<mode> (retval, mem)); emit_insn (gen_load_locked_<mode> (retval, mem));
...@@ -312,8 +307,6 @@ ...@@ -312,8 +307,6 @@
x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x)); x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX); REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
emit_label (XEXP (label2, 0));
emit_insn (gen_memory_barrier ());
DONE; DONE;
} }
[(set_attr "type" "multi")]) [(set_attr "type" "multi")])
...@@ -32,14 +32,13 @@ ...@@ -32,14 +32,13 @@
(define_insn "sync_compare_and_swap<mode>" (define_insn "sync_compare_and_swap<mode>"
[(set (match_operand:IMODE 0 "register_operand" "=a") [(set (match_operand:IMODE 0 "register_operand" "=a")
(match_operand:IMODE 1 "memory_operand" "+m"))
(set (match_dup 1)
(unspec_volatile:IMODE (unspec_volatile:IMODE
[(match_operand:IMODE 1 "memory_operand" "+m") [(match_dup 1)
(match_operand:IMODE 2 "register_operand" "a") (match_operand:IMODE 2 "register_operand" "a")
(match_operand:IMODE 3 "register_operand" "<modeconstraint>")] (match_operand:IMODE 3 "register_operand" "<modeconstraint>")]
UNSPECV_CMPXCHG_1)) UNSPECV_CMPXCHG_1))
(set (match_dup 1)
(unspec_volatile:IMODE
[(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2))
(clobber (reg:CC FLAGS_REG))] (clobber (reg:CC FLAGS_REG))]
"TARGET_CMPXCHG" "TARGET_CMPXCHG"
"lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}") "lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}")
...@@ -47,19 +46,18 @@ ...@@ -47,19 +46,18 @@
(define_expand "sync_compare_and_swap_cc<mode>" (define_expand "sync_compare_and_swap_cc<mode>"
[(parallel [(parallel
[(set (match_operand:IMODE 0 "register_operand" "") [(set (match_operand:IMODE 0 "register_operand" "")
(match_operand:IMODE 1 "memory_operand" ""))
(set (match_dup 1)
(unspec_volatile:IMODE (unspec_volatile:IMODE
[(match_operand:IMODE 1 "memory_operand" "") [(match_dup 1)
(match_operand:IMODE 2 "register_operand" "") (match_operand:IMODE 2 "register_operand" "")
(match_operand:IMODE 3 "register_operand" "")] (match_operand:IMODE 3 "register_operand" "")]
UNSPECV_CMPXCHG_1)) UNSPECV_CMPXCHG_1))
(set (match_dup 1)
(unspec_volatile:IMODE
[(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2))
(set (match_dup 4) (set (match_dup 4)
(compare:CCZ (compare:CCZ
(unspec_volatile:IMODE (unspec_volatile:IMODE
[(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_1) [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2)
(match_dup 3)))])] (match_dup 2)))])]
"TARGET_CMPXCHG" "TARGET_CMPXCHG"
{ {
operands[4] = gen_rtx_REG (CCZmode, FLAGS_REG); operands[4] = gen_rtx_REG (CCZmode, FLAGS_REG);
...@@ -70,19 +68,18 @@ ...@@ -70,19 +68,18 @@
(define_insn "*sync_compare_and_swap_cc<mode>" (define_insn "*sync_compare_and_swap_cc<mode>"
[(set (match_operand:IMODE 0 "register_operand" "=a") [(set (match_operand:IMODE 0 "register_operand" "=a")
(match_operand:IMODE 1 "memory_operand" "+m"))
(set (match_dup 1)
(unspec_volatile:IMODE (unspec_volatile:IMODE
[(match_operand:IMODE 1 "memory_operand" "+m") [(match_dup 1)
(match_operand:IMODE 2 "register_operand" "a") (match_operand:IMODE 2 "register_operand" "a")
(match_operand:IMODE 3 "register_operand" "<modeconstraint>")] (match_operand:IMODE 3 "register_operand" "<modeconstraint>")]
UNSPECV_CMPXCHG_1)) UNSPECV_CMPXCHG_1))
(set (match_dup 1)
(unspec_volatile:IMODE
[(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2))
(set (reg:CCZ FLAGS_REG) (set (reg:CCZ FLAGS_REG)
(compare:CCZ (compare:CCZ
(unspec_volatile:IMODE (unspec_volatile:IMODE
[(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_1) [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2)
(match_dup 3)))] (match_dup 2)))]
"TARGET_CMPXCHG" "TARGET_CMPXCHG"
"lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}") "lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}")
......
...@@ -5814,6 +5814,12 @@ ia64_dependencies_evaluation_hook (rtx head, rtx tail) ...@@ -5814,6 +5814,12 @@ ia64_dependencies_evaluation_hook (rtx head, rtx tail)
{ {
rtx insn, link, next, next_tail; rtx insn, link, next, next_tail;
/* Before reload, which_alternative is not set, which means that
ia64_safe_itanium_class will produce wrong results for (at least)
move instructions. */
if (!reload_completed)
return;
next_tail = NEXT_INSN (tail); next_tail = NEXT_INSN (tail);
for (insn = head; insn != next_tail; insn = NEXT_INSN (insn)) for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
if (INSN_P (insn)) if (INSN_P (insn))
...@@ -5824,6 +5830,8 @@ ia64_dependencies_evaluation_hook (rtx head, rtx tail) ...@@ -5824,6 +5830,8 @@ ia64_dependencies_evaluation_hook (rtx head, rtx tail)
{ {
for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1)) for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1))
{ {
if (REG_NOTE_KIND (link) != REG_DEP_TRUE)
continue;
next = XEXP (link, 0); next = XEXP (link, 0);
if ((ia64_safe_itanium_class (next) == ITANIUM_CLASS_ST if ((ia64_safe_itanium_class (next) == ITANIUM_CLASS_ST
|| ia64_safe_itanium_class (next) == ITANIUM_CLASS_STF) || ia64_safe_itanium_class (next) == ITANIUM_CLASS_STF)
......
...@@ -19,22 +19,14 @@ ...@@ -19,22 +19,14 @@
;; the Free Software Foundation, 59 Temple Place - Suite 330, ;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA. ;; Boston, MA 02111-1307, USA.
(define_mode_macro IMODE [QI HI SI DI])
(define_mode_macro I48MODE [SI DI]) (define_mode_macro I48MODE [SI DI])
(define_mode_attr modesuffix [(SI "4") (DI "8")]) (define_mode_attr modesuffix [(QI "1") (HI "2") (SI "4") (DI "8")])
(define_expand "memory_barrier" (define_insn "memory_barrier"
[(set (mem:BLK (match_dup 0)) [(set (mem:BLK (match_scratch:DI 0 "X"))
(unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_MF))] (unspec:BLK [(mem:BLK (match_scratch:DI 1 "X"))] UNSPEC_MF))]
""
{
operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
MEM_VOLATILE_P (operands[0]) = 1;
})
(define_insn "*mf_internal"
[(set (match_operand:BLK 0 "" "")
(unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_MF))]
"" ""
"mf" "mf"
[(set_attr "itanium_class" "syst_m")]) [(set_attr "itanium_class" "syst_m")])
...@@ -77,10 +69,10 @@ ...@@ -77,10 +69,10 @@
[(set_attr "itanium_class" "sem")]) [(set_attr "itanium_class" "sem")])
(define_expand "sync_compare_and_swap<mode>" (define_expand "sync_compare_and_swap<mode>"
[(match_operand:I48MODE 0 "gr_register_operand" "") [(match_operand:IMODE 0 "gr_register_operand" "")
(match_operand:I48MODE 1 "memory_operand" "") (match_operand:IMODE 1 "memory_operand" "")
(match_operand:I48MODE 2 "gr_register_operand" "") (match_operand:IMODE 2 "gr_register_operand" "")
(match_operand:I48MODE 3 "gr_register_operand" "")] (match_operand:IMODE 3 "gr_register_operand" "")]
"" ""
{ {
rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM); rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
...@@ -92,29 +84,29 @@ ...@@ -92,29 +84,29 @@
}) })
(define_insn "cmpxchg_acq_<mode>" (define_insn "cmpxchg_acq_<mode>"
[(set (match_operand:I48MODE 0 "gr_register_operand" "=r") [(set (match_operand:IMODE 0 "gr_register_operand" "=r")
(match_operand:I48MODE 1 "not_postinc_memory_operand" "+S")) (match_operand:IMODE 1 "not_postinc_memory_operand" "+S"))
(set (match_dup 1) (set (match_dup 1)
(unspec:I48MODE [(match_dup 1) (unspec:IMODE [(match_dup 1)
(match_operand:DI 2 "ar_ccv_reg_operand" "") (match_operand:DI 2 "ar_ccv_reg_operand" "")
(match_operand:I48MODE 3 "gr_register_operand" "r")] (match_operand:IMODE 3 "gr_register_operand" "r")]
UNSPEC_CMPXCHG_ACQ))] UNSPEC_CMPXCHG_ACQ))]
"" ""
"cmpxchg<modesuffix>.acq %0 = %1, %3, %2" "cmpxchg<modesuffix>.acq %0 = %1, %3, %2"
[(set_attr "itanium_class" "sem")]) [(set_attr "itanium_class" "sem")])
(define_insn "sync_lock_test_and_set<mode>" (define_insn "sync_lock_test_and_set<mode>"
[(set (match_operand:I48MODE 0 "gr_register_operand" "=r") [(set (match_operand:IMODE 0 "gr_register_operand" "=r")
(match_operand:I48MODE 1 "not_postinc_memory_operand" "+S")) (match_operand:IMODE 1 "not_postinc_memory_operand" "+S"))
(set (match_dup 1) (set (match_dup 1)
(match_operand:I48MODE 2 "gr_register_operand" "r"))] (match_operand:IMODE 2 "gr_register_operand" "r"))]
"" ""
"xchg<modesuffix> %0 = %1, %2" "xchg<modesuffix> %0 = %1, %2"
[(set_attr "itanium_class" "sem")]) [(set_attr "itanium_class" "sem")])
(define_expand "sync_lock_release<mode>" (define_expand "sync_lock_release<mode>"
[(set (match_operand:I48MODE 0 "memory_operand" "") [(set (match_operand:IMODE 0 "memory_operand" "")
(match_operand:I48MODE 1 "gr_reg_or_0_operand" ""))] (match_operand:IMODE 1 "gr_reg_or_0_operand" ""))]
"" ""
{ {
gcc_assert (MEM_VOLATILE_P (operands[0])); gcc_assert (MEM_VOLATILE_P (operands[0]));
......
...@@ -4639,11 +4639,9 @@ returns the value that had previously been in memory. That is, ...@@ -4639,11 +4639,9 @@ returns the value that had previously been in memory. That is,
@smallexample @smallexample
@{ tmp = *ptr; *ptr @var{op}= value; return tmp; @} @{ tmp = *ptr; *ptr @var{op}= value; return tmp; @}
@{ tmp = *ptr; *ptr = ~tmp & value; return tmp; @} // nand
@end smallexample @end smallexample
The builtin @code{__sync_fetch_and_nand} could be implemented by
@code{__sync_fetch_and_and(ptr, ~value)}.
@item @var{type} __sync_add_and_fetch (@var{type} *ptr, @var{type} value, ...) @item @var{type} __sync_add_and_fetch (@var{type} *ptr, @var{type} value, ...)
@itemx @var{type} __sync_sub_and_fetch (@var{type} *ptr, @var{type} value, ...) @itemx @var{type} __sync_sub_and_fetch (@var{type} *ptr, @var{type} value, ...)
@itemx @var{type} __sync_or_and_fetch (@var{type} *ptr, @var{type} value, ...) @itemx @var{type} __sync_or_and_fetch (@var{type} *ptr, @var{type} value, ...)
...@@ -4661,6 +4659,7 @@ return the new value. That is, ...@@ -4661,6 +4659,7 @@ return the new value. That is,
@smallexample @smallexample
@{ *ptr @var{op}= value; return *ptr; @} @{ *ptr @var{op}= value; return *ptr; @}
@{ *ptr = ~*ptr & value; return *ptr; @} // nand
@end smallexample @end smallexample
@item bool __sync_bool_compare_and_swap (@var{type} *ptr, @var{type} oldval @var{type} newval, ...) @item bool __sync_bool_compare_and_swap (@var{type} *ptr, @var{type} oldval @var{type} newval, ...)
...@@ -4673,7 +4672,7 @@ value of @code{*@var{ptr}} is @var{oldval}, then write @var{newval} into ...@@ -4673,7 +4672,7 @@ value of @code{*@var{ptr}} is @var{oldval}, then write @var{newval} into
The ``bool'' version returns true if the comparison is successful and The ``bool'' version returns true if the comparison is successful and
@var{newval} was written. The ``val'' version returns the contents @var{newval} was written. The ``val'' version returns the contents
of @code{*@var{ptr}} after the operation. of @code{*@var{ptr}} before the operation.
@item __sync_synchronize (...) @item __sync_synchronize (...)
@findex __sync_synchronize @findex __sync_synchronize
......
...@@ -5588,12 +5588,17 @@ expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target) ...@@ -5588,12 +5588,17 @@ expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
if (icode == CODE_FOR_nothing) if (icode == CODE_FOR_nothing)
return NULL_RTX; return NULL_RTX;
/* Ensure that if old_val == mem, that we're not comparing
against an old value. */
if (GET_CODE (old_val) == MEM)
old_val = force_reg (mode, old_val);
subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val, subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val,
NULL_RTX, icode); NULL_RTX, icode);
if (subtarget == NULL_RTX) if (subtarget == NULL_RTX)
return NULL_RTX; return NULL_RTX;
emit_cmp_insn (subtarget, new_val, EQ, const0_rtx, mode, true); emit_cmp_insn (subtarget, old_val, EQ, const0_rtx, mode, true);
} }
/* If the target has a sane STORE_FLAG_VALUE, then go ahead and use a /* If the target has a sane STORE_FLAG_VALUE, then go ahead and use a
...@@ -5700,7 +5705,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq) ...@@ -5700,7 +5705,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
if (subtarget == NULL_RTX) if (subtarget == NULL_RTX)
return false; return false;
emit_cmp_insn (subtarget, new_reg, EQ, const0_rtx, mode, true); emit_cmp_insn (subtarget, old_reg, EQ, const0_rtx, mode, true);
} }
/* ??? Mark this jump predicted not taken? */ /* ??? Mark this jump predicted not taken? */
...@@ -5735,6 +5740,9 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code) ...@@ -5735,6 +5740,9 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
case AND: case AND:
icode = sync_and_optab[mode]; icode = sync_and_optab[mode];
break; break;
case NOT:
icode = sync_nand_optab[mode];
break;
case MINUS: case MINUS:
icode = sync_sub_optab[mode]; icode = sync_sub_optab[mode];
...@@ -5749,19 +5757,6 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code) ...@@ -5749,19 +5757,6 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
} }
break; break;
case NOT:
icode = sync_nand_optab[mode];
if (icode == CODE_FOR_nothing)
{
icode = sync_and_optab[mode];
if (icode != CODE_FOR_nothing)
{
val = expand_simple_unop (mode, NOT, val, NULL_RTX, 1);
code = AND;
}
}
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -5790,12 +5785,13 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code) ...@@ -5790,12 +5785,13 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
start_sequence (); start_sequence ();
t1 = t0;
if (code == NOT) if (code == NOT)
{ {
val = expand_simple_unop (mode, NOT, val, NULL_RTX, true); t1 = expand_simple_unop (mode, NOT, t1, NULL_RTX, true);
code = AND; code = AND;
} }
t1 = expand_simple_binop (mode, code, t0, val, NULL_RTX, t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
true, OPTAB_LIB_WIDEN); true, OPTAB_LIB_WIDEN);
insn = get_insns (); insn = get_insns ();
...@@ -5842,6 +5838,10 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code, ...@@ -5842,6 +5838,10 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
old_code = sync_old_and_optab[mode]; old_code = sync_old_and_optab[mode];
new_code = sync_new_and_optab[mode]; new_code = sync_new_and_optab[mode];
break; break;
case NOT:
old_code = sync_old_nand_optab[mode];
new_code = sync_new_nand_optab[mode];
break;
case MINUS: case MINUS:
old_code = sync_old_sub_optab[mode]; old_code = sync_old_sub_optab[mode];
...@@ -5858,21 +5858,6 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code, ...@@ -5858,21 +5858,6 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
} }
break; break;
case NOT:
old_code = sync_old_nand_optab[mode];
new_code = sync_new_nand_optab[mode];
if (old_code == CODE_FOR_nothing && new_code == CODE_FOR_nothing)
{
old_code = sync_old_sub_optab[mode];
new_code = sync_new_sub_optab[mode];
if (old_code != CODE_FOR_nothing || new_code != CODE_FOR_nothing)
{
val = expand_simple_unop (mode, NOT, val, NULL_RTX, 1);
code = AND;
}
}
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -5933,6 +5918,9 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code, ...@@ -5933,6 +5918,9 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
else if (code == MINUS) else if (code == MINUS)
code = PLUS; code = PLUS;
} }
if (code == NOT)
target = expand_simple_unop (mode, NOT, target, NULL_RTX, true);
target = expand_simple_binop (mode, code, target, val, NULL_RTX, target = expand_simple_binop (mode, code, target, val, NULL_RTX,
true, OPTAB_LIB_WIDEN); true, OPTAB_LIB_WIDEN);
} }
...@@ -5952,14 +5940,15 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code, ...@@ -5952,14 +5940,15 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
start_sequence (); start_sequence ();
if (!after)
emit_move_insn (target, t0);
t1 = t0;
if (code == NOT) if (code == NOT)
{ {
val = expand_simple_unop (mode, NOT, val, NULL_RTX, true); t1 = expand_simple_unop (mode, NOT, t1, NULL_RTX, true);
code = AND; code = AND;
} }
if (!after) t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
emit_move_insn (target, t0);
t1 = expand_simple_binop (mode, code, t0, val, NULL_RTX,
true, OPTAB_LIB_WIDEN); true, OPTAB_LIB_WIDEN);
if (after) if (after)
emit_move_insn (target, t1); emit_move_insn (target, t1);
......
2005-04-19 Richard Henderson <rth@redhat.com>
* lib/target-supports.exp (check_effective_target_vect_int_mult):
Fix typo in exists check.
(check_effective_target_sync_int_long): New.
* gcc.dg/ia64-sync-1.c: Enable for all effective-target sync_int_long.
* gcc.dg/ia64-sync-2.c: Likewise.
* gcc.dg/ia64-sync-3.c: Likewise.
* gcc.dg/ia64-sync-4.c: Likewise.
2005-04-19 James A. Morrison <phython@gcc.gnu.org> 2005-04-19 James A. Morrison <phython@gcc.gnu.org>
* gcc.dg/fold-xor-1.c: New test. * gcc.dg/fold-xor-1.c: New test.
......
/* { dg-do run { target ia64-*-* } } */ /* { dg-do run } */
/* { dg-require-effective-target sync_int_long } */
/* { dg-options } */ /* { dg-options } */
/* { dg-options "-march=i486" { target i?86-*-* } } */
/* { dg-options "-march=i486" { target { x86_64-*-* && ilp32 } } } */
/* Test basic functionality of the intrinsics. The operations should /* Test basic functionality of the intrinsics. The operations should
not be optimized away if no one checks the return values. */ not be optimized away if no one checks the return values. */
#include <ia64intrin.h>
extern void abort (void); extern void abort (void);
extern void *memcpy (void *, const void *, __SIZE_TYPE__); extern void *memcpy (void *, const void *, __SIZE_TYPE__);
......
/* { dg-do run { target ia64-*-* } } */ /* { dg-do run } */
/* { dg-require-effective-target sync_int_long } */
/* { dg-options } */ /* { dg-options } */
/* { dg-options "-march=i486" { target i?86-*-* } } */
/* { dg-options "-march=i486" { target { x86_64-*-* && ilp32 } } } */
/* Test basic functionality of the intrinsics. */ /* Test basic functionality of the intrinsics. */
#include <ia64intrin.h>
extern void abort (void); extern void abort (void);
extern void *memcpy (void *, const void *, __SIZE_TYPE__); extern void *memcpy (void *, const void *, __SIZE_TYPE__);
......
/* { dg-do run { target ia64-*-* } } */ /* { dg-do run } */
/* { dg-require-effective-target sync_int_long } */
/* { dg-options } */ /* { dg-options } */
/* { dg-options "-march=i486" { target i?86-*-* } } */
/* { dg-options "-march=i486" { target { x86_64-*-* && ilp32 } } } */
/* Test basic functionality of the intrinsics. */ /* Test basic functionality of the intrinsics. */
#include <ia64intrin.h>
extern void abort (void); extern void abort (void);
extern void *memcpy (void *, const void *, __SIZE_TYPE__); extern void *memcpy (void *, const void *, __SIZE_TYPE__);
......
/* { dg-do compile { target ia64-*-* } } */ /* { dg-do compile } */
/* { dg-require-effective-target sync_int_long } */
/* { dg-options "-O2 -finline-functions" } */ /* { dg-options "-O2 -finline-functions" } */
/* { dg-options "-march=i486" { target i?86-*-* } } */
/* { dg-options "-march=i486" { target { x86_64-*-* && ilp32 } } } */
/* Test inlining __sync_bool_compare_and_swap_di. */ /* Test inlining __sync_bool_compare_and_swap. */
#include <stdbool.h> #include <stdbool.h>
#include <ia64intrin.h>
static bool static bool
compare_and_swap(long *addr, long old, long new_val) compare_and_swap(long *addr, long old, long new_val)
{ {
return __sync_bool_compare_and_swap_di(addr, old, new_val); return __sync_bool_compare_and_swap(addr, old, new_val);
} }
void void
......
...@@ -861,7 +861,7 @@ proc check_effective_target_vect_condition { } { ...@@ -861,7 +861,7 @@ proc check_effective_target_vect_condition { } {
proc check_effective_target_vect_int_mult { } { proc check_effective_target_vect_int_mult { } {
global et_vect_int_mult_saved global et_vect_int_mult_saved
if [info exists et_vect_int_mult] { if [info exists et_vect_int_mult_saved] {
verbose "check_effective_target_vect_int_mult: using cached result" 2 verbose "check_effective_target_vect_int_mult: using cached result" 2
} else { } else {
set et_vect_int_mult_saved 0 set et_vect_int_mult_saved 0
...@@ -874,6 +874,27 @@ proc check_effective_target_vect_int_mult { } { ...@@ -874,6 +874,27 @@ proc check_effective_target_vect_int_mult { } {
return $et_vect_int_mult_saved return $et_vect_int_mult_saved
} }
# Return 1 if the target supports atomic operations on "int" and "long".
proc check_effective_target_sync_int_long { } {
global et_sync_int_long_saved
if [info exists et_sync_int_long_saved] {
verbose "check_effective_target_sync_int_long: using cached result" 2
} else {
set et_sync_int_long_saved 0
if { [istarget ia64-*-*]
|| [istarget i?86-*-*]
|| [istarget x86_64-*-*]
|| [istarget alpha*-*-*] } {
set et_sync_int_long_saved 1
}
}
verbose "check_effective_target_sync_int_long: returning $et_sync_int_long_saved" 2
return $et_sync_int_long_saved
}
# Return 1 if the target matches the effective target 'arg', 0 otherwise. # Return 1 if the target matches the effective target 'arg', 0 otherwise.
# This can be used with any check_* proc that takes no argument and # This can be used with any check_* proc that takes no argument and
# returns only 1 or 0. It could be used with check_* procs that take # returns only 1 or 0. It could be used with check_* procs that take
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment