From c449f851c5fc2e2e46b98d8a22bde7571a9cedc6 Mon Sep 17 00:00:00 2001 From: amacleod Date: Thu, 10 Nov 2011 16:39:32 +0000 Subject: [PATCH] PR rtl-optimization/51040 * optabs.c (expand_atomic_fetch_op): Patchup code for NAND should be AND followed by NOT. * builtins.c (expand_builtin_atomic_fetch_op): Patchup code for NAND should be AND followed by NOT. * testsuite/gcc.dg/atomic-noinline[-aux].c: Test no-inline NAND and patchup code. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181259 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 10 ++++++++++ gcc/builtins.c | 13 +++++++++++-- gcc/optabs.c | 11 +++++++++-- gcc/testsuite/gcc.dg/atomic-noinline-aux.c | 15 ++++++++++++++- gcc/testsuite/gcc.dg/atomic-noinline.c | 7 +++++++ 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 86515365d21..fa7cbeb1bb5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2011-11-10 Andrew MacLeod + + PR rtl-optimization/51040 + * optabs.c (expand_atomic_fetch_op): Patchup code for NAND should be AND + followed by NOT. + * builtins.c (expand_builtin_atomic_fetch_op): Patchup code for NAND + should be AND followed by NOT. + * testsuite/gcc.dg/atomic-noinline[-aux].c: Test no-inline NAND and + patchup code. + 2011-11-10 Jakub Jelinek * vec.h (VEC_BASE): If base is at offset 0 in the structure, diff --git a/gcc/builtins.c b/gcc/builtins.c index 516292783bc..d949dbb632f 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -5460,8 +5460,17 @@ expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target, /* Then issue the arithmetic correction to return the right result. */ if (!ignore) - ret = expand_simple_binop (mode, code, ret, val, NULL_RTX, true, - OPTAB_LIB_WIDEN); + { + if (code == NOT) + { + ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true, + OPTAB_LIB_WIDEN); + ret = expand_simple_unop (mode, NOT, ret, target, true); + } + else + ret = expand_simple_binop (mode, code, ret, val, target, true, + OPTAB_LIB_WIDEN); + } return ret; } diff --git a/gcc/optabs.c b/gcc/optabs.c index b2388ec5c74..c87f5cd84ad 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -7875,8 +7875,15 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code, Fetch_before == after REVERSE_OP val. */ if (!after) code = optab.reverse_code; - result = expand_simple_binop (mode, code, result, val, target, true, - OPTAB_LIB_WIDEN); + if (code == NOT) + { + result = expand_simple_binop (mode, AND, result, val, NULL_RTX, + true, OPTAB_LIB_WIDEN); + result = expand_simple_unop (mode, NOT, result, target, true); + } + else + result = expand_simple_binop (mode, code, result, val, target, + true, OPTAB_LIB_WIDEN); return result; } } diff --git a/gcc/testsuite/gcc.dg/atomic-noinline-aux.c b/gcc/testsuite/gcc.dg/atomic-noinline-aux.c index b92fcfcd60f..b05460e469b 100644 --- a/gcc/testsuite/gcc.dg/atomic-noinline-aux.c +++ b/gcc/testsuite/gcc.dg/atomic-noinline-aux.c @@ -40,11 +40,24 @@ char __atomic_fetch_add_1 (char *p, char v, int i) *p = 1; } -short __atomic_fetch_add_2 (short *p, short v, short i) +short __atomic_fetch_add_2 (short *p, short v, int i) { *p = 1; } +/* Really perform a NAND. PR51040 showed incorrect calculation of a + non-inlined fetch_nand. */ +unsigned char +__atomic_fetch_nand_1 (unsigned char *p, unsigned char v, int i) +{ + unsigned char ret; + + ret = *p; + *p = ~(*p & v); + + return ret; +} + int __atomic_is_lock_free (int i, void *p) { return 10; diff --git a/gcc/testsuite/gcc.dg/atomic-noinline.c b/gcc/testsuite/gcc.dg/atomic-noinline.c index 06a93e0058e..eb0866e549e 100644 --- a/gcc/testsuite/gcc.dg/atomic-noinline.c +++ b/gcc/testsuite/gcc.dg/atomic-noinline.c @@ -49,6 +49,13 @@ main () if (__atomic_is_lock_free (4, 0) != 10) abort (); + /* PR 51040 was caused by arithmetic code not patching up nand_fetch properly + when used an an external function. Look for proper return value here. */ + ac = 0x3C; + bc = __atomic_nand_fetch (&ac, 0x0f, __ATOMIC_RELAXED); + if (bc != ac) + abort (); + return 0; } -- 2.11.0