re PR middle-end/37908 (atomic NAND op generate wrong code; __sync_nand_and_fetch, __sync_fetch_and_nand)

PR middle-end/37908
	* optabs.c (expand_sync_operation): Properly handle NAND case
	by calculating ~(t1 & val) instead of (~t1 & val).
	* builtins.c (expand_builtin_sync_operation): Warn for changed
	semantics in NAND builtins.
	* c.opt (Wsync-nand): New warning option.  Describe -Wsync-nand.
	
	* doc/invoke.texi (Warning options): Add Wsync-nand.
	* doc/extend.texi (Atomic Builtins) [__sync_fetch_and_nand]: Correct
	__sync_fetch_and_nand builtin operation in the example.  Add a note
	about changed semantics in GCC 4.4.
	[__sync_nand_and_fetch]: Correct __sync_nand_and_fetch builtin
	operation in the example.  Add a note about changed semantics in
	GCC 4.4.

testsuite/ChangeLog:

	PR middle-end/37908
	* gcc.dg/pr37908.c: New test.
	* gcc.dg/ia64-sync-1.c: Correct __sync_fetch_and_nand and
	__sync_nand_and_fetch results.  Add dg-message to look for the warning
	about changed semantics of NAND builtin.
	(init_si, init_di): Change init value for __sync_fetch_and_nand to -1.
	(test_si, test_di): Change expected result of
	__sync_nand_and_fetch to ~7.
	* gcc.dg/ia64-sync-2.c: Correct __sync_fetch_and_nand and
	__sync_nand_and_fetch results.  Add dg-message to look for the warning
	about changed semantics of NAND builtin.
	(init_noret_si, init_noret_di): Change init value for
	__sync_fetch_and_nand to -1.
	(init_noret_si, init_noret_di): Change expected result of
	__sync_nand_and_fetch to ~7.
	* gcc.dg/sync-2.c: Correct __sync_fetch_and_nand and
	__sync_nand_and_fetch results.  Add dg-message to look for the warning
	about changed semantics of NAND builtin.
	(init_qi, init_qi): Change init value for __sync_fetch_and_nand to -1.
	(init_hi, init_hi): Change expected result of
	__sync_nand_and_fetch to ~7.
	* gcc.dg/sync-3.c: Copy from sync-2.c instead of including
	the c source file.
	* gcc.c-torture/compile/sync-1.c: Add dg-message to look for the
	warning about changed semantics of NAND builtin.
	* gcc.c-torture/compile/sync-2.c: Ditto.
	* gcc.c-torture/compile/sync-3.c: Ditto.

From-SVN: r141942
This commit is contained in:
Uros Bizjak 2008-11-17 12:19:06 +01:00
parent 73ce7fcb8c
commit 23462d4d8f
15 changed files with 299 additions and 54 deletions

View File

