diff options
author | Richard Henderson <rth@redhat.com> | 2005-04-19 21:54:11 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2005-04-19 21:54:11 -0700 |
commit | f12b785df384d2ffc150cd2f9b449aa4d8a54834 (patch) | |
tree | 4acdd6c4898d643fa0b840941a2d12315366ec66 /gcc | |
parent | f242e7690e6e838ec12e2d09fe1b5fc7929e20da (diff) | |
download | gcc-f12b785df384d2ffc150cd2f9b449aa4d8a54834.zip gcc-f12b785df384d2ffc150cd2f9b449aa4d8a54834.tar.gz gcc-f12b785df384d2ffc150cd2f9b449aa4d8a54834.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 35 | ||||
-rw-r--r-- | gcc/builtins.c | 9 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 6 | ||||
-rw-r--r-- | gcc/config/alpha/sync.md | 35 | ||||
-rw-r--r-- | gcc/config/i386/sync.md | 29 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.c | 8 | ||||
-rw-r--r-- | gcc/config/ia64/sync.md | 48 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 7 | ||||
-rw-r--r-- | gcc/optabs.c | 61 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ia64-sync-1.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ia64-sync-2.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ia64-sync-3.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ia64-sync-4.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/lib/target-supports.exp | 23 |
15 files changed, 172 insertions, 130 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f4737d7..bb9d66a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/builtins.c b/gcc/builtins.c index e907752..33102e0 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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 diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 895189b..69d67f9 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -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) diff --git a/gcc/config/alpha/sync.md b/gcc/config/alpha/sync.md index 755a3f3..937a17a 100644 --- a/gcc/config/alpha/sync.md +++ b/gcc/config/alpha/sync.md @@ -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")]) diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md index 477b398..99d100f 100644 --- a/gcc/config/i386/sync.md +++ b/gcc/config/i386/sync.md @@ -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}") diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 82dff03..2435922 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -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) diff --git a/gcc/config/ia64/sync.md b/gcc/config/ia64/sync.md index bca52b0..0ea8e96 100644 --- a/gcc/config/ia64/sync.md +++ b/gcc/config/ia64/sync.md @@ -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])); diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 5fc85a4..acd75e4 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -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 diff --git a/gcc/optabs.c b/gcc/optabs.c index 90a42c2..e1b9e3d 100644 --- a/gcc/optabs.c +++ b/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 (!after) + emit_move_insn (target, t0); + 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; } - if (!after) - emit_move_insn (target, t0); - t1 = expand_simple_binop (mode, code, t0, val, NULL_RTX, + t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX, true, OPTAB_LIB_WIDEN); if (after) emit_move_insn (target, t1); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c7d9f2e..f256d75 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/gcc.dg/ia64-sync-1.c b/gcc/testsuite/gcc.dg/ia64-sync-1.c index c33bf3b..f58f8cb 100644 --- a/gcc/testsuite/gcc.dg/ia64-sync-1.c +++ b/gcc/testsuite/gcc.dg/ia64-sync-1.c @@ -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__); diff --git a/gcc/testsuite/gcc.dg/ia64-sync-2.c b/gcc/testsuite/gcc.dg/ia64-sync-2.c index e7dd65f..000a267 100644 --- a/gcc/testsuite/gcc.dg/ia64-sync-2.c +++ b/gcc/testsuite/gcc.dg/ia64-sync-2.c @@ -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__); diff --git a/gcc/testsuite/gcc.dg/ia64-sync-3.c b/gcc/testsuite/gcc.dg/ia64-sync-3.c index c2772f7..46f6294 100644 --- a/gcc/testsuite/gcc.dg/ia64-sync-3.c +++ b/gcc/testsuite/gcc.dg/ia64-sync-3.c @@ -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__); diff --git a/gcc/testsuite/gcc.dg/ia64-sync-4.c b/gcc/testsuite/gcc.dg/ia64-sync-4.c index 98dfdac..baeb852 100644 --- a/gcc/testsuite/gcc.dg/ia64-sync-4.c +++ b/gcc/testsuite/gcc.dg/ia64-sync-4.c @@ -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 diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 18d0e9d..ab9953f 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -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 |