https://gcc.gnu.org/g:50df2b188450457580b5ff4ac1d524fcc74de9bc
commit r16-6727-g50df2b188450457580b5ff4ac1d524fcc74de9bc Author: Andrew Pinski <[email protected]> Date: Sat Jan 10 23:17:12 2026 -0800 match: Simplify `(T1)(a bit_op (T2)b)` to `((T1)a bit_op b)` When b is T1 type and truncating from T2 [PR122845] This adds the simpliciation of: ``` <unnamed-signed:3> _1; _2 = (signed char) _1; _3 = _2 ^ -47; _4 = (<unnamed-signed:3>) _3; ``` to: ``` <unnamed-signed:3> _n; _4 = _1 ^ -47; ``` This also fixes PR 122843 by optimizing out the xor such that we get: ``` _1 = b.a; _21 = (<unnamed-signed:3>) t_23(D); // t_23 in the original testcase was 200 so this is reduced to 0 _5 = _1 ^ _21; # .MEM_24 = VDEF <.MEM_13> b.a = _5; ``` And then there is no cast catch this pattern: `(bit_xor (convert1? (bit_xor:c @0 @1)) (convert2? (bit_xor:c @0 @2)))` As we get: ``` _21 = (<unnamed-signed:3>) t_23(D); _5 = _1 ^ _21; _22 = (<unnamed-signed:3>) t_23(D); _7 = _5 ^ _22; _25 = (<unnamed-signed:3>) t_23(D); _8 = _7 ^ _25; _26 = (<unnamed-signed:3>) t_23(D); _9 = _7 ^ _26; ``` After unrolling and then fre will optimize away all of those xor. Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/122845 PR tree-optimization/122843 gcc/ChangeLog: * match.pd (`(T1)(a bit_op (T2)b)`): Also simplify if T1 is the same type as b and T2 is wider type than T1. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/bitops-12.c: New test. * gcc.dg/tree-ssa/bitops-13.c: New test. * gcc.dg/store_merging_18.c: xfail store merging. Signed-off-by: Andrew Pinski <[email protected]> Diff: --- gcc/match.pd | 10 +++++++++- gcc/testsuite/gcc.dg/store_merging_18.c | 3 ++- gcc/testsuite/gcc.dg/tree-ssa/bitops-12.c | 18 ++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/bitops-13.c | 18 ++++++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/gcc/match.pd b/gcc/match.pd index 08d0810e9865..c339762b90c4 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2323,7 +2323,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && !POINTER_TYPE_P (TREE_TYPE (@0)) && TREE_CODE (TREE_TYPE (@0)) != OFFSET_TYPE && TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type)) - (bitop:type (convert @0) (convert @1))))) + (bitop:type (convert @0) (convert @1)) + /* Similar as above, but the outer and inner most types match + and it was widening cast; replacing 2 casts with only one. */ + (if (GIMPLE + && INTEGRAL_TYPE_P (type) + && INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && types_match (type, TREE_TYPE (@0)) + && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (type)) + (bitop:type @0 (convert @1)))))) (for bitop (bit_and bit_ior) rbitop (bit_ior bit_and) diff --git a/gcc/testsuite/gcc.dg/store_merging_18.c b/gcc/testsuite/gcc.dg/store_merging_18.c index fdff6b4d8121..546c17dc7c45 100644 --- a/gcc/testsuite/gcc.dg/store_merging_18.c +++ b/gcc/testsuite/gcc.dg/store_merging_18.c @@ -1,7 +1,8 @@ /* PR tree-optimization/83843 */ /* { dg-do run } */ /* { dg-options "-O2 -fno-tree-vectorize -fdump-tree-store-merging" } */ -/* { dg-final { scan-tree-dump-times "Merging successful" 3 "store-merging" { target { store_merge && { ! arm*-*-* } } } } } */ +/* xfailed after PR 122845, see PR 123541 ( */ +/* { dg-final { scan-tree-dump-times "Merging successful" 3 "store-merging" { target { store_merge && { ! arm*-*-* } } xfail *-*-* } } } */ __attribute__((noipa)) void foo (unsigned char *buf, unsigned char *tab) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitops-12.c b/gcc/testsuite/gcc.dg/tree-ssa/bitops-12.c new file mode 100644 index 000000000000..50d8dc2180fc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bitops-12.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized-raw" } */ +/* PR tree-optimization/122845 */ + +struct s1 +{ + signed f1:3; +}; +struct s1 p; +void f(void) +{ + p.f1 ^= -47; + p.f1 ^= -47; +} + +/* There should be no gimple stmts left except for return. + That is the ^ has been optimized away. */ +/* { dg-final { scan-tree-dump-not "gimple_assign <" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitops-13.c b/gcc/testsuite/gcc.dg/tree-ssa/bitops-13.c new file mode 100644 index 000000000000..ecf697382671 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bitops-13.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized-raw" } */ +/* PR tree-optimization/122845 */ + +int f(signed char a, int b) +{ + int aa = a; + int bb = b; + aa &= bb; + signed char t = aa; + aa = t; + aa &= bb; + t = aa; + return t; +} + +/* There should be only 1 bit_and_expr left as both ands are the same. */ +/* { dg-final { scan-tree-dump-times "bit_and_expr, " 1 "optimized" } } */
