This avoids using multiple_of_p in niter analysis when its behavior
to assume the tested expression does not invoke integer overflow
produces wrong niter analysis results.  For the cases multiple_of_p
handles power-of-two values of bottom look safe which should also be
the majority of cases we care about in addition to the constant case
now handled explicitely.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

I'm unsure how important a "perfect" solution is (rewriting
multiple_of_p), and wonder whether this solution is preferable
for now (and especially for branches).  I've not yet tried
to sanitize multiple_of_p plus use range info to prove
no-overflow where TYPE_OVERFLOW_UNDEFINED doesn't tell us
immediately.

2021-07-22  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/100499
        * tree-ssa-loop-niter.c (number_of_iterations_ne): Restrict
        multiple_of_p queries to power-of-two bottoms, handle
        the all constant case inline.

        * gcc.dg/torture/pr100499-1.c: New testcase.
        * gcc.dg/torture/pr100499-2.c: Likewise.
---
 gcc/testsuite/gcc.dg/torture/pr100499-1.c | 28 +++++++++++++++++++++++
 gcc/testsuite/gcc.dg/torture/pr100499-2.c | 16 +++++++++++++
 gcc/tree-ssa-loop-niter.c                 |  8 ++++++-
 3 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr100499-1.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr100499-2.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr100499-1.c 
b/gcc/testsuite/gcc.dg/torture/pr100499-1.c
new file mode 100644
index 00000000000..97ab6051554
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr100499-1.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+typedef __UINT16_TYPE__ uint16_t;
+static uint16_t g_2823 = 0xEC75L;
+static uint16_t g_116 = 0xBC07L;
+
+static uint16_t
+safe_mul_func_uint16_t_u_u(uint16_t ui1, uint16_t ui2)
+{
+  return ((unsigned int)ui1) * ((unsigned int)ui2);
+}
+
+int main (int argc, char* argv[])
+{
+  uint16_t l_2815 = 65535UL;
+  uint16_t *l_2821 = &g_116;
+  uint16_t *l_2822 = &g_2823;
+
+lbl_2826:
+  l_2815 &= 0x9DEF1EAEL;
+  if (+(safe_mul_func_uint16_t_u_u(((*l_2821) = l_2815), (--(*l_2822)))))
+    goto lbl_2826;
+
+  if (g_2823 != 32768)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr100499-2.c 
b/gcc/testsuite/gcc.dg/torture/pr100499-2.c
new file mode 100644
index 00000000000..999f931806a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr100499-2.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+
+unsigned char ag = 55;
+unsigned i;
+int main()
+{
+  unsigned char c;
+  unsigned char a = ag;
+d:
+  c = a-- * 52;
+  if (c)
+    goto d;
+  if (a != 255)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 1b5605c26b8..c6b953c5316 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1050,7 +1050,13 @@ number_of_iterations_ne (class loop *loop, tree type, 
affine_iv *iv,
      Note, for NE_EXPR, base equals to FINAL is a special case, in
      which the loop exits immediately, and the iv does not overflow.  */
   if (!niter->control.no_overflow
-      && (integer_onep (s) || multiple_of_p (type, c, s)))
+      && (integer_onep (s)
+         || (poly_int_tree_p (c)
+             && multiple_p (wi::to_poly_widest (c), wi::to_poly_widest (s)))
+         /* ???  multiple_of_p assumes the expression 'c' does not overflow
+            but that cannot be guaranteed, so we restrict 's' to power of
+            two values where that should not be an issue.  See PR100499.  */
+         || (integer_pow2p (s) && multiple_of_p (type, c, s))))
     {
       tree t, cond, new_c, relaxed_cond = boolean_false_node;
 
-- 
2.26.2

Reply via email to