]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
match: Improve handling of double convert [PR117776]
authorAndrew Pinski <quic_apinski@quicinc.com>
Tue, 26 Nov 2024 00:04:21 +0000 (16:04 -0800)
committerAndrew Pinski <quic_apinski@quicinc.com>
Wed, 27 Nov 2024 18:21:46 +0000 (10:21 -0800)
For a double conversion, we will simplify it into a conversion
with an and if the outer type and inside precision matches and
the intra precision is smaller and unsigned. We should be able
to extend this to where the outer precision is larger too.
This is a good canonicalization too.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/117776
gcc/ChangeLog:

* match.pd (nested int casts): Allow for the case
where the final prec is greater than the original
prec.

gcc/testsuite/ChangeLog:

* g++.dg/vect/pr117776.cc: New test.
* gcc.dg/tree-ssa/cast-3.c: New test.

Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
gcc/match.pd
gcc/testsuite/g++.dg/vect/pr117776.cc [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/cast-3.c [new file with mode: 0644]

index 988fffb258fdf06b92b4165b4e81fb135484906d..2dd67b69cf1f51addc7e82700a0f7d73de4b06ae 100644 (file)
@@ -5450,8 +5450,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        canonicalized as bitwise and of a mask.  */
     (if (GIMPLE /* PR70366: doing this in GENERIC breaks -Wconversion.  */
         && final_int && inter_int && inside_int
-        && final_prec == inside_prec
-        && final_prec > inter_prec
+        && final_prec >= inside_prec
+        && inside_prec > inter_prec
         && inter_unsignedp)
      (convert (bit_and @0 { wide_int_to_tree
                              (inside_type,
diff --git a/gcc/testsuite/g++.dg/vect/pr117776.cc b/gcc/testsuite/g++.dg/vect/pr117776.cc
new file mode 100644 (file)
index 0000000..cbb8079
--- /dev/null
@@ -0,0 +1,62 @@
+// { dg-do compile }
+// { dg-require-effective-target vect_int }
+
+// PR tree-optimization/117776
+
+typedef __SIZE_TYPE__ size_t;
+typedef unsigned int u32;
+typedef unsigned char u8;
+
+static inline const bool
+is_even_bool(u8 n)
+{
+ return n % 2 == 0;
+}
+
+static inline const u32
+is_even_u32(u8 n)
+{
+  return n % 2 == 0;
+}
+
+static inline
+const u32 is_even_convert(u8 n)
+{
+  return is_even_bool(n);
+}
+
+u32 count_even_v1(u8 *data, size_t len)
+{
+  u32 ret = 0;
+  for (size_t i = 0; i < len; i++)
+    ret += is_even_bool(data[i]);
+  return ret;
+}
+
+u32 count_even_v2(u8 *data, size_t len)
+{
+  u32 ret = 0;
+  for (size_t i = 0; i < len; i++)
+    ret += is_even_u32(data[i]);
+  return ret;
+}
+
+u32 count_even_v3(u8 *data, size_t len)
+{
+  u32 ret = 0;
+  for (size_t i = 0; i < len; i++)
+    ret += is_even_convert(data[i]);
+  return ret;
+}
+
+u32 count_even_v4(u8 *data, size_t len)
+{
+  u32 ret = 0;
+  for (size_t i = 0; i < len; i++)
+    ret += static_cast<u32>(is_even_bool(data[i]));
+  return ret;
+}
+
+// All 4 count_even_v functions should be vectorized
+
+// { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 4 "vect" } }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cast-3.c b/gcc/testsuite/gcc.dg/tree-ssa/cast-3.c
new file mode 100644 (file)
index 0000000..37214ec
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* PR tree-optimization/117776 */
+
+/* These 2 functions should be optimized to just `return 1;`
+   as `(int)(unsigned smaller)medium` is the same as
+   `(int)medium&smaller_mask` where smaller_mask in this case is
+   either `1` (_Bool) or `0xff` (char).   */
+int f(unsigned char a)
+{
+  _Bool odd = (a & 1) != 0;
+  int odd1 = (a & 1) != 0;
+  return odd == odd1;
+}
+int g(unsigned short a)
+{
+  unsigned char b = a;
+  int d = b;
+  unsigned short c = a&0xff;
+  int e = c;
+  return d == e;
+}
+
+/* { dg-final { scan-tree-dump-times "return 1" 2 "optimized" } } */