Hi!

When one (or both) IVs have extend_mode wider than mode, but step doesn't
fit into mode (the IV is
(subreg:MODE (plus:EXTEND_MODE base (mult:EXTEND_MODE i step)) lowpart)
), such as for EXTEND_MODE SImode, MODE QImode and step e.g. 129, 128, 256
or 517, iv_number_of_iterations can create invalid rtl.  I think it is safe
to just use the lowpart subreg of the step.  The second hunk isn't enough,
we use iv0.step resp. iv1.step directly in several other places in the
routine, and the first hunk IMHO isn't enough either, if for the above
extend_mode SI and mode QI iv1.step is 128, the first hunk will make -128 out of
it, but then we negate it and get step 128 out of it again, not valid QImode
CONST_INT, and use it e.g. as argument to UMOD.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Or shall we just punt (either as done by H.J. in the PR, or in
iv_number_of_iterations if the steps aren't valid mode CONST_INTs)?

2013-01-03  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/55838
        * loop-iv.c (iv_number_of_iterations): Call lowpart_subreg on
        iv0.step, iv1.step and step.

        * gcc.dg/pr55838.c: New test.

--- gcc/loop-iv.c.jj    2012-10-22 08:42:25.000000000 +0200
+++ gcc/loop-iv.c       2013-01-02 09:17:42.215591646 +0100
@@ -2406,6 +2406,9 @@ iv_number_of_iterations (struct loop *lo
       iv1.step = const0_rtx;
     }
 
+  iv0.step = lowpart_subreg (mode, iv0.step, comp_mode);
+  iv1.step = lowpart_subreg (mode, iv1.step, comp_mode);
+
   /* This is either infinite loop or the one that ends immediately, depending
      on initial values.  Unswitching should remove this kind of conditions.  */
   if (iv0.step == const0_rtx && iv1.step == const0_rtx)
@@ -2516,6 +2519,7 @@ iv_number_of_iterations (struct loop *lo
        step = simplify_gen_unary (NEG, comp_mode, iv1.step, comp_mode);
       else
        step = iv0.step;
+      step = lowpart_subreg (mode, step, comp_mode);
       delta = simplify_gen_binary (MINUS, comp_mode, iv1.base, iv0.base);
       delta = lowpart_subreg (mode, delta, comp_mode);
       delta = simplify_gen_binary (UMOD, mode, delta, step);
--- gcc/testsuite/gcc.dg/pr55838.c.jj   2012-11-17 15:43:17.572007394 +0100
+++ gcc/testsuite/gcc.dg/pr55838.c      2013-01-02 21:09:55.726580313 +0100
@@ -0,0 +1,13 @@
+/* PR rtl-optimization/55838 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -funroll-loops" } */
+
+int a;
+unsigned char c;
+
+void
+f (void)
+{
+  while (c++ < 2)
+    c = a += 129;
+}

        Jakub

Reply via email to