@ -1,3 +1,20 @@
2008-11-17 Uros Bizjak <ubizjak@gmail.com>
PR middle-end/37908
* optabs.c (expand_sync_operation): Properly handle NAND case
by calculating ~(t1 & val) instead of (~t1 & val).
* builtins.c (expand_builtin_sync_operation): Warn for changed
semantics in NAND builtins.
* c.opt (Wsync-nand): New warning option. Describe -Wsync-nand.
* doc/invoke.texi (Warning options): Add Wsync-nand.
* doc/extend.texi (Atomic Builtins) [__sync_fetch_and_nand]: Correct
__sync_fetch_and_nand builtin operation in the example. Add a note
about changed semantics in GCC 4.4.
[__sync_nand_and_fetch]: Correct __sync_nand_and_fetch builtin
operation in the example. Add a note about changed semantics in
GCC 4.4.
2008-11-16 Jan Hubicka <jh@suse.cz>
* cgraph.c (cgraph_function_body_availability): Fix test of externally
@ -165,10 +182,8 @@
* configure.ac (gcc_cv_libc_provides_ssp): Also consider GNU/Hurd
systems, which are assumend to always provide SSP-support in glibc.
* configure: Regenerate.
* configure.ac (gcc_cv_libc_provides_ssp): Also consider GNU/kFreeBSD,
GNU/kNetBSD systems in the `*-*-linux*' case.
Also consider GNU/kFreeBSD, GNU/kNetBSD systems in the `*-*-linux*'
case.
* configure: Regenerate.
2008-11-14 Jakub Jelinek <jakub@redhat.com>
@ -180,9 +195,9 @@
2008-11-13 Thomas Schwinge <tschwinge@gnu.org>
PR target/28102
* config.gcc (*-*-gnu*): Move Alpha parts into the `alpha*-*-gnu*', x86
parts into the `i[34567]86-*-linux*' and parts that are independent of
the processor architecture into the `*-*-linux*' cases.
* config.gcc (*-*-gnu*): Move Alpha parts into the `alpha*-*-gnu*',
x86 parts into the `i[34567]86-*-linux*' and parts that are
independent of the processor architecture into the `*-*-linux*' cases.
(*-*-linux*): Consider `linux.opt' only for Linux-based configurations.
* config/i386/gnu.h (GLIBC_DYNAMIC_LINKER): Redefine.
(TARGET_OS_CPP_BUILTINS, LINK_SPEC): Don't redefine.
@ -340,8 +355,8 @@
2008-11-11 Richard Sandiford <rdsandiford@googlemail.com>
PR rtl-optimization/37363
* simplify-rtx.c (simplify_plus_minus): Don't create (const (minus ...))
expresisons.
* simplify-rtx.c (simplify_plus_minus): Don't create
(const (minus ...)) expresisons.
2008-11-11 Eric Botcazou <ebotcazou@adacore.com>

View File

@ -5988,6 +5988,50 @@ expand_builtin_sync_operation (enum machine_mode mode, tree exp,
rtx val, mem;
enum machine_mode old_mode;
if (code == NOT && warn_sync_nand)
{
tree fndecl = get_callee_fndecl (exp);
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
static bool warned_f_a_n, warned_n_a_f;
switch (fcode)
{
case BUILT_IN_FETCH_AND_NAND_1:
case BUILT_IN_FETCH_AND_NAND_2:
case BUILT_IN_FETCH_AND_NAND_4:
case BUILT_IN_FETCH_AND_NAND_8:
case BUILT_IN_FETCH_AND_NAND_16:
if (warned_f_a_n)
break;
fndecl = implicit_built_in_decls[BUILT_IN_FETCH_AND_NAND_N];
inform (input_location,
"%qD changed semantics in GCC 4.4", fndecl);
warned_f_a_n = true;
break;
case BUILT_IN_NAND_AND_FETCH_1:
case BUILT_IN_NAND_AND_FETCH_2:
case BUILT_IN_NAND_AND_FETCH_4:
case BUILT_IN_NAND_AND_FETCH_8:
case BUILT_IN_NAND_AND_FETCH_16:
if (warned_n_a_f)
break;
fndecl = implicit_built_in_decls[BUILT_IN_NAND_AND_FETCH_N];
inform (input_location,
"%qD changed semantics in GCC 4.4", fndecl);
warned_n_a_f = true;
break;
default:
gcc_unreachable ();
}
}
/* Expand the operands. */
mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);

View File

@ -428,6 +428,10 @@ Wstrict-selector-match
ObjC ObjC++ Var(warn_strict_selector_match) Warning
Warn if type signatures of candidate methods do not match exactly
Wsync-nand
C C++ Var(warn_sync_nand) Init(1) Warning
Warn when __sync_fetch_and_nand and __sync_nand_and_fetch built-in functions are used
Wsynth
C++ ObjC++ Var(warn_synth) Warning
Deprecated. This switch has no effect

View File

@ -5774,9 +5774,12 @@ 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
@{ tmp = *ptr; *ptr = ~(tmp & value); return tmp; @} // nand
@end smallexample
@emph{Note:} GCC 4.4 and later implement @code{__sync_fetch_and_nand}
builtin as @code{*ptr = ~(tmp & value)} instead of @code{*ptr = ~tmp & 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, ...)
@ -5794,9 +5797,13 @@ return the new value. That is,
@smallexample
@{ *ptr @var{op}= value; return *ptr; @}
@{ *ptr = ~*ptr & value; return *ptr; @} // nand
@{ *ptr = ~(*ptr & value); return *ptr; @} // nand
@end smallexample
@emph{Note:} GCC 4.4 and later implement @code{__sync_nand_and_fetch}
builtin as @code{*ptr = ~(*ptr & value)} instead of
@code{*ptr = ~*ptr & value}.
@item bool __sync_bool_compare_and_swap (@var{type} *ptr, @var{type} oldval @var{type} newval, ...)
@itemx @var{type} __sync_val_compare_and_swap (@var{type} *ptr, @var{type} oldval @var{type} newval, ...)
@findex __sync_bool_compare_and_swap

View File

@ -257,7 +257,7 @@ Objective-C and Objective-C++ Dialects}.
-Wsign-compare -Wsign-conversion -Wstack-protector @gol
-Wstrict-aliasing -Wstrict-aliasing=n @gol
-Wstrict-overflow -Wstrict-overflow=@var{n} @gol
-Wswitch -Wswitch-default -Wswitch-enum @gol
-Wswitch -Wswitch-default -Wswitch-enum -Wsync-nand @gol
-Wsystem-headers -Wtrigraphs -Wtype-limits -Wundef -Wuninitialized @gol
-Wunknown-pragmas -Wno-pragmas -Wunreachable-code @gol
-Wunused -Wunused-function -Wunused-label -Wunused-parameter @gol
@ -3127,6 +3127,12 @@ and lacks a @code{case} for one or more of the named codes of that
enumeration. @code{case} labels outside the enumeration range also
provoke warnings when this option is used.
@item -Wsync-nand
@opindex Wsync-nand
@opindex Wno-sync-nand
Warn when @code{__sync_fetch_and_nand} and @code{__sync_nand_and_fetch}
built-in functions are used. These functions changed semantics in GCC 4.4.
@item -Wtrigraphs
@opindex Wtrigraphs
@opindex Wno-trigraphs

View File

@ -7182,12 +7182,13 @@ expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
t1 = t0;
if (code == NOT)
{
t1 = expand_simple_unop (mode, NOT, t1, NULL_RTX, true);
code = AND;
t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
true, OPTAB_LIB_WIDEN);
t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
}
t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
true, OPTAB_LIB_WIDEN);
else
t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
true, OPTAB_LIB_WIDEN);
insn = get_insns ();
end_sequence ();
@ -7315,9 +7316,17 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
}
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);
{
target = expand_simple_binop (mode, AND, target, val,
NULL_RTX, true,
OPTAB_LIB_WIDEN);
target = expand_simple_unop (mode, code, target,
NULL_RTX, true);
}
else
target = expand_simple_binop (mode, code, target, val,
NULL_RTX, true,
OPTAB_LIB_WIDEN);
}
return target;
@ -7340,11 +7349,13 @@ expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
t1 = t0;
if (code == NOT)
{
t1 = expand_simple_unop (mode, NOT, t1, NULL_RTX, true);
code = AND;
t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
true, OPTAB_LIB_WIDEN);
t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
}
t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
true, OPTAB_LIB_WIDEN);
else
t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
true, OPTAB_LIB_WIDEN);
if (after)
emit_move_insn (target, t1);

View File

@ -1,3 +1,33 @@
2008-11-17 Uros Bizjak <ubizjak@gmail.com>
PR middle-end/37908
* gcc.dg/pr37908.c: New test.
* gcc.dg/ia64-sync-1.c: Correct __sync_fetch_and_nand and
__sync_nand_and_fetch results. Add dg-message to look for the warning
about changed semantics of NAND builtin.
(init_si, init_di): Change init value for __sync_fetch_and_nand to -1.
(test_si, test_di): Change expected result of
__sync_nand_and_fetch to ~7.
* gcc.dg/ia64-sync-2.c: Correct __sync_fetch_and_nand and
__sync_nand_and_fetch results. Add dg-message to look for the warning
about changed semantics of NAND builtin.
(init_noret_si, init_noret_di): Change init value for
__sync_fetch_and_nand to -1.
(init_noret_si, init_noret_di): Change expected result of
__sync_nand_and_fetch to ~7.
* gcc.dg/sync-2.c: Correct __sync_fetch_and_nand and
__sync_nand_and_fetch results. Add dg-message to look for the warning
about changed semantics of NAND builtin.
(init_qi, init_qi): Change init value for __sync_fetch_and_nand to -1.
(init_hi, init_hi): Change expected result of
__sync_nand_and_fetch to ~7.
* gcc.dg/sync-3.c: Copy from sync-2.c instead of including
the c source file.
* gcc.c-torture/compile/sync-1.c: Add dg-message to look for the
warning about changed semantics of NAND builtin.
* gcc.c-torture/compile/sync-2.c: Ditto.
* gcc.c-torture/compile/sync-3.c: Ditto.
2008-11-17 Jakub Jelinek <jakub@redhat.com>
PR c++/36089

View File

@ -1,3 +1,6 @@
/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
/* Validate that each of the __sync builtins compiles. This won't
necessarily link, since the target might not support the builtin,
so this may result in external library calls. */

View File

@ -1,3 +1,5 @@
/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
/* Validate that each of the __sync builtins compiles. This won't
necessarily link, since the target might not support the builtin,
so this may result in external library calls. */

View File

@ -1,3 +1,5 @@
/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
/* Validate that each of the __sync builtins compiles. This won't
necessarily link, since the target might not support the builtin,
so this may result in external library calls. */

View File

@ -4,6 +4,8 @@
/* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */
/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
/* Test basic functionality of the intrinsics. The operations should
not be optimized away if no one checks the return values. */
@ -13,8 +15,8 @@ extern void abort (void);
extern void *memcpy (void *, const void *, size_t);
static int AI[12];
static int init_noret_si[12] = { 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0 };
static int test_noret_si[12] = { 1, 1, 1, 0, 1, 4, 22, -12, 7, 8, 9, 7 };
static int init_noret_si[12] = { 0, 0, 0, 1, 0, 0, 0 , 0 , -1, 0, 0, -1 };
static int test_noret_si[12] = { 1, 1, 1, 0, 1, 4, 22, -12, 7 , 8, 9, ~7 };
static void
do_noret_si (void)
@ -35,8 +37,8 @@ do_noret_si (void)
}
static long AL[12];
static long init_noret_di[12] = { 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0 };
static long test_noret_di[12] = { 1, 1, 1, 0, 1, 4, 22, -12, 7, 8, 9, 7 };
static long init_noret_di[12] = { 0, 0, 0, 1, 0, 0, 0 , 0 , -1, 0, 0, -1 };
static long test_noret_di[12] = { 1, 1, 1, 0, 1, 4, 22, -12, 7 , 8, 9, ~7 };
static void
do_noret_di (void)

View File

@ -4,6 +4,9 @@
/* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */
/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
/* Test basic functionality of the intrinsics. */
__extension__ typedef __SIZE_TYPE__ size_t;
@ -12,8 +15,8 @@ extern void abort (void);
extern void *memcpy (void *, const void *, size_t);
static int AI[18];
static int init_si[18] = { 0,0,0,1,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 };
static int test_si[18] = { 1,1,1,1,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 };
static int init_si[18] = { 0,0,0,1,0,0, 0,0 ,-1,0,0,-1,0,0 ,-1,0,0,-1 };
static int test_si[18] = { 1,1,1,1,1,4,22,-12,7 ,8,9,~7,1,-12,7 ,8,9,~7 };
static void
do_si (void)
@ -44,7 +47,7 @@ do_si (void)
abort ();
if (__sync_fetch_and_xor(AI+10, 9) != 0)
abort ();
if (__sync_fetch_and_nand(AI+11, 7) != 0)
if (__sync_fetch_and_nand(AI+11, 7) != -1)
abort ();
if (__sync_add_and_fetch(AI+12, 1) != 1)
@ -57,13 +60,13 @@ do_si (void)
abort ();
if (__sync_xor_and_fetch(AI+16, 9) != 9)
abort ();
if (__sync_nand_and_fetch(AI+17, 7) != 7)
if (__sync_nand_and_fetch(AI+17, 7) != ~7)
abort ();
}
static long AL[18];
static long init_di[18] = { 0,0,0,1,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 };
static long test_di[18] = { 1,1,1,1,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 };
static long init_di[18] = { 0,0,0,1,0,0, 0,0 ,-1,0,0,-1,0,0 ,-1,0,0,-1 };
static long test_di[18] = { 1,1,1,1,1,4,22,-12,7 ,8,9,~7,1,-12,7 ,8,9,~7 };
static void
do_di (void)
@ -94,7 +97,7 @@ do_di (void)
abort ();
if (__sync_fetch_and_xor(AL+10, 9) != 0)
abort ();
if (__sync_fetch_and_nand(AL+11, 7) != 0)
if (__sync_fetch_and_nand(AL+11, 7) != -1)
abort ();
if (__sync_add_and_fetch(AL+12, 1) != 1)
@ -107,7 +110,7 @@ do_di (void)
abort ();
if (__sync_xor_and_fetch(AL+16, 9) != 9)
abort ();
if (__sync_nand_and_fetch(AL+17, 7) != 7)
if (__sync_nand_and_fetch(AL+17, 7) != ~7)
abort ();
}

View File

@ -0,0 +1,25 @@
/* { dg-do run } */
/* { dg-require-effective-target sync_char_short } */
/* { dg-options "-Wsync-nand" } */
/* { dg-options "-Wsync-nand -march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
/* { dg-options "-Wsync-nand -mcpu=v9" { target sparc*-*-* } } */
extern void abort (void);
int main (void)
{
short xLoc;
short xIn, xOut, xExpect, i = 1;
xLoc = xIn = ~ (1 << i);
xExpect = ~ (xIn & 0x7F);
xOut = __sync_nand_and_fetch (&xLoc, 0x7F); /* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" } */
if (xOut != xExpect)
abort ();
return 0;
}

View File

@ -4,18 +4,17 @@
/* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */
/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
/* Test functionality of the intrinsics for 'short' and 'char'. */
extern void abort (void);
extern void *memcpy (void *, const void *, __SIZE_TYPE__);
#ifndef AI_ALIGN
#define AI_ALIGN
#endif
static char AI[18] AI_ALIGN;
static char init_qi[18] = { 3,5,7,9,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 };
static char test_qi[18] = { 3,5,7,9,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 };
static char AI[18];
static char init_qi[18] = { 3,5,7,9,0,0,0 ,0 ,-1,0,0,-1,0,0 ,-1,0,0,-1 };
static char test_qi[18] = { 3,5,7,9,1,4,22,-12,7 ,8,9,~7,1,-12,7 ,8,9,~7 };
static void
do_qi (void)
@ -34,7 +33,7 @@ do_qi (void)
abort ();
if (__sync_fetch_and_xor(AI+10, 9) != 0)
abort ();
if (__sync_fetch_and_nand(AI+11, 7) != 0)
if (__sync_fetch_and_nand(AI+11, 7) != (char)-1)
abort ();
if (__sync_add_and_fetch(AI+12, 1) != 1)
@ -47,13 +46,13 @@ do_qi (void)
abort ();
if (__sync_xor_and_fetch(AI+16, 9) != 9)
abort ();
if (__sync_nand_and_fetch(AI+17, 7) != 7)
if (__sync_nand_and_fetch(AI+17, 7) != ~7)
abort ();
}
static short AL[18];
static short init_hi[18] = { 3,5,7,9,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 };
static short test_hi[18] = { 3,5,7,9,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 };
static short init_hi[18] = { 3,5,7,9,0,0,0 ,0 ,-1,0,0,-1,0,0 ,-1,0,0,-1 };
static short test_hi[18] = { 3,5,7,9,1,4,22,-12,7 ,8,9,~7,1,-12,7 ,8,9,~7 };
static void
do_hi (void)
@ -72,7 +71,7 @@ do_hi (void)
abort ();
if (__sync_fetch_and_xor(AL+10, 9) != 0)
abort ();
if (__sync_fetch_and_nand(AL+11, 7) != 0)
if (__sync_fetch_and_nand(AL+11, 7) != -1)
abort ();
if (__sync_add_and_fetch(AL+12, 1) != 1)
@ -85,7 +84,7 @@ do_hi (void)
abort ();
if (__sync_xor_and_fetch(AL+16, 9) != 9)
abort ();
if (__sync_nand_and_fetch(AL+17, 7) != 7)
if (__sync_nand_and_fetch(AL+17, 7) != ~7)
abort ();
}

View File

@ -1,10 +1,102 @@
/* { dg-do run } */
/* { dg-require-effective-target sync_char_short } */
/* { dg-options "-O2" } */
/* { dg-options "-march=i486 -O2" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
/* { dg-options "-mcpu=v9 -O2" { target sparc*-*-* } } */
/* { dg-options "-ansi" } */
/* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */
/* Test functionality of the intrinsics for 'short' and 'char'. */
#define AI_ALIGN __attribute__((__aligned__ (4)))
#include "sync-2.c"
extern void abort (void);
extern void *memcpy (void *, const void *, __SIZE_TYPE__);
static char AI[18] __attribute__((__aligned__ (4)));
static char init_qi[18] = { 3,5,7,9,0,0,0 ,0 ,-1,0,0,-1,0,0 ,-1,0,0,-1 };
static char test_qi[18] = { 3,5,7,9,1,4,22,-12,7 ,8,9,~7,1,-12,7 ,8,9,~7 };
static void
do_qi (void)
{
if (__sync_fetch_and_add(AI+4, 1) != 0)
abort ();
if (__sync_fetch_and_add(AI+5, 4) != 0)
abort ();
if (__sync_fetch_and_add(AI+6, 22) != 0)
abort ();
if (__sync_fetch_and_sub(AI+7, 12) != 0)
abort ();
if (__sync_fetch_and_and(AI+8, 7) != (char)-1)
abort ();
if (__sync_fetch_and_or(AI+9, 8) != 0)
abort ();
if (__sync_fetch_and_xor(AI+10, 9) != 0)
abort ();
if (__sync_fetch_and_nand(AI+11, 7) != (char)-1) /* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" } */
abort ();
if (__sync_add_and_fetch(AI+12, 1) != 1)
abort ();
if (__sync_sub_and_fetch(AI+13, 12) != (char)-12)
abort ();
if (__sync_and_and_fetch(AI+14, 7) != 7)
abort ();
if (__sync_or_and_fetch(AI+15, 8) != 8)
abort ();
if (__sync_xor_and_fetch(AI+16, 9) != 9)
abort ();
if (__sync_nand_and_fetch(AI+17, 7) != ~7) /* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" } */
abort ();
}
static short AL[18];
static short init_hi[18] = { 3,5,7,9,0,0,0 ,0 ,-1,0,0,-1,0,0 ,-1,0,0,-1 };
static short test_hi[18] = { 3,5,7,9,1,4,22,-12,7 ,8,9,~7,1,-12,7 ,8,9,~7 };
static void
do_hi (void)
{
if (__sync_fetch_and_add(AL+4, 1) != 0)
abort ();
if (__sync_fetch_and_add(AL+5, 4) != 0)
abort ();
if (__sync_fetch_and_add(AL+6, 22) != 0)
abort ();
if (__sync_fetch_and_sub(AL+7, 12) != 0)
abort ();
if (__sync_fetch_and_and(AL+8, 7) != -1)
abort ();
if (__sync_fetch_and_or(AL+9, 8) != 0)
abort ();
if (__sync_fetch_and_xor(AL+10, 9) != 0)
abort ();
if (__sync_fetch_and_nand(AL+11, 7) != -1)
abort ();
if (__sync_add_and_fetch(AL+12, 1) != 1)
abort ();
if (__sync_sub_and_fetch(AL+13, 12) != -12)
abort ();
if (__sync_and_and_fetch(AL+14, 7) != 7)
abort ();
if (__sync_or_and_fetch(AL+15, 8) != 8)
abort ();
if (__sync_xor_and_fetch(AL+16, 9) != 9)
abort ();
if (__sync_nand_and_fetch(AL+17, 7) != ~7)
abort ();
}
int main()
{
memcpy(AI, init_qi, sizeof(init_qi));
memcpy(AL, init_hi, sizeof(init_hi));
do_qi ();
do_hi ();
if (memcmp (AI, test_qi, sizeof(test_qi)))
abort ();
if (memcmp (AL, test_hi, sizeof(test_hi)))
abort ();
return 0;
}