diff mbox series

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

Message ID 20221102190819.862078-1-hjl.tools@gmail.com
State New
Headers show
Series Extend optimization for integer bit test on __atomic_fetch_[or|and]_* | expand

Commit Message

H.J. Lu Nov. 2, 2022, 7:08 p.m. UTC
Extend optimization for

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

to

_1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _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

Comments

Richard Biener Nov. 5, 2022, 11:21 a.m. UTC | #1
On Wed, Nov 2, 2022 at 8:09 PM H.J. Lu via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Extend optimization for
>
> _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
> _5 = (signed int) _1;
> _4 = _5 >= 0;
>
> to
>
> _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _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 00000000000..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 <atomic>
> +
> +template<uint32_t b>
> +void lock_bts(std::atomic<uint32_t> &a) { while (!(a.fetch_or(b) & b)); }
> +template<uint32_t b>
> +void lock_btr(std::atomic<uint32_t> &a) { while (a.fetch_and(~b) & b); }
> +template<uint32_t b>
> +void lock_btc(std::atomic<uint32_t> &a) { while (a.fetch_xor(b) & b); }
> +template void lock_bts<1U<<30>(std::atomic<uint32_t> &a);
> +template void lock_btr<1U<<30>(std::atomic<uint32_t> &a);
> +template void lock_btc<1U<<30>(std::atomic<uint32_t> &a);
> +template void lock_bts<1U<<31>(std::atomic<uint32_t> &a);
> +template void lock_btr<1U<<31>(std::atomic<uint32_t> &a);
> +template void lock_btc<1U<<31>(std::atomic<uint32_t> &a);
> +
> +/* { 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, &use_p, &use_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 (!integer_zerop (cmp_rhs2))
>                     return false;
>
> @@ -3547,6 +3582,14 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
>                          _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
>                          _6 = _1 & 0x80000000;
>                          _4 = _6 != 0 or _6 == 0;
> +                        and convert
> +                        _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
> +                        _5 = (signed int) _1;
> +                        if (_5 < 0 or _5 >= 0)
> +                        to
> +                        _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
> +                        _6 = _1 & 0x80000000;
> +                        if (_6 != 0 or _6 == 0)
>                        */
>                       and_mask = build_int_cst (TREE_TYPE (use_rhs),
>                                                 highest);
> @@ -3567,6 +3610,14 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
>                          _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
>                          _6 = _1 & 0x80000000;
>                          _4 = _6 != 0 or _6 == 0;
> +                        and convert
> +                        _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
> +                        _5 = (signed int) _1;
> +                        if (_5 < 0 or _5 >= 0)
> +                        to
> +                        _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
> +                        _6 = _1 & 0x80000000;
> +                        if (_6 != 0 or _6 == 0)
>                        */
>                     }
>                   var = make_ssa_name (TREE_TYPE (use_rhs));
> @@ -3577,11 +3628,14 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
>                   gsi = gsi_for_stmt (use_nop_stmt);
>                   gsi_insert_before (&gsi, g, GSI_NEW_STMT);
>                   use_stmt = g;
> -                 g = gimple_build_assign (use_nop_lhs,
> -                                          (rhs_code == GE_EXPR
> -                                           ? EQ_EXPR : NE_EXPR),
> -                                          var,
> -                                          build_zero_cst (TREE_TYPE (use_rhs)));
> +                 rhs_code = rhs_code == GE_EXPR ? EQ_EXPR : NE_EXPR;
> +                 tree const_zero = build_zero_cst (TREE_TYPE (use_rhs));
> +                 if (use_nop_lhs)
> +                   g = gimple_build_assign (use_nop_lhs, rhs_code,
> +                                            var, const_zero);
> +                 else
> +                   g = gimple_build_cond (rhs_code, var, const_zero,
> +                                          nullptr, nullptr);
>                   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
>                   gsi = gsi_for_stmt (use_nop_stmt);
>                   gsi_remove (&gsi, true);
> --
> 2.37.3
>
diff mbox series

Patch

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 00000000000..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 <atomic>
+
+template<uint32_t b>
+void lock_bts(std::atomic<uint32_t> &a) { while (!(a.fetch_or(b) & b)); }
+template<uint32_t b>
+void lock_btr(std::atomic<uint32_t> &a) { while (a.fetch_and(~b) & b); }
+template<uint32_t b>
+void lock_btc(std::atomic<uint32_t> &a) { while (a.fetch_xor(b) & b); }
+template void lock_bts<1U<<30>(std::atomic<uint32_t> &a);
+template void lock_btr<1U<<30>(std::atomic<uint32_t> &a);
+template void lock_btc<1U<<30>(std::atomic<uint32_t> &a);
+template void lock_bts<1U<<31>(std::atomic<uint32_t> &a);
+template void lock_btr<1U<<31>(std::atomic<uint32_t> &a);
+template void lock_btc<1U<<31>(std::atomic<uint32_t> &a);
+
+/* { 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, &use_p, &use_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 (!integer_zerop (cmp_rhs2))
 		    return false;
 
@@ -3547,6 +3582,14 @@  optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
 			 _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
 			 _6 = _1 & 0x80000000;
 			 _4 = _6 != 0 or _6 == 0;
+			 and convert
+			 _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
+			 _5 = (signed int) _1;
+			 if (_5 < 0 or _5 >= 0)
+			 to
+			 _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
+			 _6 = _1 & 0x80000000;
+			 if (_6 != 0 or _6 == 0)
 		       */
 		      and_mask = build_int_cst (TREE_TYPE (use_rhs),
 						highest);
@@ -3567,6 +3610,14 @@  optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
 			 _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
 			 _6 = _1 & 0x80000000;
 			 _4 = _6 != 0 or _6 == 0;
+			 and convert
+			 _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
+			 _5 = (signed int) _1;
+			 if (_5 < 0 or _5 >= 0)
+			 to
+			 _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
+			 _6 = _1 & 0x80000000;
+			 if (_6 != 0 or _6 == 0)
 		       */
 		    }
 		  var = make_ssa_name (TREE_TYPE (use_rhs));
@@ -3577,11 +3628,14 @@  optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
 		  gsi = gsi_for_stmt (use_nop_stmt);
 		  gsi_insert_before (&gsi, g, GSI_NEW_STMT);
 		  use_stmt = g;
-		  g = gimple_build_assign (use_nop_lhs,
-					   (rhs_code == GE_EXPR
-					    ? EQ_EXPR : NE_EXPR),
-					   var,
-					   build_zero_cst (TREE_TYPE (use_rhs)));
+		  rhs_code = rhs_code == GE_EXPR ? EQ_EXPR : NE_EXPR;
+		  tree const_zero = build_zero_cst (TREE_TYPE (use_rhs));
+		  if (use_nop_lhs)
+		    g = gimple_build_assign (use_nop_lhs, rhs_code,
+					     var, const_zero);
+		  else
+		    g = gimple_build_cond (rhs_code, var, const_zero,
+					   nullptr, nullptr);
 		  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
 		  gsi = gsi_for_stmt (use_nop_stmt);
 		  gsi_remove (&gsi, true);