https://gcc.gnu.org/g:1df85ac92c10919d0da88853d4e9522574c41002

commit 1df85ac92c10919d0da88853d4e9522574c41002
Author: Alexandre Oliva <ol...@gnu.org>
Date:   Thu Nov 21 22:36:47 2024 -0300

    fold_truth_andor: test narrowing conversions

Diff:
---
 gcc/gimple-fold.cc                   |  4 ++--
 gcc/match.pd                         |  4 ++++
 gcc/testsuite/gcc.dg/field-merge-8.c | 25 +++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/field-merge-9.c | 36 ++++++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 1abf09470567..73a22ad3be59 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -7387,7 +7387,7 @@ maybe_fold_comparisons_from_match_pd (tree type, enum 
tree_code code,
   return NULL_TREE;
 }
 
-extern bool gimple_nop_convert (tree, tree *, tree (*)(tree));
+extern bool gimple_any_convert (tree, tree *, tree (*)(tree));
 extern bool gimple_bit_and_cst (tree, tree *, tree (*)(tree));
 extern bool gimple_bit_xor_cst (tree, tree *, tree (*)(tree));
 extern bool gimple_rshift_cst (tree, tree *, tree (*)(tree));
@@ -7403,7 +7403,7 @@ is_cast_p (tree *name)
   tree type = 0;
   tree res_ops[1];
 
-  while (gimple_nop_convert (*name, res_ops, follow_all_ssa_edges))
+  while (gimple_any_convert (*name, res_ops, follow_all_ssa_edges))
     {
       if (!type)
        type = TREE_TYPE (*name);
diff --git a/gcc/match.pd b/gcc/match.pd
index 598624086bd5..9cdb47fafa01 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -202,6 +202,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (bit_xor_cst@0 @1 @2))
 
 /* These are used by ifcombine fold_truth_andor.  */
+(match (any_convert @0)
+ (convert @0))
+(match (any_convert @0)
+ (view_convert @0))
 (match (bit_and_cst @0 @1)
  (bit_and @0 uniform_integer_cst_p@1))
 (match (rshift_cst @0 @1)
diff --git a/gcc/testsuite/gcc.dg/field-merge-8.c 
b/gcc/testsuite/gcc.dg/field-merge-8.c
new file mode 100644
index 000000000000..ae270e10070e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/field-merge-8.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O" } */
+
+/* Check that conversions are not thrown away.  */
+
+struct s {
+  unsigned char a;
+  unsigned short b;
+} __attribute__ ((aligned (4)));
+
+struct s p = { 42, 0xfe };
+struct s q = { 42, 0xfe | (2 << (__CHAR_BIT__ - 1)) };
+
+void f (void) {
+  if (0
+      || p.a != q.a
+      || (unsigned char)p.b != (unsigned char)q.b
+      )
+    __builtin_abort ();
+}
+
+int main () {
+  f ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/field-merge-9.c 
b/gcc/testsuite/gcc.dg/field-merge-9.c
new file mode 100644
index 000000000000..25a8b1fa9b0a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/field-merge-9.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-O" } */
+
+/* Check that conversions and selections of similar bit ranges across different
+   types don't prevent combination.  */
+
+struct s1 {
+  unsigned char b[2];
+  unsigned char a;
+} __attribute__ ((aligned (4)));
+
+struct s2 {
+  unsigned short b;
+  unsigned char a;
+} __attribute__ ((aligned (4)));
+
+static const char le = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ? 1 : 0;
+
+struct s1 p = { { -!le , -le }, 42 };
+struct s2 q = { (le
+                ? -2 << (__CHAR_BIT__ - 1)
+                : -1 & ((1 << (__CHAR_BIT__ - 1) << 1) - 1)), 42 };
+
+void f (void) {
+  if (0
+      || p.a != q.a
+      || p.b[!le] != (unsigned char)q.b
+      || p.b[le] != (char)((q.b >> (__CHAR_BIT__ - 1)) >> 1)
+      )
+    __builtin_abort ();
+}
+
+int main () {
+  f ();
+  return 0;
+}

Reply via email to