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"  } } */

Reply via email to