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)