tree-optimization/104519 - adjust PR100499 niter fix
authorRichard Biener <rguenther@suse.de>
Tue, 15 Feb 2022 08:40:59 +0000 (09:40 +0100)
committerRichard Biener <rguenther@suse.de>
Tue, 15 Feb 2022 10:41:42 +0000 (11:41 +0100)
The following adjusts the PR100499 niter fix to use the appropriate
types when checking whether the difference between the final and base
values of the IV are a multiple of the step.  It also gets rid of
an always false condition in multiple_of_p which lead me to a
wrong solution first.

2022-02-15  Richard Biener  <rguenther@suse.de>

PR tree-optimization/104519
* fold-const.cc (multiple_of_p): Remove never true condition.
* tree-ssa-loop-niter.cc (number_of_iterations_ne): Use
the appropriate types for determining whether the difference
of final and base is a multiple of the step.

* gcc.dg/torture/pr104519.c: New testcase.

gcc/fold-const.cc
gcc/testsuite/gcc.dg/torture/pr104519.c [new file with mode: 0644]
gcc/tree-ssa-loop-niter.cc

index 386d573..9d99396 100644 (file)
@@ -14208,11 +14208,7 @@ multiple_of_p (tree type, const_tree top, const_tree bottom, bool nowrap)
              && multiple_of_p (type, TREE_OPERAND (top, 2), bottom, nowrap));
 
     case INTEGER_CST:
-      if (TREE_CODE (bottom) != INTEGER_CST
-         || integer_zerop (bottom)
-         || (TYPE_UNSIGNED (type)
-             && (tree_int_cst_sgn (top) < 0
-                 || tree_int_cst_sgn (bottom) < 0)))
+      if (TREE_CODE (bottom) != INTEGER_CST || integer_zerop (bottom))
        return 0;
       return wi::multiple_of_p (wi::to_widest (top), wi::to_widest (bottom),
                                SIGNED);
diff --git a/gcc/testsuite/gcc.dg/torture/pr104519.c b/gcc/testsuite/gcc.dg/torture/pr104519.c
new file mode 100644 (file)
index 0000000..389c7bb
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+
+signed char a, b;
+int main()
+{
+  for (b = -7; b; b += 3)
+    if (a)
+      __builtin_abort();
+  return 0;
+}
index 318d10c..9bb5097 100644 (file)
@@ -1048,13 +1048,19 @@ number_of_iterations_ne (class loop *loop, tree type, affine_iv *iv,
      which the loop exits immediately, and the iv does not overflow.
 
      Also note, we prove condition 2) by checking base and final seperately
-     along with condition 1) or 1').  */
+     along with condition 1) or 1').  Since we ensure the difference
+     computation of c does not wrap with cond below and the adjusted s
+     will fit a signed type as well as an unsigned we can safely do
+     this using the type of the IV if it is not pointer typed.  */
+  tree mtype = type;
+  if (POINTER_TYPE_P (type))
+    mtype = niter_type;
   if (!niter->control.no_overflow
       && (integer_onep (s)
-         || (multiple_of_p (type, fold_convert (niter_type, iv->base), s,
-                            false)
-             && multiple_of_p (type, fold_convert (niter_type, final), s,
-                               false))))
+         || (multiple_of_p (mtype, fold_convert (mtype, iv->base),
+                            fold_convert (mtype, s), false)
+             && multiple_of_p (mtype, fold_convert (mtype, final),
+                               fold_convert (mtype, s), false))))
     {
       tree t, cond, relaxed_cond = boolean_false_node;