Re: [PATCH] Extend optimization for integer bit test on __atomic_fetch_[or|and]_*

2022-11-05 Thread Richard Biener via Gcc-patches
On Wed, Nov 2, 2022 at 8:09 PM H.J. Lu via Gcc-patches
 wrote:
>
> Extend optimization for
>
> _1 = __atomic_fetch_or_4 (ptr_6, 0x8000, _3);
> _5 = (signed int) _1;
> _4 = _5 >= 0;
>
> to
>
> _1 = __atomic_fetch_or_4 (ptr_6, 0x8000, _3);
> _5 = (signed int) _1;
> if (_5 >= 0)

OK.

> gcc/
>
> PR middle-end/102566
> * tree-ssa-ccp.cc (optimize_atomic_bit_test_and): Also handle
> if (_5 < 0) and if (_5 >= 0).
>
> gcc/testsuite/
>
> PR middle-end/102566
> * g++.target/i386/pr102566-7.C
> ---
>  gcc/testsuite/g++.target/i386/pr102566-7.C | 22 ++
>  gcc/tree-ssa-ccp.cc| 84 ++
>  2 files changed, 91 insertions(+), 15 deletions(-)
>  create mode 100644 gcc/testsuite/g++.target/i386/pr102566-7.C
>
> diff --git a/gcc/testsuite/g++.target/i386/pr102566-7.C 
> b/gcc/testsuite/g++.target/i386/pr102566-7.C
> new file mode 100644
> index 000..ce90214f33d
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/pr102566-7.C
> @@ -0,0 +1,22 @@
> +/* { dg-do compile { target c++11 } } */
> +/* { dg-options "-O2" } */
> +
> +#include 
> +
> +template
> +void lock_bts(std::atomic ) { while (!(a.fetch_or(b) & b)); }
> +template
> +void lock_btr(std::atomic ) { while (a.fetch_and(~b) & b); }
> +template
> +void lock_btc(std::atomic ) { while (a.fetch_xor(b) & b); }
> +template void lock_bts<1U<<30>(std::atomic );
> +template void lock_btr<1U<<30>(std::atomic );
> +template void lock_btc<1U<<30>(std::atomic );
> +template void lock_bts<1U<<31>(std::atomic );
> +template void lock_btr<1U<<31>(std::atomic );
> +template void lock_btc<1U<<31>(std::atomic );
> +
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btsl" 2 } } */
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrl" 2 } } */
> +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btcl" 2 } } */
> +/* { dg-final { scan-assembler-not "cmpxchg" } } */
> diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
> index 9778e776cf2..3a4b6bc1118 100644
> --- a/gcc/tree-ssa-ccp.cc
> +++ b/gcc/tree-ssa-ccp.cc
> @@ -3471,17 +3471,35 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator 
> *gsip,
> {
>   gimple *use_nop_stmt;
>   if (!single_imm_use (use_lhs, _p, _nop_stmt)
> - || !is_gimple_assign (use_nop_stmt))
> + || (!is_gimple_assign (use_nop_stmt)
> + && gimple_code (use_nop_stmt) != GIMPLE_COND))
> return false;
> - tree use_nop_lhs = gimple_assign_lhs (use_nop_stmt);
> - rhs_code = gimple_assign_rhs_code (use_nop_stmt);
> - if (rhs_code != BIT_AND_EXPR)
> + /* Handle both
> +_4 = _5 < 0;
> +and
> +if (_5 < 0)
> +  */
> + tree use_nop_lhs = nullptr;
> + rhs_code = ERROR_MARK;
> + if (is_gimple_assign (use_nop_stmt))
> {
> - if (TREE_CODE (use_nop_lhs) == SSA_NAME
> + use_nop_lhs = gimple_assign_lhs (use_nop_stmt);
> + rhs_code = gimple_assign_rhs_code (use_nop_stmt);
> +   }
> + if (!use_nop_lhs || rhs_code != BIT_AND_EXPR)
> +   {
> + /* Also handle
> +if (_5 < 0)
> +  */
> + if (use_nop_lhs
> + && TREE_CODE (use_nop_lhs) == SSA_NAME
>   && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use_nop_lhs))
> return false;
> - if (rhs_code == BIT_NOT_EXPR)
> + if (use_nop_lhs && rhs_code == BIT_NOT_EXPR)
> {
> + /* Handle
> +_7 = ~_2;
> +  */
>   g = convert_atomic_bit_not (fn, use_nop_stmt, lhs,
>   mask);
>   if (!g)
> @@ -3512,14 +3530,31 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator 
> *gsip,
> }
>   else
> {
> - if (TREE_CODE (TREE_TYPE (use_nop_lhs)) != BOOLEAN_TYPE)
> -   return false;
> + tree cmp_rhs1, cmp_rhs2;
> + if (use_nop_lhs)
> +   {
> + /* Handle
> +_4 = _5 < 0;
> +  */
> + if (TREE_CODE (TREE_TYPE (use_nop_lhs))
> + != BOOLEAN_TYPE)
> +   return false;
> + cmp_rhs1 = gimple_assign_rhs1 (use_nop_stmt);
> + cmp_rhs2 = gimple_assign_rhs2 (use_nop_stmt);
> +   }
> + else
> +   {
> + /* Handle
> +if (_5 < 0)
> +  */
> + rhs_code = gimple_cond_code (use_nop_stmt);
> + cmp_rhs1 = gimple_cond_lhs (use_nop_stmt);
> + cmp_rhs2 = gimple_cond_rhs (use_nop_stmt);
> +   }
>   if 

[PATCH] Extend optimization for integer bit test on __atomic_fetch_[or|and]_*

2022-11-02 Thread H.J. Lu via Gcc-patches
Extend optimization for

_1 = __atomic_fetch_or_4 (ptr_6, 0x8000, _3);
_5 = (signed int) _1;
_4 = _5 >= 0;

to

_1 = __atomic_fetch_or_4 (ptr_6, 0x8000, _3);
_5 = (signed int) _1;
if (_5 >= 0)

gcc/

PR middle-end/102566
* tree-ssa-ccp.cc (optimize_atomic_bit_test_and): Also handle
if (_5 < 0) and if (_5 >= 0).

gcc/testsuite/

PR middle-end/102566
* g++.target/i386/pr102566-7.C
---
 gcc/testsuite/g++.target/i386/pr102566-7.C | 22 ++
 gcc/tree-ssa-ccp.cc| 84 ++
 2 files changed, 91 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/i386/pr102566-7.C

diff --git a/gcc/testsuite/g++.target/i386/pr102566-7.C 
b/gcc/testsuite/g++.target/i386/pr102566-7.C
new file mode 100644
index 000..ce90214f33d
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr102566-7.C
@@ -0,0 +1,22 @@
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "-O2" } */
+
+#include 
+
+template
+void lock_bts(std::atomic ) { while (!(a.fetch_or(b) & b)); }
+template
+void lock_btr(std::atomic ) { while (a.fetch_and(~b) & b); }
+template
+void lock_btc(std::atomic ) { while (a.fetch_xor(b) & b); }
+template void lock_bts<1U<<30>(std::atomic );
+template void lock_btr<1U<<30>(std::atomic );
+template void lock_btc<1U<<30>(std::atomic );
+template void lock_bts<1U<<31>(std::atomic );
+template void lock_btr<1U<<31>(std::atomic );
+template void lock_btc<1U<<31>(std::atomic );
+
+/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btsl" 2 } } */
+/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrl" 2 } } */
+/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btcl" 2 } } */
+/* { dg-final { scan-assembler-not "cmpxchg" } } */
diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
index 9778e776cf2..3a4b6bc1118 100644
--- a/gcc/tree-ssa-ccp.cc
+++ b/gcc/tree-ssa-ccp.cc
@@ -3471,17 +3471,35 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator 
*gsip,
{
  gimple *use_nop_stmt;
  if (!single_imm_use (use_lhs, _p, _nop_stmt)
- || !is_gimple_assign (use_nop_stmt))
+ || (!is_gimple_assign (use_nop_stmt)
+ && gimple_code (use_nop_stmt) != GIMPLE_COND))
return false;
- tree use_nop_lhs = gimple_assign_lhs (use_nop_stmt);
- rhs_code = gimple_assign_rhs_code (use_nop_stmt);
- if (rhs_code != BIT_AND_EXPR)
+ /* Handle both
+_4 = _5 < 0;
+and
+if (_5 < 0)
+  */
+ tree use_nop_lhs = nullptr;
+ rhs_code = ERROR_MARK;
+ if (is_gimple_assign (use_nop_stmt))
{
- if (TREE_CODE (use_nop_lhs) == SSA_NAME
+ use_nop_lhs = gimple_assign_lhs (use_nop_stmt);
+ rhs_code = gimple_assign_rhs_code (use_nop_stmt);
+   }
+ if (!use_nop_lhs || rhs_code != BIT_AND_EXPR)
+   {
+ /* Also handle
+if (_5 < 0)
+  */
+ if (use_nop_lhs
+ && TREE_CODE (use_nop_lhs) == SSA_NAME
  && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use_nop_lhs))
return false;
- if (rhs_code == BIT_NOT_EXPR)
+ if (use_nop_lhs && rhs_code == BIT_NOT_EXPR)
{
+ /* Handle
+_7 = ~_2;
+  */
  g = convert_atomic_bit_not (fn, use_nop_stmt, lhs,
  mask);
  if (!g)
@@ -3512,14 +3530,31 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator 
*gsip,
}
  else
{
- if (TREE_CODE (TREE_TYPE (use_nop_lhs)) != BOOLEAN_TYPE)
-   return false;
+ tree cmp_rhs1, cmp_rhs2;
+ if (use_nop_lhs)
+   {
+ /* Handle
+_4 = _5 < 0;
+  */
+ if (TREE_CODE (TREE_TYPE (use_nop_lhs))
+ != BOOLEAN_TYPE)
+   return false;
+ cmp_rhs1 = gimple_assign_rhs1 (use_nop_stmt);
+ cmp_rhs2 = gimple_assign_rhs2 (use_nop_stmt);
+   }
+ else
+   {
+ /* Handle
+if (_5 < 0)
+  */
+ rhs_code = gimple_cond_code (use_nop_stmt);
+ cmp_rhs1 = gimple_cond_lhs (use_nop_stmt);
+ cmp_rhs2 = gimple_cond_rhs (use_nop_stmt);
+   }
  if (rhs_code != GE_EXPR && rhs_code != LT_EXPR)
return false;
- tree cmp_rhs1 = gimple_assign_rhs1 (use_nop_stmt);
  if (use_lhs != cmp_rhs1)
return false;
- tree cmp_rhs2 = gimple_assign_rhs2 (use_nop_stmt);
  if