From: Kyrylo Tkachov <[email protected]>

For 0 < C < prec the fold

  .CTZ (x, V) >= C -> (x & ((1 << C) - 1)) == 0
  .CTZ (x, V) < C -> (x & ((1 << C) - 1)) != 0

applies when V < 0 or V >= prec.  For x = 0 the bit test is true, so the
fold is correct only if V >= C.  For

  _1 = .CTZ (x_4(D), -1);
  _2 = _1 >= 3;

and x = 0, _2 is 0, but the fold gives

  _5 = x_4(D) & 7;
  _2 = _5 == 0;

which is 1.  gcn, and rs6000 without TARGET_CTZ and TARGET_POPCNTD,
define -1 as the value at zero, so __builtin_ctzg (x, -1) >= 3 is
miscompiled there.  The condition comes from r12-151 (PR95527).

Fold only if V >= C.

Bootstrapped and tested on aarch64-none-linux-gnu and x86_64-linux.

gcc/ChangeLog:

        * match.pd (.CTZ (x, V) >= C -> (x & ((1 << C) - 1)) == 0):
        Require that the value at zero is at least C.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c: New test.

Signed-off-by: Kyrylo Tkachov <[email protected]>
---
 gcc/match.pd                                  |  2 +-
 .../gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c | 69 +++++++++++++++++++
 2 files changed, 70 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 68b910e337b..ebbe24c0aea 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -11421,7 +11421,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       (if (val >= prec)
        (if (ok && zero_val < val)
        { constant_boolean_node (cmp != EQ_EXPR, type); })
-       (if (ok && (zero_val < 0 || zero_val >= prec))
+       (if (ok && zero_val >= val)
        (cmp (bit_and @0 { wide_int_to_tree (type0,
                                             wi::mask (val, false, prec)); })
             { build_zero_cst (type0); })))))))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c
new file mode 100644
index 00000000000..5a159ec2d08
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c
@@ -0,0 +1,69 @@
+/* .CTZ (X, V) >= C becomes (X & ((1 << C) - 1)) == 0 only if V >= C,
+   because the bit test is true for X = 0.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target int32 } */
+/* { dg-require-effective-target ctz_ifn } */
+/* { dg-options "-O2 -fgimple -fdump-tree-optimized" } */
+
+/* .CTZ (0, -1) is -1, which is smaller than 3.  */
+
+int __GIMPLE (ssa)
+gem1 (unsigned int x)
+{
+  int _1;
+  _Bool _2;
+  int _3;
+
+  __BB(2):
+  _1 = .CTZ (x_4(D), -1);
+  _2 = _1 >= 3;
+  _3 = (int) _2;
+  return _3;
+}
+
+int __GIMPLE (ssa)
+ltm1 (unsigned int x)
+{
+  int _1;
+  _Bool _2;
+  int _3;
+
+  __BB(2):
+  _1 = .CTZ (x_4(D), -1);
+  _2 = _1 < 3;
+  _3 = (int) _2;
+  return _3;
+}
+
+/* .CTZ (0, 32) is 32, which is not smaller than 3.  */
+
+int __GIMPLE (ssa)
+ge32 (unsigned int x)
+{
+  int _1;
+  _Bool _2;
+  int _3;
+
+  __BB(2):
+  _1 = .CTZ (x_4(D), 32);
+  _2 = _1 >= 3;
+  _3 = (int) _2;
+  return _3;
+}
+
+int __GIMPLE (ssa)
+lt32 (unsigned int x)
+{
+  int _1;
+  _Bool _2;
+  int _3;
+
+  __BB(2):
+  _1 = .CTZ (x_4(D), 32);
+  _2 = _1 < 3;
+  _3 = (int) _2;
+  return _3;
+}
+
+/* { dg-final { scan-tree-dump-times "\\.CTZ" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " & 7;" 2 "optimized" } } */
-- 
2.54.0 (Apple Git-157)

Reply via email to