[PATCH] Fix PR41919, wrong-code with VRP

View: New views
1 Messages — Rating Filter:   Alert me  

[PATCH] Fix PR41919, wrong-code with VRP

by Richard Guenther-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


This fixes PR41919, we were using compare_values without accounting
for its various results.  The testcase is somewhat fragile - it
relies on early inlining of bar and late inlining of foo, but it
currently fails at -O2 at least.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2009-11-04  Richard Guenther  <rguenther@...>

        PR tree-optimization/41919
        * tree-vrp.c (test_for_singularity): Properly compare values.

        * gcc.c-torture/execute/pr41919.c: New testcase.

Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c (revision 153852)
--- gcc/tree-vrp.c (working copy)
*************** test_for_singularity (enum tree_code con
*** 6748,6760 ****
       value range information we have for op0.  */
    if (min && max)
      {
!       if (compare_values (vr->min, min) == -1)
! min = min;
!       else
  min = vr->min;
!       if (compare_values (vr->max, max) == 1)
! max = max;
!       else
  max = vr->max;
 
        /* If the new min/max values have converged to a single value,
--- 6748,6756 ----
       value range information we have for op0.  */
    if (min && max)
      {
!       if (compare_values (vr->min, min) == 1)
  min = vr->min;
!       if (compare_values (vr->max, max) == -1)
  max = vr->max;
 
        /* If the new min/max values have converged to a single value,
Index: gcc/testsuite/gcc.c-torture/execute/pr41919.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/pr41919.c (revision 0)
--- gcc/testsuite/gcc.c-torture/execute/pr41919.c (revision 0)
***************
*** 0 ****
--- 1,39 ----
+ extern void abort (void);
+
+ #define assert(x) if(!(x)) abort()
+
+ struct S1
+ {
+   char f0;
+ };
+
+ int g_23 = 0;
+
+ static struct S1
+ foo (void)
+ {
+   int *l_100 = &g_23;
+   int **l_110 = &l_100;
+   struct S1 l_128 = { 1 };
+   assert (l_100 == &g_23);
+   assert (l_100 == &g_23);
+   assert (l_100 == &g_23);
+   assert (l_100 == &g_23);
+   assert (l_100 == &g_23);
+   assert (l_100 == &g_23);
+   assert (l_100 == &g_23);
+   return l_128;
+ }
+
+ static char bar(char si1, char si2)
+ {
+   return (si1 <= 0) ? si1 : (si2 * 2);
+ }
+ int main (void)
+ {
+   struct S1 s = foo();
+   if (bar(0x99 ^ (s.f0 && 1), 1) != -104)
+     abort ();
+   return 0;
+ }
+