This is similar to PR36817, but has different reasons.

% cat x.c
void fail (void)
{
  unsigned int w[5], *wi;

  wi = &w[2];
  do {
      unsigned int x = wi[-2];
      *wi = x;
  } while (++wi < w+5);
}

% ./gcc/cc1 -O3 -quiet x.c
x.c: In function &#8216;fail&#8217;:
x.c:2: internal compiler error: in compare_values_warnv, at tree-vrp.c:772

I think the reason is that # of iterations analysis puts type-incorrect
compares into iter->may_be_zero, which is a problem because (unlike
->assumptions) this is used later by loop-unrolling to generate code
(to guard against a non-looping loop).

In this case it generates this:

Analyzing # of iterations of loop 1
  exit condition [&w[3], + , 4](no_overflow) < &w + 20
  bounds on difference of bases: -4294967275 ... 4294967295
  result:
    zero if &w[3] > (unsigned int) (&w + 20)
    # of iterations 2, bounded by 1073741823

Note the "&w[3] > (unsigned int) (&w + 20)" which has mismatching types.

It might be that only number_of_iterations_lt_to_ne needs to be changed,
I looked at other uses of fold_build* in tree-ssa-loop-niter.c and quite
some others also look at least fishy (at least those generating compares),
but they usually only set assumptions, so they might be fine for now.

In any case, this seems to work for me:
Index: tree-ssa-loop-niter.c
===================================================================
--- tree-ssa-loop-niter.c       (revision 141741)
+++ tree-ssa-loop-niter.c       (working copy)
@@ -710,7 +710,7 @@ number_of_iterations_lt_to_ne (tree type
        noloop = boolean_false_node;
       else
        noloop = fold_build2 (GT_EXPR, boolean_type_node,
-                             iv0->base,
+                             fold_convert (type1, iv0->base),
                              fold_build2 (PLUS_EXPR, type1,
                                           iv1->base, tmod));
     }
@@ -734,7 +734,7 @@ number_of_iterations_lt_to_ne (tree type
        noloop = fold_build2 (GT_EXPR, boolean_type_node,
                              fold_build2 (MINUS_EXPR, type1,
                                           iv0->base, tmod),
-                             iv1->base);
+                             fold_convert (type1, iv1->base));
     }

   if (!integer_nonzerop (assumption))

I haven't checked other versions of the compiler, but trunk at least still
has the same code.


-- 
           Summary: ICE in compare_values_warnv
           Product: gcc
           Version: 4.3.2
            Status: UNCONFIRMED
          Keywords: ice-on-valid-code
          Severity: normal
          Priority: P3
         Component: middle-end
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: matz at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38070

Reply via email to