Re: [PATCH] Extend optimization for integer bit test on __atomic_fetch_[or|and]_*
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]_*
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