match.pd: Fix up FFS -> CTZ + 1 optimization [PR97325]
authorJakub Jelinek <jakub@redhat.com>
Fri, 9 Oct 2020 08:16:57 +0000 (10:16 +0200)
committerJakub Jelinek <jakub@redhat.com>
Fri, 9 Oct 2020 08:18:41 +0000 (10:18 +0200)
And no testcase was included, I'm including one below.

Anyway, this PR and the other CTZ related discussions led me to discover a
bug I've made earlier, CLZ/CTZ builtins have unsigned arguments and e.g.
both the vr-values.cc and now gimple-range.cc code heavily relies on that,
but __builtin_ffs has a signed operand and this optimization was incorrectly
making the operand signed too, so I guess it would greatly confuse VRP in
some cases.

2020-10-09  Jakub Jelinek  <jakub@redhat.com>

PR tree-optimization/97325
* match.pd (FFS(nonzero) -> CTZ(nonzero) + 1): Cast argument to
corresponding unsigned type.

* gcc.c-torture/execute/pr97325.c: New test.

gcc/match.pd
gcc/testsuite/gcc.c-torture/execute/pr97325.c [new file with mode: 0644]

index 952643f3c6d7a33a4631819991c7651f511ac8d3..a7032dcae29b6f9e604b1e67f30208150b0e347f 100644 (file)
@@ -6196,7 +6196,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
       && direct_internal_fn_supported_p (IFN_CTZ, TREE_TYPE (@0),
                                         OPTIMIZE_FOR_SPEED))
-  (plus (CTZ:type @0) { build_one_cst (type); })))
+  (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
+   (plus (CTZ:type (convert:utype @0)) { build_one_cst (type); }))))
 #endif
 
 (for ffs (BUILT_IN_FFS BUILT_IN_FFSL BUILT_IN_FFSLL
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr97325.c b/gcc/testsuite/gcc.c-torture/execute/pr97325.c
new file mode 100644 (file)
index 0000000..f734c85
--- /dev/null
@@ -0,0 +1,15 @@
+/* PR tree-optimization/97325 */
+
+unsigned long long
+foo (unsigned long long c)
+{
+  return c ? __builtin_ffs (-(unsigned short) c) : 0;
+}
+
+int
+main ()
+{
+  if (foo (2) != 2)
+    __builtin_abort ();
+  return 0;
+}