public inbox for gcc-regression@sourceware.org
help / color / mirror / Atom feed
* Re: [TCWG CI] Regression caused by gcc: Improve integer bit test on __atomic_fetch_[or|and]_* returns
       [not found] <129273368.6511.1636560535186@jenkins.jenkins>
@ 2021-11-11  1:22 ` Hongtao Liu
  2021-11-11  8:55   ` Hongtao Liu
  0 siblings, 1 reply; 2+ messages in thread
From: Hongtao Liu @ 2021-11-11  1:22 UTC (permalink / raw)
  To: ci_notify; +Cc: liuhongt, gcc-regression

On Thu, Nov 11, 2021 at 12:09 AM ci_notify--- via Gcc-regression
<gcc-regression@gcc.gnu.org> wrote:
>
> [TCWG CI] Regression caused by gcc: Improve integer bit test on __atomic_fetch_[or|and]_* returns:
> commit fb161782545224f55ba26ba663889c5e6e9a04d1
> Author: liuhongt <hongtao.liu@intel.com>
>
>     Improve integer bit test on __atomic_fetch_[or|and]_* returns
>
> Results regressed to
> # reset_artifacts:
> -10
> # true:
> 0
> # build_abe binutils:
> 1
> # build_abe stage1:
> 2
> # build_abe linux:
> 3
> # First few build errors in logs:
> # 00:00:51 pthread_cancel.c:60:1: error: type mismatch in binary expression
> # 00:00:51 pthread_cancel.c:60:1: internal compiler error: verify_gimple failed
> # 00:00:51 make[2]: *** [../o-iterator.mk:9: /home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/builds/x86_64-pc-linux-gnu/aarch64-linux-gnu/glibc-glibc.git~master/nptl/pthread_cancel.o] Error 1
> # 00:00:52 make[1]: *** [Makefile:483: nptl/subdir_lib] Error 2
> # 00:00:52 make: *** [Makefile:9: all] Error 2
>
It seems there's ICE when using gcc to build glibc, what's the
configure for building glibc?
> from
> # reset_artifacts:
> -10
> # true:
> 0
> # build_abe binutils:
> 1
> # build_abe stage1:
> 2
> # build_abe linux:
> 3
> # build_abe glibc:
> 4
> # build_abe stage2:
> 5
>
> THIS IS THE END OF INTERESTING STUFF.  BELOW ARE LINKS TO BUILDS, REPRODUCTION INSTRUCTIONS, AND THE RAW COMMIT.
>
> This commit has regressed these CI configurations:
>  - tcwg_gnu_cross_build/master-aarch64
>
> First_bad build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/build-fb161782545224f55ba26ba663889c5e6e9a04d1/
> Last_good build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/build-f15ad1e3f9488a31abf1c122bd186c1a3d2a5dbc/
> Baseline build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/build-baseline/
> Even more details: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/
>
> Reproduce builds:
> <cut>
> mkdir investigate-gcc-fb161782545224f55ba26ba663889c5e6e9a04d1
> cd investigate-gcc-fb161782545224f55ba26ba663889c5e6e9a04d1
>
> # Fetch scripts
> git clone https://git.linaro.org/toolchain/jenkins-scripts
>
> # Fetch manifests and test.sh script
> mkdir -p artifacts/manifests
> curl -o artifacts/manifests/build-baseline.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/manifests/build-baseline.sh --fail
> curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/manifests/build-parameters.sh --fail
> curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/test.sh --fail
> chmod +x artifacts/test.sh
>
> # Reproduce the baseline build (build all pre-requisites)
> ./jenkins-scripts/tcwg_gnu-build.sh @@ artifacts/manifests/build-baseline.sh
>
> # Save baseline build state (which is then restored in artifacts/test.sh)
> mkdir -p ./bisect
> rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /gcc/ ./ ./bisect/baseline/
>
> cd gcc
>
> # Reproduce first_bad build
> git checkout --detach fb161782545224f55ba26ba663889c5e6e9a04d1
> ../artifacts/test.sh
>
> # Reproduce last_good build
> git checkout --detach f15ad1e3f9488a31abf1c122bd186c1a3d2a5dbc
> ../artifacts/test.sh
>
> cd ..
> </cut>
>
> Full commit (up to 1000 lines):
> <cut>
> commit fb161782545224f55ba26ba663889c5e6e9a04d1
> Author: liuhongt <hongtao.liu@intel.com>
> Date:   Mon Oct 25 13:59:51 2021 +0800
>
>     Improve integer bit test on __atomic_fetch_[or|and]_* returns
>
>     commit adedd5c173388ae505470df152b9cb3947339566
>     Author: Jakub Jelinek <jakub@redhat.com>
>     Date:   Tue May 3 13:37:25 2016 +0200
>
>         re PR target/49244 (__sync or __atomic builtins will not emit 'lock bts/btr/btc')
>
>     optimized bit test on __atomic_fetch_or_* and __atomic_fetch_and_* returns
>     with lock bts/btr/btc by turning
>
>       mask_2 = 1 << cnt_1;
>       _4 = __atomic_fetch_or_* (ptr_6, mask_2, _3);
>       _5 = _4 & mask_2;
>
>     into
>
>       _4 = ATOMIC_BIT_TEST_AND_SET (ptr_6, cnt_1, 0, _3);
>       _5 = _4;
>
>     and
>
>       mask_6 = 1 << bit_5(D);
>       _1 = ~mask_6;
>       _2 = __atomic_fetch_and_4 (v_8(D), _1, 0);
>       _3 = _2 & mask_6;
>       _4 = _3 != 0;
>
>     into
>
>       mask_6 = 1 << bit_5(D);
>       _1 = ~mask_6;
>       _11 = .ATOMIC_BIT_TEST_AND_RESET (v_8(D), bit_5(D), 1, 0);
>       _4 = _11 != 0;
>
>     But it failed to optimize many equivalent, but slighly different cases:
>
>     1.
>       _1 = __atomic_fetch_or_4 (ptr_6, 1, _3);
>       _4 = (_Bool) _1;
>     2.
>       _1 = __atomic_fetch_and_4 (ptr_6, ~1, _3);
>       _4 = (_Bool) _1;
>     3.
>       _1 = __atomic_fetch_or_4 (ptr_6, 1, _3);
>       _7 = ~_1;
>       _5 = (_Bool) _7;
>     4.
>       _1 = __atomic_fetch_and_4 (ptr_6, ~1, _3);
>       _7 = ~_1;
>       _5 = (_Bool) _7;
>     5.
>       _1 = __atomic_fetch_or_4 (ptr_6, 1, _3);
>       _2 = (int) _1;
>       _7 = ~_2;
>       _5 = (_Bool) _7;
>     6.
>       _1 = __atomic_fetch_and_4 (ptr_6, ~1, _3);
>       _2 = (int) _1;
>       _7 = ~_2;
>       _5 = (_Bool) _7;
>     7.
>       _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
>       _5 = (signed int) _1;
>       _4 = _5 < 0;
>     8.
>       _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
>       _5 = (signed int) _1;
>       _4 = _5 < 0;
>     9.
>       _1 = 1 << bit_4(D);
>       mask_5 = (unsigned int) _1;
>       _2 = __atomic_fetch_or_4 (v_7(D), mask_5, 0);
>       _3 = _2 & mask_5;
>     10.
>       mask_7 = 1 << bit_6(D);
>       _1 = ~mask_7;
>       _2 = (unsigned int) _1;
>       _3 = __atomic_fetch_and_4 (v_9(D), _2, 0);
>       _4 = (int) _3;
>       _5 = _4 & mask_7;
>
>     We make
>
>       mask_2 = 1 << cnt_1;
>       _4 = __atomic_fetch_or_* (ptr_6, mask_2, _3);
>       _5 = _4 & mask_2;
>
>     and
>
>       mask_6 = 1 << bit_5(D);
>       _1 = ~mask_6;
>       _2 = __atomic_fetch_and_4 (v_8(D), _1, 0);
>       _3 = _2 & mask_6;
>       _4 = _3 != 0;
>
>     the canonical forms for this optimization and transform cases 1-9 to the
>     equivalent canonical form.  For cases 10 and 11, we simply remove the cast
>     before __atomic_fetch_or_4/__atomic_fetch_and_4 with
>
>       _1 = 1 << bit_4(D);
>       _2 = __atomic_fetch_or_4 (v_7(D), _1, 0);
>       _3 = _2 & _1;
>
>     and
>
>       mask_7 = 1 << bit_6(D);
>       _1 = ~mask_7;
>       _3 = __atomic_fetch_and_4 (v_9(D), _1, 0);
>       _6 = _3 & mask_7;
>       _5 = (int) _6;
>
>     2021-11-04  H.J. Lu  <hongjiu.lu@intel.com>
>                 Hongtao Liu  <hongtao.liu@intel.com>
>     gcc/
>
>             PR middle-end/102566
>             * match.pd (nop_atomic_bit_test_and_p): New match.
>             * tree-ssa-ccp.c (convert_atomic_bit_not): New function.
>             (gimple_nop_atomic_bit_test_and_p): New prototype.
>             (optimize_atomic_bit_test_and): Transform equivalent, but slighly
>             different cases to their canonical forms.
>
>     gcc/testsuite/
>
>             PR middle-end/102566
>             * g++.target/i386/pr102566-1.C: New test.
>             * g++.target/i386/pr102566-2.C: Likewise.
>             * g++.target/i386/pr102566-3.C: Likewise.
>             * g++.target/i386/pr102566-4.C: Likewise.
>             * g++.target/i386/pr102566-5a.C: Likewise.
>             * g++.target/i386/pr102566-5b.C: Likewise.
>             * g++.target/i386/pr102566-6a.C: Likewise.
>             * g++.target/i386/pr102566-6b.C: Likewise.
>             * gcc.target/i386/pr102566-1a.c: Likewise.
>             * gcc.target/i386/pr102566-1b.c: Likewise.
>             * gcc.target/i386/pr102566-2.c: Likewise.
>             * gcc.target/i386/pr102566-3a.c: Likewise.
>             * gcc.target/i386/pr102566-3b.c: Likewise.
>             * gcc.target/i386/pr102566-4.c: Likewise.
>             * gcc.target/i386/pr102566-5.c: Likewise.
>             * gcc.target/i386/pr102566-6.c: Likewise.
>             * gcc.target/i386/pr102566-7.c: Likewise.
>             * gcc.target/i386/pr102566-8a.c: Likewise.
>             * gcc.target/i386/pr102566-8b.c: Likewise.
>             * gcc.target/i386/pr102566-9a.c: Likewise.
>             * gcc.target/i386/pr102566-9b.c: Likewise.
>             * gcc.target/i386/pr102566-10a.c: Likewise.
>             * gcc.target/i386/pr102566-10b.c: Likewise.
>             * gcc.target/i386/pr102566-11.c: Likewise.
>             * gcc.target/i386/pr102566-12.c: Likewise.
>             * gcc.target/i386/pr102566-13.c: New test.
>             * gcc.target/i386/pr102566-14.c: New test.
> ---
>  gcc/match.pd                                 | 103 ++++++
>  gcc/testsuite/g++.target/i386/pr102566-1.C   |  31 ++
>  gcc/testsuite/g++.target/i386/pr102566-2.C   |  31 ++
>  gcc/testsuite/g++.target/i386/pr102566-3.C   |  31 ++
>  gcc/testsuite/g++.target/i386/pr102566-4.C   |  29 ++
>  gcc/testsuite/g++.target/i386/pr102566-5a.C  |  31 ++
>  gcc/testsuite/g++.target/i386/pr102566-5b.C  |  31 ++
>  gcc/testsuite/g++.target/i386/pr102566-6a.C  |  31 ++
>  gcc/testsuite/g++.target/i386/pr102566-6b.C  |  31 ++
>  gcc/testsuite/gcc.target/i386/pr102566-10a.c |  15 +
>  gcc/testsuite/gcc.target/i386/pr102566-10b.c |  15 +
>  gcc/testsuite/gcc.target/i386/pr102566-11.c  |  28 ++
>  gcc/testsuite/gcc.target/i386/pr102566-12.c  |  28 ++
>  gcc/testsuite/gcc.target/i386/pr102566-13.c  |  66 ++++
>  gcc/testsuite/gcc.target/i386/pr102566-14.c  |  65 ++++
>  gcc/testsuite/gcc.target/i386/pr102566-1a.c  | 188 +++++++++++
>  gcc/testsuite/gcc.target/i386/pr102566-1b.c  | 107 +++++++
>  gcc/testsuite/gcc.target/i386/pr102566-2.c   |  32 ++
>  gcc/testsuite/gcc.target/i386/pr102566-3a.c  |  15 +
>  gcc/testsuite/gcc.target/i386/pr102566-3b.c  |  15 +
>  gcc/testsuite/gcc.target/i386/pr102566-4.c   |  15 +
>  gcc/testsuite/gcc.target/i386/pr102566-5.c   |  15 +
>  gcc/testsuite/gcc.target/i386/pr102566-6.c   |  32 ++
>  gcc/testsuite/gcc.target/i386/pr102566-7.c   |  30 ++
>  gcc/testsuite/gcc.target/i386/pr102566-8a.c  |  32 ++
>  gcc/testsuite/gcc.target/i386/pr102566-8b.c  |  32 ++
>  gcc/testsuite/gcc.target/i386/pr102566-9a.c  |  32 ++
>  gcc/testsuite/gcc.target/i386/pr102566-9b.c  |  32 ++
>  gcc/tree-ssa-ccp.c                           | 456 ++++++++++++++++++++++++---
>  29 files changed, 1557 insertions(+), 42 deletions(-)
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 7826af1998a..a319aefa808 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -105,6 +105,39 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>  (define_operator_list COND_TERNARY
>    IFN_COND_FMA IFN_COND_FMS IFN_COND_FNMA IFN_COND_FNMS)
>
> +/* __atomic_fetch_or_*, __atomic_fetch_xor_*, __atomic_xor_fetch_*  */
> +(define_operator_list ATOMIC_FETCH_OR_XOR_N
> +  BUILT_IN_ATOMIC_FETCH_OR_1 BUILT_IN_ATOMIC_FETCH_OR_2
> +  BUILT_IN_ATOMIC_FETCH_OR_4 BUILT_IN_ATOMIC_FETCH_OR_8
> +  BUILT_IN_ATOMIC_FETCH_OR_16
> +  BUILT_IN_ATOMIC_FETCH_XOR_1 BUILT_IN_ATOMIC_FETCH_XOR_2
> +  BUILT_IN_ATOMIC_FETCH_XOR_4 BUILT_IN_ATOMIC_FETCH_XOR_8
> +  BUILT_IN_ATOMIC_FETCH_XOR_16
> +  BUILT_IN_ATOMIC_XOR_FETCH_1 BUILT_IN_ATOMIC_XOR_FETCH_2
> +  BUILT_IN_ATOMIC_XOR_FETCH_4 BUILT_IN_ATOMIC_XOR_FETCH_8
> +  BUILT_IN_ATOMIC_XOR_FETCH_16)
> +/* __sync_fetch_and_or_*, __sync_fetch_and_xor_*, __sync_xor_and_fetch_*  */
> +(define_operator_list SYNC_FETCH_OR_XOR_N
> +  BUILT_IN_SYNC_FETCH_AND_OR_1 BUILT_IN_SYNC_FETCH_AND_OR_2
> +  BUILT_IN_SYNC_FETCH_AND_OR_4 BUILT_IN_SYNC_FETCH_AND_OR_8
> +  BUILT_IN_SYNC_FETCH_AND_OR_16
> +  BUILT_IN_SYNC_FETCH_AND_XOR_1 BUILT_IN_SYNC_FETCH_AND_XOR_2
> +  BUILT_IN_SYNC_FETCH_AND_XOR_4 BUILT_IN_SYNC_FETCH_AND_XOR_8
> +  BUILT_IN_SYNC_FETCH_AND_XOR_16
> +  BUILT_IN_SYNC_XOR_AND_FETCH_1 BUILT_IN_SYNC_XOR_AND_FETCH_2
> +  BUILT_IN_SYNC_XOR_AND_FETCH_4 BUILT_IN_SYNC_XOR_AND_FETCH_8
> +  BUILT_IN_SYNC_XOR_AND_FETCH_16)
> +/* __atomic_fetch_and_*.  */
> +(define_operator_list ATOMIC_FETCH_AND_N
> +  BUILT_IN_ATOMIC_FETCH_AND_1 BUILT_IN_ATOMIC_FETCH_AND_2
> +  BUILT_IN_ATOMIC_FETCH_AND_4 BUILT_IN_ATOMIC_FETCH_AND_8
> +  BUILT_IN_ATOMIC_FETCH_AND_16)
> +/* __sync_fetch_and_and_*.  */
> +(define_operator_list SYNC_FETCH_AND_AND_N
> +  BUILT_IN_SYNC_FETCH_AND_AND_1 BUILT_IN_SYNC_FETCH_AND_AND_2
> +  BUILT_IN_SYNC_FETCH_AND_AND_4 BUILT_IN_SYNC_FETCH_AND_AND_8
> +  BUILT_IN_SYNC_FETCH_AND_AND_16)
> +
>  /* With nop_convert? combine convert? and view_convert? in one pattern
>     plus conditionalize on tree_nop_conversion_p conversions.  */
>  (match (nop_convert @0)
> @@ -3976,6 +4009,76 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>    (vec_cond @0 (op! @3 @1) (op! @3 @2))))
>  #endif
>
> +#if GIMPLE
> +(match (nop_atomic_bit_test_and_p @0 @1 @4)
> + (bit_and (nop_convert?@4 (ATOMIC_FETCH_OR_XOR_N @2 INTEGER_CST@0 @3))
> +          INTEGER_CST@1)
> + (with {
> +        int ibit = tree_log2 (@0);
> +        int ibit2 = tree_log2 (@1);
> +       }
> +  (if (ibit == ibit2
> +      && ibit >= 0))))
> +
> +(match (nop_atomic_bit_test_and_p @0 @1 @3)
> + (bit_and (nop_convert?@3 (SYNC_FETCH_OR_XOR_N @2 INTEGER_CST@0))
> +         INTEGER_CST@1)
> + (with {
> +        int ibit = tree_log2 (@0);
> +        int ibit2 = tree_log2 (@1);
> +       }
> +  (if (ibit == ibit2
> +      && ibit >= 0))))
> +
> +(match (nop_atomic_bit_test_and_p @0 @0 @4)
> + (bit_and:c
> +  (nop_convert?@4
> +   (ATOMIC_FETCH_OR_XOR_N @2 (nop_convert? (lshift@0 integer_onep@5 @6)) @3))
> +  @0))
> +
> +(match (nop_atomic_bit_test_and_p @0 @0 @4)
> + (bit_and:c
> +  (nop_convert?@4
> +   (SYNC_FETCH_OR_XOR_N @2 (nop_convert? (lshift@0 integer_onep@3 @5))))
> +  @0))
> +
> +(match (nop_atomic_bit_test_and_p @0 @1 @3)
> + (bit_and@4 (nop_convert?@3 (ATOMIC_FETCH_AND_N @2 INTEGER_CST@0 @5))
> +           INTEGER_CST@1)
> + (with {
> +        int ibit = wi::exact_log2 (wi::zext (wi::bit_not (wi::to_wide (@0)),
> +                                             TYPE_PRECISION(type)));
> +        int ibit2 = tree_log2 (@1);
> +       }
> +  (if (ibit == ibit2
> +      && ibit >= 0))))
> +
> +(match (nop_atomic_bit_test_and_p @0 @1 @3)
> + (bit_and@4
> +  (nop_convert?@3 (SYNC_FETCH_AND_AND_N @2 INTEGER_CST@0))
> +  INTEGER_CST@1)
> + (with {
> +        int ibit = wi::exact_log2 (wi::zext (wi::bit_not (wi::to_wide (@0)),
> +                                             TYPE_PRECISION(type)));
> +        int ibit2 = tree_log2 (@1);
> +       }
> +  (if (ibit == ibit2
> +      && ibit >= 0))))
> +
> +(match (nop_atomic_bit_test_and_p @0 @0 @3)
> + (bit_and:c
> +  (nop_convert?@3
> +   (ATOMIC_FETCH_AND_N @2 (nop_convert? (bit_not (lshift@0 integer_onep@6 @7))) @5))
> +   @0))
> +
> +(match (nop_atomic_bit_test_and_p @0 @0 @3)
> + (bit_and:c
> +  (nop_convert?@3
> +   (SYNC_FETCH_AND_AND_N @2 (nop_convert? (bit_not (lshift@0 integer_onep@6 @7)))))
> +   @0))
> +
> +#endif
> +
>  /* (v ? w : 0) ? a : b is just (v & w) ? a : b
>     Currently disabled after pass lvec because ARM understands
>     VEC_COND_EXPR<v==w,-1,0> but not a plain v==w fed to BIT_IOR_EXPR.  */
> diff --git a/gcc/testsuite/g++.target/i386/pr102566-1.C b/gcc/testsuite/g++.target/i386/pr102566-1.C
> new file mode 100644
> index 00000000000..94a66d717cc
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/pr102566-1.C
> @@ -0,0 +1,31 @@
> +/* { dg-do compile { target c++11 } } */
> +/* { dg-options "-O2" } */
> +
> +#include <atomic>
> +
> +bool
> +tbit0 (std::atomic<int> &i)
> +{
> +#define BIT (1 << 0)
> +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +bool
> +tbit30 (std::atomic<int> &i)
> +{
> +#define BIT (1 << 30)
> +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +bool
> +tbit31 (std::atomic<int> &i)
> +{
> +#define BIT (1 << 31)
> +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btsl" 3 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/testsuite/g++.target/i386/pr102566-2.C b/gcc/testsuite/g++.target/i386/pr102566-2.C
> new file mode 100644
> index 00000000000..4f2aea961c2
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/pr102566-2.C
> @@ -0,0 +1,31 @@
> +/* { dg-do compile { target c++11 } } */
> +/* { dg-options "-O2" } */
> +
> +#include <atomic>
> +
> +bool
> +tbit0 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 0)
> +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +bool
> +tbit30 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 30)
> +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +bool
> +tbit31 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 31)
> +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btsl" 3 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/testsuite/g++.target/i386/pr102566-3.C b/gcc/testsuite/g++.target/i386/pr102566-3.C
> new file mode 100644
> index 00000000000..e88921dd155
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/pr102566-3.C
> @@ -0,0 +1,31 @@
> +/* { dg-do compile { target c++11 } } */
> +/* { dg-options "-O2" } */
> +
> +#include <atomic>
> +
> +bool
> +tbit0 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 0)
> +  return !(i.fetch_or(BIT, std::memory_order_relaxed) & BIT);
> +#undef BIT
> +}
> +
> +bool
> +tbit30 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 30)
> +  return !(i.fetch_or(BIT, std::memory_order_relaxed) & BIT);
> +#undef BIT
> +}
> +
> +bool
> +tbit31 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 31)
> +  return !(i.fetch_or(BIT, std::memory_order_relaxed) & BIT);
> +#undef BIT
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btsl" 3 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/testsuite/g++.target/i386/pr102566-4.C b/gcc/testsuite/g++.target/i386/pr102566-4.C
> new file mode 100644
> index 00000000000..44d1362ac2e
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/pr102566-4.C
> @@ -0,0 +1,29 @@
> +/* { dg-do compile { target c++11 } } */
> +/* { dg-options "-O2" } */
> +
> +#include <atomic>
> +
> +typedef int __attribute__ ((mode (__word__))) int_type;
> +
> +#define BIT (1 << 0)
> +
> +bool
> +tbit0 (std::atomic<int_type> &i)
> +{
> +  return i.fetch_or(BIT, std::memory_order_relaxed) & ~1;
> +}
> +
> +bool
> +tbit30 (std::atomic<int_type> &i)
> +{
> +  return i.fetch_or(BIT, std::memory_order_relaxed) & ~2;
> +}
> +
> +bool
> +tbit31 (std::atomic<int_type> &i)
> +{
> +  return i.fetch_or(BIT, std::memory_order_relaxed) & ~4;
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*cmpxchg" 3 } } */
> +/* { dg-final { scan-assembler-not "bts" } } */
> diff --git a/gcc/testsuite/g++.target/i386/pr102566-5a.C b/gcc/testsuite/g++.target/i386/pr102566-5a.C
> new file mode 100644
> index 00000000000..f9595bee2ab
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/pr102566-5a.C
> @@ -0,0 +1,31 @@
> +/* { dg-do compile { target c++11 } } */
> +/* { dg-options "-O2" } */
> +
> +#include <atomic>
> +
> +bool
> +tbit0 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 0)
> +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +bool
> +tbit30 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 30)
> +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +bool
> +tbit31 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 31)
> +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrl" 3 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/testsuite/g++.target/i386/pr102566-5b.C b/gcc/testsuite/g++.target/i386/pr102566-5b.C
> new file mode 100644
> index 00000000000..d917b27a918
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/pr102566-5b.C
> @@ -0,0 +1,31 @@
> +/* { dg-do compile { target { c++11 && { ! ia32 } } } } */
> +/* { dg-options "-O2" } */
> +
> +#include <atomic>
> +
> +bool
> +tbit0 (std::atomic<unsigned long long> &i)
> +{
> +#define BIT (1ll << 0)
> +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +bool
> +tbit30 (std::atomic<unsigned long long> &i)
> +{
> +#define BIT (1ll << 30)
> +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +bool
> +tbit31 (std::atomic<unsigned long long> &i)
> +{
> +#define BIT (1ll << 63)
> +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> +#undef BIT
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrq" 3 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/testsuite/g++.target/i386/pr102566-6a.C b/gcc/testsuite/g++.target/i386/pr102566-6a.C
> new file mode 100644
> index 00000000000..01d495eda23
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/pr102566-6a.C
> @@ -0,0 +1,31 @@
> +/* { dg-do compile { target c++11 } } */
> +/* { dg-options "-O2" } */
> +
> +#include <atomic>
> +
> +bool
> +tbit0 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 0)
> +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> +#undef BIT
> +}
> +
> +bool
> +tbit30 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 30)
> +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> +#undef BIT
> +}
> +
> +bool
> +tbit31 (std::atomic<unsigned int> &i)
> +{
> +#define BIT (1 << 31)
> +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> +#undef BIT
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrl" 3 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/testsuite/g++.target/i386/pr102566-6b.C b/gcc/testsuite/g++.target/i386/pr102566-6b.C
> new file mode 100644
> index 00000000000..adc11fcbf2d
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/pr102566-6b.C
> @@ -0,0 +1,31 @@
> +/* { dg-do compile { target { c++11 && { ! ia32 } } } } */
> +/* { dg-options "-O2" } */
> +
> +#include <atomic>
> +
> +bool
> +tbit0 (std::atomic<unsigned long long> &i)
> +{
> +#define BIT (1ll << 0)
> +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> +#undef BIT
> +}
> +
> +bool
> +tbit30 (std::atomic<unsigned long long> &i)
> +{
> +#define BIT (1ll << 30)
> +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> +#undef BIT
> +}
> +
> +bool
> +tbit31 (std::atomic<unsigned long long> &i)
> +{
> +#define BIT (1ll << 63)
> +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> +#undef BIT
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrq" 3 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr102566-10a.c b/gcc/testsuite/gcc.target/i386/pr102566-10a.c
> new file mode 100644
> index 00000000000..1c1f86a9659
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr102566-10a.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +#include <stdatomic.h>
> +#include <stdbool.h>
> +
> +bool
> +foo (_Atomic int *v, int bit)
> +{
> +  int mask = 1 << bit;
> +  return atomic_fetch_and_explicit (v, ~mask, memory_order_relaxed) & mask;
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrl" 1 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr102566-10b.c b/gcc/testsuite/gcc.target/i386/pr102566-10b.c
> new file mode 100644
> index 00000000000..0bf39824ea6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr102566-10b.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile { target { ! ia32 } } } */
> +/* { dg-options "-O2" } */
> +
> +#include <stdatomic.h>
> +#include <stdbool.h>
> +
> +bool
> +foo (_Atomic long long int *v, int bit)
> +{
> +  long long int mask = 1ll << bit;
> +  return atomic_fetch_and_explicit (v, ~mask, memory_order_relaxed) & mask;
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrq" 1 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr102566-11.c b/gcc/testsuite/gcc.target/i386/pr102566-11.c
> new file mode 100644
> index 00000000000..2c8f8c4e59a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr102566-11.c
> @@ -0,0 +1,28 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +#include <stdatomic.h>
> +#include <stdbool.h>
> +
> +#define MASK 0x1234
> +
> +bool
> +foo1 (_Atomic int *v)
> +{
> +  return atomic_fetch_or_explicit (v, MASK, memory_order_relaxed) & MASK;
> +}
> +
> +bool
> +foo2 (_Atomic unsigned int *v, int mask)
> +{
> +  return atomic_fetch_or_explicit (v, mask, memory_order_relaxed) & mask;
> +}
> +
> +bool
> +foo3 (_Atomic unsigned int *v, int mask)
> +{
> +  return !(atomic_fetch_or_explicit (v, mask, memory_order_relaxed) & mask);
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*cmpxchg" 3 } } */
> +/* { dg-final { scan-assembler-not "bts" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr102566-12.c b/gcc/testsuite/gcc.target/i386/pr102566-12.c
> new file mode 100644
> index 00000000000..4603a77612c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr102566-12.c
> @@ -0,0 +1,28 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +#include <stdatomic.h>
> +#include <stdbool.h>
> +
> +#define MASK 0x1234
> +
> +bool
> +foo1 (_Atomic long *v)
> +{
> +  return atomic_fetch_and_explicit (v, ~MASK, memory_order_relaxed) & MASK;
> +}
> +
> +bool
> +foo2 (_Atomic long *v, long mask)
> +{
> +  return atomic_fetch_and_explicit (v, ~mask, memory_order_relaxed) & mask;
> +}
> +
> +bool
> +foo3 (_Atomic long *v, long mask)
> +{
> +  return !(atomic_fetch_and_explicit (v, ~mask, memory_order_relaxed) & mask);
> +}
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*cmpxchg" 3 } } */
> +/* { dg-final { scan-assembler-not "btr" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr102566-13.c b/gcc/testsuite/gcc.target/i386/pr102566-13.c
> new file mode 100644
> index 00000000000..2657a2f62ae
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr102566-13.c
> @@ -0,0 +1,66 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +#include <stdatomic.h>
> +#include <stdbool.h>
> +
> +#define FOO(TYPE,MASK)                                                 \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  atomic_fetch_or_##TYPE##_##MASK (_Atomic TYPE* a)                    \
> +  {                                                                    \
> +    TYPE mask = 1 << MASK;                                             \
> +    return __atomic_fetch_or (a, mask, __ATOMIC_RELAXED) & mask;       \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  atomic_fetch_xor_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> +  {                                                                    \
> +    TYPE mask = 1 << MASK;                                             \
> +    return __atomic_fetch_xor (a, mask, __ATOMIC_RELAXED) & mask;      \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  atomic_xor_fetch_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> +  {                                                                    \
> +    TYPE mask = 1 << MASK;                                             \
> +    return __atomic_xor_fetch (a, mask, __ATOMIC_RELAXED) & mask;      \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  atomic_fetch_and_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> +  {                                                                    \
> +    TYPE mask = 1 << MASK;                                             \
> +    return __atomic_fetch_and (a, ~mask, __ATOMIC_RELAXED) & mask;     \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  sync_fetch_and_or_##TYPE##_##MASK (_Atomic TYPE* a)                  \
> +  {                                                                    \
> +    TYPE mask = 1 << MASK;                                             \
> +    return __sync_fetch_and_or (a, mask) & mask;                       \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  sync_fetch_and_xor_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> +  {                                                                    \
> +    TYPE mask = 1 << MASK;                                             \
> +    return __sync_fetch_and_xor (a, mask) & mask;                      \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  sync_xor_and_fetch_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> +  {                                                                    \
> +    TYPE mask = 1 << MASK;                                             \
> +    return __sync_xor_and_fetch (a, mask) & mask;                      \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  sync_fetch_and_and_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> +  {                                                                    \
> +    TYPE mask = 1 << MASK;                                             \
> +    return __sync_fetch_and_and (a, ~mask) & mask;                     \
> +  }                                                                    \
> +
> +FOO(short, 0);
> +FOO(short, 7);
> +FOO(short, 15);
> +FOO(int, 0);
> +FOO(int, 15);
> +FOO(int, 31);
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*bts" 12 } } */
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btc" 24 } } */
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btr" 12 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr102566-14.c b/gcc/testsuite/gcc.target/i386/pr102566-14.c
> new file mode 100644
> index 00000000000..24681c1da18
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr102566-14.c
> @@ -0,0 +1,65 @@
> +/* { dg-do compile { target { ! ia32 } } } */
> +/* { dg-options "-O2" } */
> +#include <stdatomic.h>
> +#include <stdbool.h>
> +typedef long long int64;
> +
> +#define FOO(TYPE,MASK)                                                 \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  atomic_fetch_or_##TYPE##_##MASK (_Atomic TYPE* a)                    \
> +  {                                                                    \
> +    TYPE mask = 1ll << MASK;                                           \
> +    return __atomic_fetch_or (a, mask, __ATOMIC_RELAXED) & mask;       \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  atomic_fetch_xor_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> +  {                                                                    \
> +    TYPE mask = 1ll << MASK;                                           \
> +    return __atomic_fetch_xor (a, mask, __ATOMIC_RELAXED) & mask;      \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  atomic_xor_fetch_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> +  {                                                                    \
> +    TYPE mask = 1ll << MASK;                                           \
> +    return __atomic_xor_fetch (a, mask, __ATOMIC_RELAXED) & mask;      \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  atomic_fetch_and_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> +  {                                                                    \
> +    TYPE mask = 1ll << MASK;                                           \
> +    return __atomic_fetch_and (a, ~mask, __ATOMIC_RELAXED) & mask;     \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  sync_fetch_and_or_##TYPE##_##MASK (_Atomic TYPE* a)                  \
> +  {                                                                    \
> +    TYPE mask = 1ll << MASK;                                           \
> +    return __sync_fetch_and_or (a, mask) & mask;                       \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  sync_fetch_and_xor_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> +  {                                                                    \
> +    TYPE mask = 1ll << MASK;                                           \
> +    return __sync_fetch_and_xor (a, mask) & mask;                      \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  sync_xor_and_fetch_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> +  {                                                                    \
> +    TYPE mask = 1ll << MASK;                                           \
> +    return __sync_xor_and_fetch (a, mask) & mask;                      \
> +  }                                                                    \
> +  __attribute__((noinline,noclone)) TYPE                               \
> +  sync_fetch_and_and_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> +  {                                                                    \
> +    TYPE mask = 1ll << MASK;                                           \
> +    return __sync_fetch_and_and (a, ~mask) & mask;                     \
> +  }                                                                    \
> +
> +
> +FOO(int64, 0);
> +FOO(int64, 32);
> +FOO(int64, 63);
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*bts" 6 } } */
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btc" 12 } } */
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btr" 6 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/pr102566-1a.c b/gcc/testsuite/gcc.target/i386/pr102566-1a.c
> new file mode 100644
> index 00000000000..a915de354e5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr102566-1a.c
> @@ -0,0 +1,188 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +void bar (void);
> +
> +__attribute__((noinline, noclone)) int
> +f1 (int *a, int bit)
> +{
> +  int mask = 1 << bit;
> +  return (__sync_fetch_and_or (a, mask) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f2 (int *a, int bit)
> +{
> +  int mask = 1 << bit;
> +  int t1 = __atomic_fetch_or (a, mask, __ATOMIC_RELAXED);
> +  int t2 = t1 & mask;
> +  return t2 != 0;
> +}
> +
> +__attribute__((noinline, noclone)) long int
> +f3 (long int *a, int bit)
> +{
> +  long int mask = 1l << bit;
> +  return (__atomic_fetch_or (a, mask, __ATOMIC_SEQ_CST) & mask) == 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f4 (int *a)
> +{
> +  int mask = 1 << 7;
> +  return (__sync_fetch_and_or (a, mask) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f5 (int *a)
> +{
> +  int mask = 1 << 13;
> +  return (__atomic_fetch_or (a, mask, __ATOMIC_RELAXED) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f6 (int *a)
> +{
> +  int mask = 1 << 0;
> +  return (__atomic_fetch_or (a, mask, __ATOMIC_SEQ_CST) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) void
> +f7 (int *a, int bit)
> +{
> +  int mask = 1 << bit;
> +  if ((__sync_fetch_and_xor (a, mask) & mask) != 0)
> +    bar ();
> +}
> +
> +__attribute__((noinline, noclone)) void
> +f8 (int *a, int bit)
> +{
> +  int mask = 1 << bit;
> +  if ((__atomic_fetch_xor (a, mask, __ATOMIC_RELAXED) & mask) == 0)
> +    bar ();
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f9 (int *a, int bit)
> +{
> +  int mask = 1 << bit;
> +  return (__atomic_fetch_xor (a, mask, __ATOMIC_SEQ_CST) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f10 (int *a)
> +{
> +  int mask = 1 << 7;
> +  return (__sync_fetch_and_xor (a, mask) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f11 (int *a)
> +{
> +  int mask = 1 << 13;
> +  return (__atomic_fetch_xor (a, mask, __ATOMIC_RELAXED) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f12 (int *a)
> +{
> +  int mask = 1 << 0;
> +  return (__atomic_fetch_xor (a, mask, __ATOMIC_SEQ_CST) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f13 (int *a, int bit)
> +{
> +  int mask = 1 << bit;
> +  return (__sync_fetch_and_and (a, ~mask) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f14 (int *a, int bit)
> +{
> +  int mask = 1 << bit;
> +  return (__atomic_fetch_and (a, ~mask, __ATOMIC_RELAXED) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f15 (int *a, int bit)
> +{
> +  int mask = 1 << bit;
> +  return (__atomic_fetch_and (a, ~mask, __ATOMIC_SEQ_CST) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f16 (int *a)
> +{
> +  int mask = 1 << 7;
> +  return (__sync_fetch_and_and (a, ~mask) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f17 (int *a)
> +{
> +  int mask = 1 << 13;
> +  return (__atomic_fetch_and (a, ~mask, __ATOMIC_RELAXED) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) int
> +f18 (int *a)
> +{
> +  int mask = 1 << 0;
> +  return (__atomic_fetch_and (a, ~mask, __ATOMIC_SEQ_CST) & mask) != 0;
> +}
> +
> +__attribute__((noinline, noclone)) long int
> +f19 (long int *a, int bit)
> </cut>



-- 
BR,
Hongtao


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [TCWG CI] Regression caused by gcc: Improve integer bit test on __atomic_fetch_[or|and]_* returns
  2021-11-11  1:22 ` [TCWG CI] Regression caused by gcc: Improve integer bit test on __atomic_fetch_[or|and]_* returns Hongtao Liu
@ 2021-11-11  8:55   ` Hongtao Liu
  0 siblings, 0 replies; 2+ messages in thread
From: Hongtao Liu @ 2021-11-11  8:55 UTC (permalink / raw)
  To: ci_notify; +Cc: liuhongt, gcc-regression

On Thu, Nov 11, 2021 at 9:22 AM Hongtao Liu <crazylht@gmail.com> wrote:
>
> On Thu, Nov 11, 2021 at 12:09 AM ci_notify--- via Gcc-regression
> <gcc-regression@gcc.gnu.org> wrote:
> >
> > [TCWG CI] Regression caused by gcc: Improve integer bit test on __atomic_fetch_[or|and]_* returns:
> > commit fb161782545224f55ba26ba663889c5e6e9a04d1
> > Author: liuhongt <hongtao.liu@intel.com>
> >
> >     Improve integer bit test on __atomic_fetch_[or|and]_* returns
> >
> > Results regressed to
> > # reset_artifacts:
> > -10
> > # true:
> > 0
> > # build_abe binutils:
> > 1
> > # build_abe stage1:
> > 2
> > # build_abe linux:
> > 3
> > # First few build errors in logs:
> > # 00:00:51 pthread_cancel.c:60:1: error: type mismatch in binary expression
> > # 00:00:51 pthread_cancel.c:60:1: internal compiler error: verify_gimple failed
> > # 00:00:51 make[2]: *** [../o-iterator.mk:9: /home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/builds/x86_64-pc-linux-gnu/aarch64-linux-gnu/glibc-glibc.git~master/nptl/pthread_cancel.o] Error 1
> > # 00:00:52 make[1]: *** [Makefile:483: nptl/subdir_lib] Error 2
> > # 00:00:52 make: *** [Makefile:9: all] Error 2
> >
> It seems there's ICE when using gcc to build glibc, what's the
> configure for building glibc?
I reproduced, open https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103184.
> > from
> > # reset_artifacts:
> > -10
> > # true:
> > 0
> > # build_abe binutils:
> > 1
> > # build_abe stage1:
> > 2
> > # build_abe linux:
> > 3
> > # build_abe glibc:
> > 4
> > # build_abe stage2:
> > 5
> >
> > THIS IS THE END OF INTERESTING STUFF.  BELOW ARE LINKS TO BUILDS, REPRODUCTION INSTRUCTIONS, AND THE RAW COMMIT.
> >
> > This commit has regressed these CI configurations:
> >  - tcwg_gnu_cross_build/master-aarch64
> >
> > First_bad build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/build-fb161782545224f55ba26ba663889c5e6e9a04d1/
> > Last_good build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/build-f15ad1e3f9488a31abf1c122bd186c1a3d2a5dbc/
> > Baseline build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/build-baseline/
> > Even more details: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/
> >
> > Reproduce builds:
> > <cut>
> > mkdir investigate-gcc-fb161782545224f55ba26ba663889c5e6e9a04d1
> > cd investigate-gcc-fb161782545224f55ba26ba663889c5e6e9a04d1
> >
> > # Fetch scripts
> > git clone https://git.linaro.org/toolchain/jenkins-scripts
> >
> > # Fetch manifests and test.sh script
> > mkdir -p artifacts/manifests
> > curl -o artifacts/manifests/build-baseline.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/manifests/build-baseline.sh --fail
> > curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/manifests/build-parameters.sh --fail
> > curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/6/artifact/artifacts/test.sh --fail
> > chmod +x artifacts/test.sh
> >
> > # Reproduce the baseline build (build all pre-requisites)
> > ./jenkins-scripts/tcwg_gnu-build.sh @@ artifacts/manifests/build-baseline.sh
> >
> > # Save baseline build state (which is then restored in artifacts/test.sh)
> > mkdir -p ./bisect
> > rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /gcc/ ./ ./bisect/baseline/
> >
> > cd gcc
> >
> > # Reproduce first_bad build
> > git checkout --detach fb161782545224f55ba26ba663889c5e6e9a04d1
> > ../artifacts/test.sh
> >
> > # Reproduce last_good build
> > git checkout --detach f15ad1e3f9488a31abf1c122bd186c1a3d2a5dbc
> > ../artifacts/test.sh
> >
> > cd ..
> > </cut>
> >
> > Full commit (up to 1000 lines):
> > <cut>
> > commit fb161782545224f55ba26ba663889c5e6e9a04d1
> > Author: liuhongt <hongtao.liu@intel.com>
> > Date:   Mon Oct 25 13:59:51 2021 +0800
> >
> >     Improve integer bit test on __atomic_fetch_[or|and]_* returns
> >
> >     commit adedd5c173388ae505470df152b9cb3947339566
> >     Author: Jakub Jelinek <jakub@redhat.com>
> >     Date:   Tue May 3 13:37:25 2016 +0200
> >
> >         re PR target/49244 (__sync or __atomic builtins will not emit 'lock bts/btr/btc')
> >
> >     optimized bit test on __atomic_fetch_or_* and __atomic_fetch_and_* returns
> >     with lock bts/btr/btc by turning
> >
> >       mask_2 = 1 << cnt_1;
> >       _4 = __atomic_fetch_or_* (ptr_6, mask_2, _3);
> >       _5 = _4 & mask_2;
> >
> >     into
> >
> >       _4 = ATOMIC_BIT_TEST_AND_SET (ptr_6, cnt_1, 0, _3);
> >       _5 = _4;
> >
> >     and
> >
> >       mask_6 = 1 << bit_5(D);
> >       _1 = ~mask_6;
> >       _2 = __atomic_fetch_and_4 (v_8(D), _1, 0);
> >       _3 = _2 & mask_6;
> >       _4 = _3 != 0;
> >
> >     into
> >
> >       mask_6 = 1 << bit_5(D);
> >       _1 = ~mask_6;
> >       _11 = .ATOMIC_BIT_TEST_AND_RESET (v_8(D), bit_5(D), 1, 0);
> >       _4 = _11 != 0;
> >
> >     But it failed to optimize many equivalent, but slighly different cases:
> >
> >     1.
> >       _1 = __atomic_fetch_or_4 (ptr_6, 1, _3);
> >       _4 = (_Bool) _1;
> >     2.
> >       _1 = __atomic_fetch_and_4 (ptr_6, ~1, _3);
> >       _4 = (_Bool) _1;
> >     3.
> >       _1 = __atomic_fetch_or_4 (ptr_6, 1, _3);
> >       _7 = ~_1;
> >       _5 = (_Bool) _7;
> >     4.
> >       _1 = __atomic_fetch_and_4 (ptr_6, ~1, _3);
> >       _7 = ~_1;
> >       _5 = (_Bool) _7;
> >     5.
> >       _1 = __atomic_fetch_or_4 (ptr_6, 1, _3);
> >       _2 = (int) _1;
> >       _7 = ~_2;
> >       _5 = (_Bool) _7;
> >     6.
> >       _1 = __atomic_fetch_and_4 (ptr_6, ~1, _3);
> >       _2 = (int) _1;
> >       _7 = ~_2;
> >       _5 = (_Bool) _7;
> >     7.
> >       _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
> >       _5 = (signed int) _1;
> >       _4 = _5 < 0;
> >     8.
> >       _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
> >       _5 = (signed int) _1;
> >       _4 = _5 < 0;
> >     9.
> >       _1 = 1 << bit_4(D);
> >       mask_5 = (unsigned int) _1;
> >       _2 = __atomic_fetch_or_4 (v_7(D), mask_5, 0);
> >       _3 = _2 & mask_5;
> >     10.
> >       mask_7 = 1 << bit_6(D);
> >       _1 = ~mask_7;
> >       _2 = (unsigned int) _1;
> >       _3 = __atomic_fetch_and_4 (v_9(D), _2, 0);
> >       _4 = (int) _3;
> >       _5 = _4 & mask_7;
> >
> >     We make
> >
> >       mask_2 = 1 << cnt_1;
> >       _4 = __atomic_fetch_or_* (ptr_6, mask_2, _3);
> >       _5 = _4 & mask_2;
> >
> >     and
> >
> >       mask_6 = 1 << bit_5(D);
> >       _1 = ~mask_6;
> >       _2 = __atomic_fetch_and_4 (v_8(D), _1, 0);
> >       _3 = _2 & mask_6;
> >       _4 = _3 != 0;
> >
> >     the canonical forms for this optimization and transform cases 1-9 to the
> >     equivalent canonical form.  For cases 10 and 11, we simply remove the cast
> >     before __atomic_fetch_or_4/__atomic_fetch_and_4 with
> >
> >       _1 = 1 << bit_4(D);
> >       _2 = __atomic_fetch_or_4 (v_7(D), _1, 0);
> >       _3 = _2 & _1;
> >
> >     and
> >
> >       mask_7 = 1 << bit_6(D);
> >       _1 = ~mask_7;
> >       _3 = __atomic_fetch_and_4 (v_9(D), _1, 0);
> >       _6 = _3 & mask_7;
> >       _5 = (int) _6;
> >
> >     2021-11-04  H.J. Lu  <hongjiu.lu@intel.com>
> >                 Hongtao Liu  <hongtao.liu@intel.com>
> >     gcc/
> >
> >             PR middle-end/102566
> >             * match.pd (nop_atomic_bit_test_and_p): New match.
> >             * tree-ssa-ccp.c (convert_atomic_bit_not): New function.
> >             (gimple_nop_atomic_bit_test_and_p): New prototype.
> >             (optimize_atomic_bit_test_and): Transform equivalent, but slighly
> >             different cases to their canonical forms.
> >
> >     gcc/testsuite/
> >
> >             PR middle-end/102566
> >             * g++.target/i386/pr102566-1.C: New test.
> >             * g++.target/i386/pr102566-2.C: Likewise.
> >             * g++.target/i386/pr102566-3.C: Likewise.
> >             * g++.target/i386/pr102566-4.C: Likewise.
> >             * g++.target/i386/pr102566-5a.C: Likewise.
> >             * g++.target/i386/pr102566-5b.C: Likewise.
> >             * g++.target/i386/pr102566-6a.C: Likewise.
> >             * g++.target/i386/pr102566-6b.C: Likewise.
> >             * gcc.target/i386/pr102566-1a.c: Likewise.
> >             * gcc.target/i386/pr102566-1b.c: Likewise.
> >             * gcc.target/i386/pr102566-2.c: Likewise.
> >             * gcc.target/i386/pr102566-3a.c: Likewise.
> >             * gcc.target/i386/pr102566-3b.c: Likewise.
> >             * gcc.target/i386/pr102566-4.c: Likewise.
> >             * gcc.target/i386/pr102566-5.c: Likewise.
> >             * gcc.target/i386/pr102566-6.c: Likewise.
> >             * gcc.target/i386/pr102566-7.c: Likewise.
> >             * gcc.target/i386/pr102566-8a.c: Likewise.
> >             * gcc.target/i386/pr102566-8b.c: Likewise.
> >             * gcc.target/i386/pr102566-9a.c: Likewise.
> >             * gcc.target/i386/pr102566-9b.c: Likewise.
> >             * gcc.target/i386/pr102566-10a.c: Likewise.
> >             * gcc.target/i386/pr102566-10b.c: Likewise.
> >             * gcc.target/i386/pr102566-11.c: Likewise.
> >             * gcc.target/i386/pr102566-12.c: Likewise.
> >             * gcc.target/i386/pr102566-13.c: New test.
> >             * gcc.target/i386/pr102566-14.c: New test.
> > ---
> >  gcc/match.pd                                 | 103 ++++++
> >  gcc/testsuite/g++.target/i386/pr102566-1.C   |  31 ++
> >  gcc/testsuite/g++.target/i386/pr102566-2.C   |  31 ++
> >  gcc/testsuite/g++.target/i386/pr102566-3.C   |  31 ++
> >  gcc/testsuite/g++.target/i386/pr102566-4.C   |  29 ++
> >  gcc/testsuite/g++.target/i386/pr102566-5a.C  |  31 ++
> >  gcc/testsuite/g++.target/i386/pr102566-5b.C  |  31 ++
> >  gcc/testsuite/g++.target/i386/pr102566-6a.C  |  31 ++
> >  gcc/testsuite/g++.target/i386/pr102566-6b.C  |  31 ++
> >  gcc/testsuite/gcc.target/i386/pr102566-10a.c |  15 +
> >  gcc/testsuite/gcc.target/i386/pr102566-10b.c |  15 +
> >  gcc/testsuite/gcc.target/i386/pr102566-11.c  |  28 ++
> >  gcc/testsuite/gcc.target/i386/pr102566-12.c  |  28 ++
> >  gcc/testsuite/gcc.target/i386/pr102566-13.c  |  66 ++++
> >  gcc/testsuite/gcc.target/i386/pr102566-14.c  |  65 ++++
> >  gcc/testsuite/gcc.target/i386/pr102566-1a.c  | 188 +++++++++++
> >  gcc/testsuite/gcc.target/i386/pr102566-1b.c  | 107 +++++++
> >  gcc/testsuite/gcc.target/i386/pr102566-2.c   |  32 ++
> >  gcc/testsuite/gcc.target/i386/pr102566-3a.c  |  15 +
> >  gcc/testsuite/gcc.target/i386/pr102566-3b.c  |  15 +
> >  gcc/testsuite/gcc.target/i386/pr102566-4.c   |  15 +
> >  gcc/testsuite/gcc.target/i386/pr102566-5.c   |  15 +
> >  gcc/testsuite/gcc.target/i386/pr102566-6.c   |  32 ++
> >  gcc/testsuite/gcc.target/i386/pr102566-7.c   |  30 ++
> >  gcc/testsuite/gcc.target/i386/pr102566-8a.c  |  32 ++
> >  gcc/testsuite/gcc.target/i386/pr102566-8b.c  |  32 ++
> >  gcc/testsuite/gcc.target/i386/pr102566-9a.c  |  32 ++
> >  gcc/testsuite/gcc.target/i386/pr102566-9b.c  |  32 ++
> >  gcc/tree-ssa-ccp.c                           | 456 ++++++++++++++++++++++++---
> >  29 files changed, 1557 insertions(+), 42 deletions(-)
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index 7826af1998a..a319aefa808 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -105,6 +105,39 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >  (define_operator_list COND_TERNARY
> >    IFN_COND_FMA IFN_COND_FMS IFN_COND_FNMA IFN_COND_FNMS)
> >
> > +/* __atomic_fetch_or_*, __atomic_fetch_xor_*, __atomic_xor_fetch_*  */
> > +(define_operator_list ATOMIC_FETCH_OR_XOR_N
> > +  BUILT_IN_ATOMIC_FETCH_OR_1 BUILT_IN_ATOMIC_FETCH_OR_2
> > +  BUILT_IN_ATOMIC_FETCH_OR_4 BUILT_IN_ATOMIC_FETCH_OR_8
> > +  BUILT_IN_ATOMIC_FETCH_OR_16
> > +  BUILT_IN_ATOMIC_FETCH_XOR_1 BUILT_IN_ATOMIC_FETCH_XOR_2
> > +  BUILT_IN_ATOMIC_FETCH_XOR_4 BUILT_IN_ATOMIC_FETCH_XOR_8
> > +  BUILT_IN_ATOMIC_FETCH_XOR_16
> > +  BUILT_IN_ATOMIC_XOR_FETCH_1 BUILT_IN_ATOMIC_XOR_FETCH_2
> > +  BUILT_IN_ATOMIC_XOR_FETCH_4 BUILT_IN_ATOMIC_XOR_FETCH_8
> > +  BUILT_IN_ATOMIC_XOR_FETCH_16)
> > +/* __sync_fetch_and_or_*, __sync_fetch_and_xor_*, __sync_xor_and_fetch_*  */
> > +(define_operator_list SYNC_FETCH_OR_XOR_N
> > +  BUILT_IN_SYNC_FETCH_AND_OR_1 BUILT_IN_SYNC_FETCH_AND_OR_2
> > +  BUILT_IN_SYNC_FETCH_AND_OR_4 BUILT_IN_SYNC_FETCH_AND_OR_8
> > +  BUILT_IN_SYNC_FETCH_AND_OR_16
> > +  BUILT_IN_SYNC_FETCH_AND_XOR_1 BUILT_IN_SYNC_FETCH_AND_XOR_2
> > +  BUILT_IN_SYNC_FETCH_AND_XOR_4 BUILT_IN_SYNC_FETCH_AND_XOR_8
> > +  BUILT_IN_SYNC_FETCH_AND_XOR_16
> > +  BUILT_IN_SYNC_XOR_AND_FETCH_1 BUILT_IN_SYNC_XOR_AND_FETCH_2
> > +  BUILT_IN_SYNC_XOR_AND_FETCH_4 BUILT_IN_SYNC_XOR_AND_FETCH_8
> > +  BUILT_IN_SYNC_XOR_AND_FETCH_16)
> > +/* __atomic_fetch_and_*.  */
> > +(define_operator_list ATOMIC_FETCH_AND_N
> > +  BUILT_IN_ATOMIC_FETCH_AND_1 BUILT_IN_ATOMIC_FETCH_AND_2
> > +  BUILT_IN_ATOMIC_FETCH_AND_4 BUILT_IN_ATOMIC_FETCH_AND_8
> > +  BUILT_IN_ATOMIC_FETCH_AND_16)
> > +/* __sync_fetch_and_and_*.  */
> > +(define_operator_list SYNC_FETCH_AND_AND_N
> > +  BUILT_IN_SYNC_FETCH_AND_AND_1 BUILT_IN_SYNC_FETCH_AND_AND_2
> > +  BUILT_IN_SYNC_FETCH_AND_AND_4 BUILT_IN_SYNC_FETCH_AND_AND_8
> > +  BUILT_IN_SYNC_FETCH_AND_AND_16)
> > +
> >  /* With nop_convert? combine convert? and view_convert? in one pattern
> >     plus conditionalize on tree_nop_conversion_p conversions.  */
> >  (match (nop_convert @0)
> > @@ -3976,6 +4009,76 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >    (vec_cond @0 (op! @3 @1) (op! @3 @2))))
> >  #endif
> >
> > +#if GIMPLE
> > +(match (nop_atomic_bit_test_and_p @0 @1 @4)
> > + (bit_and (nop_convert?@4 (ATOMIC_FETCH_OR_XOR_N @2 INTEGER_CST@0 @3))
> > +          INTEGER_CST@1)
> > + (with {
> > +        int ibit = tree_log2 (@0);
> > +        int ibit2 = tree_log2 (@1);
> > +       }
> > +  (if (ibit == ibit2
> > +      && ibit >= 0))))
> > +
> > +(match (nop_atomic_bit_test_and_p @0 @1 @3)
> > + (bit_and (nop_convert?@3 (SYNC_FETCH_OR_XOR_N @2 INTEGER_CST@0))
> > +         INTEGER_CST@1)
> > + (with {
> > +        int ibit = tree_log2 (@0);
> > +        int ibit2 = tree_log2 (@1);
> > +       }
> > +  (if (ibit == ibit2
> > +      && ibit >= 0))))
> > +
> > +(match (nop_atomic_bit_test_and_p @0 @0 @4)
> > + (bit_and:c
> > +  (nop_convert?@4
> > +   (ATOMIC_FETCH_OR_XOR_N @2 (nop_convert? (lshift@0 integer_onep@5 @6)) @3))
> > +  @0))
> > +
> > +(match (nop_atomic_bit_test_and_p @0 @0 @4)
> > + (bit_and:c
> > +  (nop_convert?@4
> > +   (SYNC_FETCH_OR_XOR_N @2 (nop_convert? (lshift@0 integer_onep@3 @5))))
> > +  @0))
> > +
> > +(match (nop_atomic_bit_test_and_p @0 @1 @3)
> > + (bit_and@4 (nop_convert?@3 (ATOMIC_FETCH_AND_N @2 INTEGER_CST@0 @5))
> > +           INTEGER_CST@1)
> > + (with {
> > +        int ibit = wi::exact_log2 (wi::zext (wi::bit_not (wi::to_wide (@0)),
> > +                                             TYPE_PRECISION(type)));
> > +        int ibit2 = tree_log2 (@1);
> > +       }
> > +  (if (ibit == ibit2
> > +      && ibit >= 0))))
> > +
> > +(match (nop_atomic_bit_test_and_p @0 @1 @3)
> > + (bit_and@4
> > +  (nop_convert?@3 (SYNC_FETCH_AND_AND_N @2 INTEGER_CST@0))
> > +  INTEGER_CST@1)
> > + (with {
> > +        int ibit = wi::exact_log2 (wi::zext (wi::bit_not (wi::to_wide (@0)),
> > +                                             TYPE_PRECISION(type)));
> > +        int ibit2 = tree_log2 (@1);
> > +       }
> > +  (if (ibit == ibit2
> > +      && ibit >= 0))))
> > +
> > +(match (nop_atomic_bit_test_and_p @0 @0 @3)
> > + (bit_and:c
> > +  (nop_convert?@3
> > +   (ATOMIC_FETCH_AND_N @2 (nop_convert? (bit_not (lshift@0 integer_onep@6 @7))) @5))
> > +   @0))
> > +
> > +(match (nop_atomic_bit_test_and_p @0 @0 @3)
> > + (bit_and:c
> > +  (nop_convert?@3
> > +   (SYNC_FETCH_AND_AND_N @2 (nop_convert? (bit_not (lshift@0 integer_onep@6 @7)))))
> > +   @0))
> > +
> > +#endif
> > +
> >  /* (v ? w : 0) ? a : b is just (v & w) ? a : b
> >     Currently disabled after pass lvec because ARM understands
> >     VEC_COND_EXPR<v==w,-1,0> but not a plain v==w fed to BIT_IOR_EXPR.  */
> > diff --git a/gcc/testsuite/g++.target/i386/pr102566-1.C b/gcc/testsuite/g++.target/i386/pr102566-1.C
> > new file mode 100644
> > index 00000000000..94a66d717cc
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/i386/pr102566-1.C
> > @@ -0,0 +1,31 @@
> > +/* { dg-do compile { target c++11 } } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <atomic>
> > +
> > +bool
> > +tbit0 (std::atomic<int> &i)
> > +{
> > +#define BIT (1 << 0)
> > +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit30 (std::atomic<int> &i)
> > +{
> > +#define BIT (1 << 30)
> > +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit31 (std::atomic<int> &i)
> > +{
> > +#define BIT (1 << 31)
> > +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btsl" 3 } } */
> > +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> > diff --git a/gcc/testsuite/g++.target/i386/pr102566-2.C b/gcc/testsuite/g++.target/i386/pr102566-2.C
> > new file mode 100644
> > index 00000000000..4f2aea961c2
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/i386/pr102566-2.C
> > @@ -0,0 +1,31 @@
> > +/* { dg-do compile { target c++11 } } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <atomic>
> > +
> > +bool
> > +tbit0 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 0)
> > +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit30 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 30)
> > +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit31 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 31)
> > +  return i.fetch_or(BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btsl" 3 } } */
> > +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> > diff --git a/gcc/testsuite/g++.target/i386/pr102566-3.C b/gcc/testsuite/g++.target/i386/pr102566-3.C
> > new file mode 100644
> > index 00000000000..e88921dd155
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/i386/pr102566-3.C
> > @@ -0,0 +1,31 @@
> > +/* { dg-do compile { target c++11 } } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <atomic>
> > +
> > +bool
> > +tbit0 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 0)
> > +  return !(i.fetch_or(BIT, std::memory_order_relaxed) & BIT);
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit30 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 30)
> > +  return !(i.fetch_or(BIT, std::memory_order_relaxed) & BIT);
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit31 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 31)
> > +  return !(i.fetch_or(BIT, std::memory_order_relaxed) & BIT);
> > +#undef BIT
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btsl" 3 } } */
> > +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> > diff --git a/gcc/testsuite/g++.target/i386/pr102566-4.C b/gcc/testsuite/g++.target/i386/pr102566-4.C
> > new file mode 100644
> > index 00000000000..44d1362ac2e
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/i386/pr102566-4.C
> > @@ -0,0 +1,29 @@
> > +/* { dg-do compile { target c++11 } } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <atomic>
> > +
> > +typedef int __attribute__ ((mode (__word__))) int_type;
> > +
> > +#define BIT (1 << 0)
> > +
> > +bool
> > +tbit0 (std::atomic<int_type> &i)
> > +{
> > +  return i.fetch_or(BIT, std::memory_order_relaxed) & ~1;
> > +}
> > +
> > +bool
> > +tbit30 (std::atomic<int_type> &i)
> > +{
> > +  return i.fetch_or(BIT, std::memory_order_relaxed) & ~2;
> > +}
> > +
> > +bool
> > +tbit31 (std::atomic<int_type> &i)
> > +{
> > +  return i.fetch_or(BIT, std::memory_order_relaxed) & ~4;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*cmpxchg" 3 } } */
> > +/* { dg-final { scan-assembler-not "bts" } } */
> > diff --git a/gcc/testsuite/g++.target/i386/pr102566-5a.C b/gcc/testsuite/g++.target/i386/pr102566-5a.C
> > new file mode 100644
> > index 00000000000..f9595bee2ab
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/i386/pr102566-5a.C
> > @@ -0,0 +1,31 @@
> > +/* { dg-do compile { target c++11 } } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <atomic>
> > +
> > +bool
> > +tbit0 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 0)
> > +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit30 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 30)
> > +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit31 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 31)
> > +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrl" 3 } } */
> > +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> > diff --git a/gcc/testsuite/g++.target/i386/pr102566-5b.C b/gcc/testsuite/g++.target/i386/pr102566-5b.C
> > new file mode 100644
> > index 00000000000..d917b27a918
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/i386/pr102566-5b.C
> > @@ -0,0 +1,31 @@
> > +/* { dg-do compile { target { c++11 && { ! ia32 } } } } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <atomic>
> > +
> > +bool
> > +tbit0 (std::atomic<unsigned long long> &i)
> > +{
> > +#define BIT (1ll << 0)
> > +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit30 (std::atomic<unsigned long long> &i)
> > +{
> > +#define BIT (1ll << 30)
> > +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit31 (std::atomic<unsigned long long> &i)
> > +{
> > +#define BIT (1ll << 63)
> > +  return i.fetch_and(~BIT, std::memory_order_relaxed) & BIT;
> > +#undef BIT
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrq" 3 } } */
> > +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> > diff --git a/gcc/testsuite/g++.target/i386/pr102566-6a.C b/gcc/testsuite/g++.target/i386/pr102566-6a.C
> > new file mode 100644
> > index 00000000000..01d495eda23
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/i386/pr102566-6a.C
> > @@ -0,0 +1,31 @@
> > +/* { dg-do compile { target c++11 } } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <atomic>
> > +
> > +bool
> > +tbit0 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 0)
> > +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit30 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 30)
> > +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit31 (std::atomic<unsigned int> &i)
> > +{
> > +#define BIT (1 << 31)
> > +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> > +#undef BIT
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrl" 3 } } */
> > +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> > diff --git a/gcc/testsuite/g++.target/i386/pr102566-6b.C b/gcc/testsuite/g++.target/i386/pr102566-6b.C
> > new file mode 100644
> > index 00000000000..adc11fcbf2d
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/i386/pr102566-6b.C
> > @@ -0,0 +1,31 @@
> > +/* { dg-do compile { target { c++11 && { ! ia32 } } } } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <atomic>
> > +
> > +bool
> > +tbit0 (std::atomic<unsigned long long> &i)
> > +{
> > +#define BIT (1ll << 0)
> > +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit30 (std::atomic<unsigned long long> &i)
> > +{
> > +#define BIT (1ll << 30)
> > +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> > +#undef BIT
> > +}
> > +
> > +bool
> > +tbit31 (std::atomic<unsigned long long> &i)
> > +{
> > +#define BIT (1ll << 63)
> > +  return !(i.fetch_and(~BIT, std::memory_order_relaxed) & BIT);
> > +#undef BIT
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrq" 3 } } */
> > +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/pr102566-10a.c b/gcc/testsuite/gcc.target/i386/pr102566-10a.c
> > new file mode 100644
> > index 00000000000..1c1f86a9659
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr102566-10a.c
> > @@ -0,0 +1,15 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <stdatomic.h>
> > +#include <stdbool.h>
> > +
> > +bool
> > +foo (_Atomic int *v, int bit)
> > +{
> > +  int mask = 1 << bit;
> > +  return atomic_fetch_and_explicit (v, ~mask, memory_order_relaxed) & mask;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrl" 1 } } */
> > +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/pr102566-10b.c b/gcc/testsuite/gcc.target/i386/pr102566-10b.c
> > new file mode 100644
> > index 00000000000..0bf39824ea6
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr102566-10b.c
> > @@ -0,0 +1,15 @@
> > +/* { dg-do compile { target { ! ia32 } } } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <stdatomic.h>
> > +#include <stdbool.h>
> > +
> > +bool
> > +foo (_Atomic long long int *v, int bit)
> > +{
> > +  long long int mask = 1ll << bit;
> > +  return atomic_fetch_and_explicit (v, ~mask, memory_order_relaxed) & mask;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrq" 1 } } */
> > +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/pr102566-11.c b/gcc/testsuite/gcc.target/i386/pr102566-11.c
> > new file mode 100644
> > index 00000000000..2c8f8c4e59a
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr102566-11.c
> > @@ -0,0 +1,28 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <stdatomic.h>
> > +#include <stdbool.h>
> > +
> > +#define MASK 0x1234
> > +
> > +bool
> > +foo1 (_Atomic int *v)
> > +{
> > +  return atomic_fetch_or_explicit (v, MASK, memory_order_relaxed) & MASK;
> > +}
> > +
> > +bool
> > +foo2 (_Atomic unsigned int *v, int mask)
> > +{
> > +  return atomic_fetch_or_explicit (v, mask, memory_order_relaxed) & mask;
> > +}
> > +
> > +bool
> > +foo3 (_Atomic unsigned int *v, int mask)
> > +{
> > +  return !(atomic_fetch_or_explicit (v, mask, memory_order_relaxed) & mask);
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*cmpxchg" 3 } } */
> > +/* { dg-final { scan-assembler-not "bts" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/pr102566-12.c b/gcc/testsuite/gcc.target/i386/pr102566-12.c
> > new file mode 100644
> > index 00000000000..4603a77612c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr102566-12.c
> > @@ -0,0 +1,28 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <stdatomic.h>
> > +#include <stdbool.h>
> > +
> > +#define MASK 0x1234
> > +
> > +bool
> > +foo1 (_Atomic long *v)
> > +{
> > +  return atomic_fetch_and_explicit (v, ~MASK, memory_order_relaxed) & MASK;
> > +}
> > +
> > +bool
> > +foo2 (_Atomic long *v, long mask)
> > +{
> > +  return atomic_fetch_and_explicit (v, ~mask, memory_order_relaxed) & mask;
> > +}
> > +
> > +bool
> > +foo3 (_Atomic long *v, long mask)
> > +{
> > +  return !(atomic_fetch_and_explicit (v, ~mask, memory_order_relaxed) & mask);
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*cmpxchg" 3 } } */
> > +/* { dg-final { scan-assembler-not "btr" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/pr102566-13.c b/gcc/testsuite/gcc.target/i386/pr102566-13.c
> > new file mode 100644
> > index 00000000000..2657a2f62ae
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr102566-13.c
> > @@ -0,0 +1,66 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2" } */
> > +#include <stdatomic.h>
> > +#include <stdbool.h>
> > +
> > +#define FOO(TYPE,MASK)                                                 \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  atomic_fetch_or_##TYPE##_##MASK (_Atomic TYPE* a)                    \
> > +  {                                                                    \
> > +    TYPE mask = 1 << MASK;                                             \
> > +    return __atomic_fetch_or (a, mask, __ATOMIC_RELAXED) & mask;       \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  atomic_fetch_xor_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> > +  {                                                                    \
> > +    TYPE mask = 1 << MASK;                                             \
> > +    return __atomic_fetch_xor (a, mask, __ATOMIC_RELAXED) & mask;      \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  atomic_xor_fetch_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> > +  {                                                                    \
> > +    TYPE mask = 1 << MASK;                                             \
> > +    return __atomic_xor_fetch (a, mask, __ATOMIC_RELAXED) & mask;      \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  atomic_fetch_and_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> > +  {                                                                    \
> > +    TYPE mask = 1 << MASK;                                             \
> > +    return __atomic_fetch_and (a, ~mask, __ATOMIC_RELAXED) & mask;     \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  sync_fetch_and_or_##TYPE##_##MASK (_Atomic TYPE* a)                  \
> > +  {                                                                    \
> > +    TYPE mask = 1 << MASK;                                             \
> > +    return __sync_fetch_and_or (a, mask) & mask;                       \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  sync_fetch_and_xor_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> > +  {                                                                    \
> > +    TYPE mask = 1 << MASK;                                             \
> > +    return __sync_fetch_and_xor (a, mask) & mask;                      \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  sync_xor_and_fetch_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> > +  {                                                                    \
> > +    TYPE mask = 1 << MASK;                                             \
> > +    return __sync_xor_and_fetch (a, mask) & mask;                      \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  sync_fetch_and_and_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> > +  {                                                                    \
> > +    TYPE mask = 1 << MASK;                                             \
> > +    return __sync_fetch_and_and (a, ~mask) & mask;                     \
> > +  }                                                                    \
> > +
> > +FOO(short, 0);
> > +FOO(short, 7);
> > +FOO(short, 15);
> > +FOO(int, 0);
> > +FOO(int, 15);
> > +FOO(int, 31);
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*bts" 12 } } */
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btc" 24 } } */
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btr" 12 } } */
> > +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/pr102566-14.c b/gcc/testsuite/gcc.target/i386/pr102566-14.c
> > new file mode 100644
> > index 00000000000..24681c1da18
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr102566-14.c
> > @@ -0,0 +1,65 @@
> > +/* { dg-do compile { target { ! ia32 } } } */
> > +/* { dg-options "-O2" } */
> > +#include <stdatomic.h>
> > +#include <stdbool.h>
> > +typedef long long int64;
> > +
> > +#define FOO(TYPE,MASK)                                                 \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  atomic_fetch_or_##TYPE##_##MASK (_Atomic TYPE* a)                    \
> > +  {                                                                    \
> > +    TYPE mask = 1ll << MASK;                                           \
> > +    return __atomic_fetch_or (a, mask, __ATOMIC_RELAXED) & mask;       \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  atomic_fetch_xor_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> > +  {                                                                    \
> > +    TYPE mask = 1ll << MASK;                                           \
> > +    return __atomic_fetch_xor (a, mask, __ATOMIC_RELAXED) & mask;      \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  atomic_xor_fetch_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> > +  {                                                                    \
> > +    TYPE mask = 1ll << MASK;                                           \
> > +    return __atomic_xor_fetch (a, mask, __ATOMIC_RELAXED) & mask;      \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  atomic_fetch_and_##TYPE##_##MASK (_Atomic TYPE* a)                   \
> > +  {                                                                    \
> > +    TYPE mask = 1ll << MASK;                                           \
> > +    return __atomic_fetch_and (a, ~mask, __ATOMIC_RELAXED) & mask;     \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  sync_fetch_and_or_##TYPE##_##MASK (_Atomic TYPE* a)                  \
> > +  {                                                                    \
> > +    TYPE mask = 1ll << MASK;                                           \
> > +    return __sync_fetch_and_or (a, mask) & mask;                       \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  sync_fetch_and_xor_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> > +  {                                                                    \
> > +    TYPE mask = 1ll << MASK;                                           \
> > +    return __sync_fetch_and_xor (a, mask) & mask;                      \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  sync_xor_and_fetch_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> > +  {                                                                    \
> > +    TYPE mask = 1ll << MASK;                                           \
> > +    return __sync_xor_and_fetch (a, mask) & mask;                      \
> > +  }                                                                    \
> > +  __attribute__((noinline,noclone)) TYPE                               \
> > +  sync_fetch_and_and_##TYPE##_##MASK (_Atomic TYPE* a)                 \
> > +  {                                                                    \
> > +    TYPE mask = 1ll << MASK;                                           \
> > +    return __sync_fetch_and_and (a, ~mask) & mask;                     \
> > +  }                                                                    \
> > +
> > +
> > +FOO(int64, 0);
> > +FOO(int64, 32);
> > +FOO(int64, 63);
> > +
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*bts" 6 } } */
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btc" 12 } } */
> > +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btr" 6 } } */
> > +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/pr102566-1a.c b/gcc/testsuite/gcc.target/i386/pr102566-1a.c
> > new file mode 100644
> > index 00000000000..a915de354e5
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr102566-1a.c
> > @@ -0,0 +1,188 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2" } */
> > +
> > +void bar (void);
> > +
> > +__attribute__((noinline, noclone)) int
> > +f1 (int *a, int bit)
> > +{
> > +  int mask = 1 << bit;
> > +  return (__sync_fetch_and_or (a, mask) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f2 (int *a, int bit)
> > +{
> > +  int mask = 1 << bit;
> > +  int t1 = __atomic_fetch_or (a, mask, __ATOMIC_RELAXED);
> > +  int t2 = t1 & mask;
> > +  return t2 != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) long int
> > +f3 (long int *a, int bit)
> > +{
> > +  long int mask = 1l << bit;
> > +  return (__atomic_fetch_or (a, mask, __ATOMIC_SEQ_CST) & mask) == 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f4 (int *a)
> > +{
> > +  int mask = 1 << 7;
> > +  return (__sync_fetch_and_or (a, mask) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f5 (int *a)
> > +{
> > +  int mask = 1 << 13;
> > +  return (__atomic_fetch_or (a, mask, __ATOMIC_RELAXED) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f6 (int *a)
> > +{
> > +  int mask = 1 << 0;
> > +  return (__atomic_fetch_or (a, mask, __ATOMIC_SEQ_CST) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) void
> > +f7 (int *a, int bit)
> > +{
> > +  int mask = 1 << bit;
> > +  if ((__sync_fetch_and_xor (a, mask) & mask) != 0)
> > +    bar ();
> > +}
> > +
> > +__attribute__((noinline, noclone)) void
> > +f8 (int *a, int bit)
> > +{
> > +  int mask = 1 << bit;
> > +  if ((__atomic_fetch_xor (a, mask, __ATOMIC_RELAXED) & mask) == 0)
> > +    bar ();
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f9 (int *a, int bit)
> > +{
> > +  int mask = 1 << bit;
> > +  return (__atomic_fetch_xor (a, mask, __ATOMIC_SEQ_CST) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f10 (int *a)
> > +{
> > +  int mask = 1 << 7;
> > +  return (__sync_fetch_and_xor (a, mask) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f11 (int *a)
> > +{
> > +  int mask = 1 << 13;
> > +  return (__atomic_fetch_xor (a, mask, __ATOMIC_RELAXED) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f12 (int *a)
> > +{
> > +  int mask = 1 << 0;
> > +  return (__atomic_fetch_xor (a, mask, __ATOMIC_SEQ_CST) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f13 (int *a, int bit)
> > +{
> > +  int mask = 1 << bit;
> > +  return (__sync_fetch_and_and (a, ~mask) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f14 (int *a, int bit)
> > +{
> > +  int mask = 1 << bit;
> > +  return (__atomic_fetch_and (a, ~mask, __ATOMIC_RELAXED) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f15 (int *a, int bit)
> > +{
> > +  int mask = 1 << bit;
> > +  return (__atomic_fetch_and (a, ~mask, __ATOMIC_SEQ_CST) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f16 (int *a)
> > +{
> > +  int mask = 1 << 7;
> > +  return (__sync_fetch_and_and (a, ~mask) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f17 (int *a)
> > +{
> > +  int mask = 1 << 13;
> > +  return (__atomic_fetch_and (a, ~mask, __ATOMIC_RELAXED) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) int
> > +f18 (int *a)
> > +{
> > +  int mask = 1 << 0;
> > +  return (__atomic_fetch_and (a, ~mask, __ATOMIC_SEQ_CST) & mask) != 0;
> > +}
> > +
> > +__attribute__((noinline, noclone)) long int
> > +f19 (long int *a, int bit)
> > </cut>
>
>
>
> --
> BR,
> Hongtao



-- 
BR,
Hongtao


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-11-11  8:48 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <129273368.6511.1636560535186@jenkins.jenkins>
2021-11-11  1:22 ` [TCWG CI] Regression caused by gcc: Improve integer bit test on __atomic_fetch_[or|and]_* returns Hongtao Liu
2021-11-11  8:55   ` Hongtao Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).