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
This commit is contained in:
parent
f242e7690e
commit
f12b785df3
15 changed files with 174 additions and 132 deletions
|
@ -1,3 +1,38 @@
|
|||
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>
|
||||
|
||||
* 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,
|
|||
{
|
||||
enum machine_mode mode;
|
||||
rtx addr, val, mem;
|
||||
tree valt;
|
||||
|
||||
/* Expand the operands. */
|
||||
addr = expand_expr (TREE_VALUE (arglist), NULL, Pmode, EXPAND_SUM);
|
||||
mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_VALUE (arglist))));
|
||||
|
||||
arglist = TREE_CHAIN (arglist);
|
||||
valt = TREE_VALUE (arglist);
|
||||
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);
|
||||
val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -4502,15 +4502,15 @@ alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
|
|||
|
||||
if (code == NOT)
|
||||
{
|
||||
x = gen_rtx_NOT (mode, val);
|
||||
x = gen_rtx_AND (mode, x, before);
|
||||
x = gen_rtx_NOT (mode, before);
|
||||
x = gen_rtx_AND (mode, x, val);
|
||||
}
|
||||
else
|
||||
x = gen_rtx_fmt_ee (code, mode, before, val);
|
||||
|
||||
emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
|
||||
if (after)
|
||||
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));
|
||||
if (mode == SImode)
|
||||
|
|
|
@ -94,10 +94,8 @@
|
|||
(define_insn_and_split "sync_nand<mode>"
|
||||
[(set (match_operand:I48MODE 0 "memory_operand" "+m")
|
||||
(unspec_volatile:I48MODE
|
||||
[(and:I48MODE
|
||||
(not:I48MODE
|
||||
(match_operand:I48MODE 1 "reg_or_8bit_operand" "rI"))
|
||||
(match_dup 0))]
|
||||
[(and:I48MODE (not:I48MODE (match_dup 0))
|
||||
(match_operand:I48MODE 1 "register_operand" "r"))]
|
||||
UNSPECV_ATOMIC))
|
||||
(clobber (match_scratch:I48MODE 2 "=&r"))]
|
||||
""
|
||||
|
@ -136,10 +134,8 @@
|
|||
(match_operand:I48MODE 1 "memory_operand" "+m"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:I48MODE
|
||||
[(and:I48MODE
|
||||
(not:I48MODE
|
||||
(match_operand:I48MODE 2 "reg_or_8bit_operand" "rI"))
|
||||
(match_dup 1))]
|
||||
[(and:I48MODE (not:I48MODE (match_dup 1))
|
||||
(match_operand:I48MODE 2 "register_operand" "r"))]
|
||||
UNSPECV_ATOMIC))
|
||||
(clobber (match_scratch:I48MODE 3 "=&r"))]
|
||||
""
|
||||
|
@ -177,12 +173,11 @@
|
|||
(define_insn_and_split "sync_new_nand<mode>"
|
||||
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
||||
(and:I48MODE
|
||||
(not:I48MODE
|
||||
(match_operand:I48MODE 2 "reg_or_8bit_operand" "rI"))
|
||||
(match_operand:I48MODE 1 "memory_operand" "+m")))
|
||||
(not:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m"))
|
||||
(match_operand:I48MODE 2 "reg_or_8bit_operand" "rI")))
|
||||
(set (match_dup 1)
|
||||
(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))
|
||||
(clobber (match_scratch:I48MODE 3 "=&r"))]
|
||||
""
|
||||
|
@ -246,9 +241,11 @@
|
|||
emit_insn (gen_load_locked_<mode> (retval, mem));
|
||||
|
||||
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));
|
||||
x = gen_rtx_EQ (DImode, cond, const0_rtx);
|
||||
}
|
||||
|
@ -257,8 +254,7 @@
|
|||
REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
|
||||
|
||||
emit_move_insn (scratch, newval);
|
||||
emit_move_insn (retval, newval);
|
||||
|
||||
|
||||
emit_insn (gen_store_conditional_<mode> (cond, mem, scratch));
|
||||
|
||||
x = gen_rtx_EQ (DImode, cond, const0_rtx);
|
||||
|
@ -266,8 +262,8 @@
|
|||
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);
|
||||
|
||||
emit_label (XEXP (label2, 0));
|
||||
emit_insn (gen_memory_barrier ());
|
||||
emit_label (XEXP (label2, 0));
|
||||
DONE;
|
||||
}
|
||||
[(set_attr "type" "multi")])
|
||||
|
@ -286,7 +282,7 @@
|
|||
[(const_int 0)]
|
||||
{
|
||||
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);
|
||||
|
||||
retval = operands[0];
|
||||
|
@ -298,7 +294,6 @@
|
|||
emit_insn (gen_memory_barrier ());
|
||||
|
||||
label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
|
||||
label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
|
||||
emit_label (XEXP (label1, 0));
|
||||
|
||||
emit_insn (gen_load_locked_<mode> (retval, mem));
|
||||
|
@ -312,8 +307,6 @@
|
|||
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);
|
||||
|
||||
emit_label (XEXP (label2, 0));
|
||||
emit_insn (gen_memory_barrier ());
|
||||
DONE;
|
||||
}
|
||||
[(set_attr "type" "multi")])
|
||||
|
|
|
@ -32,14 +32,13 @@
|
|||
|
||||
(define_insn "sync_compare_and_swap<mode>"
|
||||
[(set (match_operand:IMODE 0 "register_operand" "=a")
|
||||
(match_operand:IMODE 1 "memory_operand" "+m"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:IMODE
|
||||
[(match_operand:IMODE 1 "memory_operand" "+m")
|
||||
[(match_dup 1)
|
||||
(match_operand:IMODE 2 "register_operand" "a")
|
||||
(match_operand:IMODE 3 "register_operand" "<modeconstraint>")]
|
||||
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))]
|
||||
"TARGET_CMPXCHG"
|
||||
"lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}")
|
||||
|
@ -47,19 +46,18 @@
|
|||
(define_expand "sync_compare_and_swap_cc<mode>"
|
||||
[(parallel
|
||||
[(set (match_operand:IMODE 0 "register_operand" "")
|
||||
(match_operand:IMODE 1 "memory_operand" ""))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:IMODE
|
||||
[(match_operand:IMODE 1 "memory_operand" "")
|
||||
[(match_dup 1)
|
||||
(match_operand:IMODE 2 "register_operand" "")
|
||||
(match_operand:IMODE 3 "register_operand" "")]
|
||||
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)
|
||||
(compare:CCZ
|
||||
(unspec_volatile:IMODE
|
||||
[(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_1)
|
||||
(match_dup 3)))])]
|
||||
[(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2)
|
||||
(match_dup 2)))])]
|
||||
"TARGET_CMPXCHG"
|
||||
{
|
||||
operands[4] = gen_rtx_REG (CCZmode, FLAGS_REG);
|
||||
|
@ -70,19 +68,18 @@
|
|||
|
||||
(define_insn "*sync_compare_and_swap_cc<mode>"
|
||||
[(set (match_operand:IMODE 0 "register_operand" "=a")
|
||||
(match_operand:IMODE 1 "memory_operand" "+m"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:IMODE
|
||||
[(match_operand:IMODE 1 "memory_operand" "+m")
|
||||
[(match_dup 1)
|
||||
(match_operand:IMODE 2 "register_operand" "a")
|
||||
(match_operand:IMODE 3 "register_operand" "<modeconstraint>")]
|
||||
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)
|
||||
(compare:CCZ
|
||||
(unspec_volatile:IMODE
|
||||
[(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_1)
|
||||
(match_dup 3)))]
|
||||
[(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2)
|
||||
(match_dup 2)))]
|
||||
"TARGET_CMPXCHG"
|
||||
"lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}")
|
||||
|
||||
|
|
|
@ -5814,6 +5814,12 @@ ia64_dependencies_evaluation_hook (rtx head, rtx 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);
|
||||
for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
|
||||
if (INSN_P (insn))
|
||||
|
@ -5824,6 +5830,8 @@ ia64_dependencies_evaluation_hook (rtx head, rtx tail)
|
|||
{
|
||||
for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1))
|
||||
{
|
||||
if (REG_NOTE_KIND (link) != REG_DEP_TRUE)
|
||||
continue;
|
||||
next = XEXP (link, 0);
|
||||
if ((ia64_safe_itanium_class (next) == ITANIUM_CLASS_ST
|
||||
|| ia64_safe_itanium_class (next) == ITANIUM_CLASS_STF)
|
||||
|
|
|
@ -19,22 +19,14 @@
|
|||
;; the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
;; Boston, MA 02111-1307, USA.
|
||||
|
||||
(define_mode_macro IMODE [QI HI 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"
|
||||
[(set (mem:BLK (match_dup 0))
|
||||
(unspec:BLK [(mem:BLK (match_dup 0))] 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))]
|
||||
(define_insn "memory_barrier"
|
||||
[(set (mem:BLK (match_scratch:DI 0 "X"))
|
||||
(unspec:BLK [(mem:BLK (match_scratch:DI 1 "X"))] UNSPEC_MF))]
|
||||
""
|
||||
"mf"
|
||||
[(set_attr "itanium_class" "syst_m")])
|
||||
|
@ -77,10 +69,10 @@
|
|||
[(set_attr "itanium_class" "sem")])
|
||||
|
||||
(define_expand "sync_compare_and_swap<mode>"
|
||||
[(match_operand:I48MODE 0 "gr_register_operand" "")
|
||||
(match_operand:I48MODE 1 "memory_operand" "")
|
||||
(match_operand:I48MODE 2 "gr_register_operand" "")
|
||||
(match_operand:I48MODE 3 "gr_register_operand" "")]
|
||||
[(match_operand:IMODE 0 "gr_register_operand" "")
|
||||
(match_operand:IMODE 1 "memory_operand" "")
|
||||
(match_operand:IMODE 2 "gr_register_operand" "")
|
||||
(match_operand:IMODE 3 "gr_register_operand" "")]
|
||||
""
|
||||
{
|
||||
rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
|
||||
|
@ -92,29 +84,29 @@
|
|||
})
|
||||
|
||||
(define_insn "cmpxchg_acq_<mode>"
|
||||
[(set (match_operand:I48MODE 0 "gr_register_operand" "=r")
|
||||
(match_operand:I48MODE 1 "not_postinc_memory_operand" "+S"))
|
||||
[(set (match_operand:IMODE 0 "gr_register_operand" "=r")
|
||||
(match_operand:IMODE 1 "not_postinc_memory_operand" "+S"))
|
||||
(set (match_dup 1)
|
||||
(unspec:I48MODE [(match_dup 1)
|
||||
(match_operand:DI 2 "ar_ccv_reg_operand" "")
|
||||
(match_operand:I48MODE 3 "gr_register_operand" "r")]
|
||||
UNSPEC_CMPXCHG_ACQ))]
|
||||
(unspec:IMODE [(match_dup 1)
|
||||
(match_operand:DI 2 "ar_ccv_reg_operand" "")
|
||||
(match_operand:IMODE 3 "gr_register_operand" "r")]
|
||||
UNSPEC_CMPXCHG_ACQ))]
|
||||
""
|
||||
"cmpxchg<modesuffix>.acq %0 = %1, %3, %2"
|
||||
[(set_attr "itanium_class" "sem")])
|
||||
|
||||
(define_insn "sync_lock_test_and_set<mode>"
|
||||
[(set (match_operand:I48MODE 0 "gr_register_operand" "=r")
|
||||
(match_operand:I48MODE 1 "not_postinc_memory_operand" "+S"))
|
||||
[(set (match_operand:IMODE 0 "gr_register_operand" "=r")
|
||||
(match_operand:IMODE 1 "not_postinc_memory_operand" "+S"))
|
||||
(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"
|
||||
[(set_attr "itanium_class" "sem")])
|
||||
|
||||
(define_expand "sync_lock_release<mode>"
|
||||
[(set (match_operand:I48MODE 0 "memory_operand" "")
|
||||
(match_operand:I48MODE 1 "gr_reg_or_0_operand" ""))]
|
||||
[(set (match_operand:IMODE 0 "memory_operand" "")
|
||||
(match_operand:IMODE 1 "gr_reg_or_0_operand" ""))]
|
||||
""
|
||||
{
|
||||
gcc_assert (MEM_VOLATILE_P (operands[0]));
|
||||
|
|
|
@ -4639,11 +4639,9 @@ returns the value that had previously been in memory. That is,
|
|||
|
||||
@smallexample
|
||||
@{ tmp = *ptr; *ptr @var{op}= value; return tmp; @}
|
||||
@{ tmp = *ptr; *ptr = ~tmp & value; return tmp; @} // nand
|
||||
@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, ...)
|
||||
@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, ...)
|
||||
|
@ -4661,6 +4659,7 @@ return the new value. That is,
|
|||
|
||||
@smallexample
|
||||
@{ *ptr @var{op}= value; return *ptr; @}
|
||||
@{ *ptr = ~*ptr & value; return *ptr; @} // nand
|
||||
@end smallexample
|
||||
|
||||
@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
|
|||
|
||||
The ``bool'' version returns true if the comparison is successful and
|
||||
@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 (...)
|
||||
@findex __sync_synchronize
|
||||
|
|
65
gcc/optabs.c
65
gcc/optabs.c
|
@ -5588,12 +5588,17 @@ expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
|
|||
if (icode == CODE_FOR_nothing)
|
||||
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,
|
||||
NULL_RTX, icode);
|
||||
if (subtarget == 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
|
||||
|
@ -5700,7 +5705,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
|
|||
if (subtarget == NULL_RTX)
|
||||
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? */
|
||||
|
@ -5735,6 +5740,9 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
|
|||
case AND:
|
||||
icode = sync_and_optab[mode];
|
||||
break;
|
||||
case NOT:
|
||||
icode = sync_nand_optab[mode];
|
||||
break;
|
||||
|
||||
case MINUS:
|
||||
icode = sync_sub_optab[mode];
|
||||
|
@ -5749,19 +5757,6 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
|
|||
}
|
||||
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:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -5790,12 +5785,13 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
|
|||
|
||||
start_sequence ();
|
||||
|
||||
t1 = t0;
|
||||
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;
|
||||
}
|
||||
t1 = expand_simple_binop (mode, code, t0, val, NULL_RTX,
|
||||
t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
|
||||
true, OPTAB_LIB_WIDEN);
|
||||
|
||||
insn = get_insns ();
|
||||
|
@ -5842,6 +5838,10 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
|
|||
old_code = sync_old_and_optab[mode];
|
||||
new_code = sync_new_and_optab[mode];
|
||||
break;
|
||||
case NOT:
|
||||
old_code = sync_old_nand_optab[mode];
|
||||
new_code = sync_new_nand_optab[mode];
|
||||
break;
|
||||
|
||||
case MINUS:
|
||||
old_code = sync_old_sub_optab[mode];
|
||||
|
@ -5858,21 +5858,6 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
|
|||
}
|
||||
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:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -5933,6 +5918,9 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
|
|||
else if (code == MINUS)
|
||||
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,
|
||||
true, OPTAB_LIB_WIDEN);
|
||||
}
|
||||
|
@ -5952,14 +5940,15 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
|
|||
|
||||
start_sequence ();
|
||||
|
||||
if (code == NOT)
|
||||
{
|
||||
val = expand_simple_unop (mode, NOT, val, NULL_RTX, true);
|
||||
code = AND;
|
||||
}
|
||||
if (!after)
|
||||
emit_move_insn (target, t0);
|
||||
t1 = expand_simple_binop (mode, code, t0, val, NULL_RTX,
|
||||
t1 = t0;
|
||||
if (code == NOT)
|
||||
{
|
||||
t1 = expand_simple_unop (mode, NOT, t1, NULL_RTX, true);
|
||||
code = AND;
|
||||
}
|
||||
t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
|
||||
true, OPTAB_LIB_WIDEN);
|
||||
if (after)
|
||||
emit_move_insn (target, t1);
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
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>
|
||||
|
||||
* gcc.dg/fold-xor-1.c: New test.
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
/* { dg-do run { target ia64-*-* } } */
|
||||
/* { dg-do run } */
|
||||
/* { dg-require-effective-target sync_int_long } */
|
||||
/* { 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
|
||||
not be optimized away if no one checks the return values. */
|
||||
|
||||
#include <ia64intrin.h>
|
||||
|
||||
extern void abort (void);
|
||||
extern void *memcpy (void *, const void *, __SIZE_TYPE__);
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/* { dg-do run { target ia64-*-* } } */
|
||||
/* { dg-do run } */
|
||||
/* { dg-require-effective-target sync_int_long } */
|
||||
/* { dg-options } */
|
||||
/* { dg-options "-march=i486" { target i?86-*-* } } */
|
||||
/* { dg-options "-march=i486" { target { x86_64-*-* && ilp32 } } } */
|
||||
|
||||
/* Test basic functionality of the intrinsics. */
|
||||
|
||||
#include <ia64intrin.h>
|
||||
|
||||
extern void abort (void);
|
||||
extern void *memcpy (void *, const void *, __SIZE_TYPE__);
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/* { dg-do run { target ia64-*-* } } */
|
||||
/* { dg-do run } */
|
||||
/* { dg-require-effective-target sync_int_long } */
|
||||
/* { dg-options } */
|
||||
/* { dg-options "-march=i486" { target i?86-*-* } } */
|
||||
/* { dg-options "-march=i486" { target { x86_64-*-* && ilp32 } } } */
|
||||
|
||||
/* Test basic functionality of the intrinsics. */
|
||||
|
||||
#include <ia64intrin.h>
|
||||
|
||||
extern void abort (void);
|
||||
extern void *memcpy (void *, const void *, __SIZE_TYPE__);
|
||||
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
/* { dg-do compile { target ia64-*-* } } */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target sync_int_long } */
|
||||
/* { 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 <ia64intrin.h>
|
||||
|
||||
static bool
|
||||
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
|
||||
|
|
|
@ -861,7 +861,7 @@ proc check_effective_target_vect_condition { } {
|
|||
proc check_effective_target_vect_int_mult { } {
|
||||
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
|
||||
} else {
|
||||
set et_vect_int_mult_saved 0
|
||||
|
@ -874,6 +874,27 @@ proc check_effective_target_vect_int_mult { } {
|
|||
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.
|
||||
# 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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue