aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2005-04-19 21:54:11 -0700
committerRichard Henderson <rth@gcc.gnu.org>2005-04-19 21:54:11 -0700
commitf12b785df384d2ffc150cd2f9b449aa4d8a54834 (patch)
tree4acdd6c4898d643fa0b840941a2d12315366ec66 /gcc
parentf242e7690e6e838ec12e2d09fe1b5fc7929e20da (diff)
downloadgcc-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/ChangeLog35
-rw-r--r--gcc/builtins.c9
-rw-r--r--gcc/config/alpha/alpha.c6
-rw-r--r--gcc/config/alpha/sync.md35
-rw-r--r--gcc/config/i386/sync.md29
-rw-r--r--gcc/config/ia64/ia64.c8
-rw-r--r--gcc/config/ia64/sync.md48
-rw-r--r--gcc/doc/extend.texi7
-rw-r--r--gcc/optabs.c61
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.dg/ia64-sync-1.c7
-rw-r--r--gcc/testsuite/gcc.dg/ia64-sync-2.c7
-rw-r--r--gcc/testsuite/gcc.dg/ia64-sync-3.c7
-rw-r--r--gcc/testsuite/gcc.dg/ia64-sync-4.c10
-rw-r--r--gcc/testsuite/lib/target-supports.exp23
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