[PATCH] Fix PR50189

2011-10-12 Thread Richard Guenther

This changes VRP to use the type of the variable we record
an assertion for to look for TYPE_MIN/MAX_VALUEs rather than
the limit that it is tested against.  That makes sense anyway
and happens to mitigate the wrong-code bug for the testcase
in PR50189.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Thanks,
Richard.

2011-10-12  Paul Koning  pkon...@gcc.gnu.org

PR tree-optimization/50189
* tree-vrp.c (extract_range_from_assert): Use the type of
the variable, not the limit.

* g++.dg/torture/pr50189.C: New testcase.

Index: gcc/tree-vrp.c
===
*** gcc/tree-vrp.c  (revision 179757)
--- gcc/tree-vrp.c  (working copy)
*** extract_range_from_assert (value_range_t
*** 1476,1482 
  
limit = avoid_overflow_infinity (limit);
  
!   type = TREE_TYPE (limit);
gcc_assert (limit != var);
  
/* For pointer arithmetic, we only keep track of pointer equality
--- 1476,1482 
  
limit = avoid_overflow_infinity (limit);
  
!   type = TREE_TYPE (var);
gcc_assert (limit != var);
  
/* For pointer arithmetic, we only keep track of pointer equality
Index: gcc/testsuite/g++.dg/torture/pr50189.C
===
*** gcc/testsuite/g++.dg/torture/pr50189.C  (revision 0)
--- gcc/testsuite/g++.dg/torture/pr50189.C  (revision 0)
***
*** 0 
--- 1,121 
+ // { dg-do run }
+ // { dg-options -fstrict-enums }
+ 
+ extern C void abort (void);
+ class CCUTILS_KeyedScalarLevelPosition
+ {
+ public:
+ 
+ typedef enum
+ {
+ UNINITED = 0,
+ AT_BEGIN = 1,
+ AT_END = 2,
+ AT_KEY = 3
+ 
+ } position_t;
+ 
+ bool is_init() const
+ { return(m_timestamp != UNINITED); }
+ 
+ bool is_at_begin() const
+ { return(m_timestamp == AT_BEGIN); }
+ 
+ position_t get_state() const
+ {
+ return((m_timestamp = AT_KEY)
+  ? AT_KEY
+  : ((position_t)m_timestamp));
+ }
+ 
+ void set_at_begin()
+ { m_timestamp = AT_BEGIN; }
+ 
+ unsigned int get_index() const
+ { return(m_index); }
+ 
+ void set_pos(unsigned int a_index, unsigned int a_timestmap)
+ {
+ m_index = a_index;
+ m_timestamp = a_timestmap;
+ }
+ 
+ bool check_pos(unsigned int a_num_entries, unsigned int a_timestamp) const
+ {
+ if (get_state() != AT_KEY)
+ return(false);
+ 
+ if (m_timestamp != a_timestamp)
+ return(false);
+ 
+ return(m_index  a_num_entries);
+ }
+ 
+ void set_not_init()
+ { m_timestamp = 0; }
+ 
+ private:
+ 
+ unsigned int m_timestamp;
+ unsigned int m_index;
+ 
+ };
+ 
+ class CCUTILS_KeyedScalarPosition
+ {
+ public:
+ 
+ CCUTILS_KeyedScalarLevelPosition m_L1;
+ CCUTILS_KeyedScalarLevelPosition m_L2;
+ };
+ 
+ class baz
+ {
+ public:
+ int *n[20];
+ unsigned int m_cur_array_len;
+ unsigned int m_timestamp;
+ 
+ unsigned int _get_timestamp() const
+ { return(m_timestamp); }
+ 
+ bool _check_L1_pos(const CCUTILS_KeyedScalarPosition a_position) const
+ {
+ return(a_position.m_L1.check_pos(
+m_cur_array_len, _get_timestamp()));
+ }
+ 
+ void *next (CCUTILS_KeyedScalarPosition );
+ };
+ 
+ void * baz::next (CCUTILS_KeyedScalarPosition a_position)
+ {
+ if (a_position.m_L1.is_at_begin() || (!a_position.m_L1.is_init()))
+ {
+ a_position.m_L1.set_pos(0, _get_timestamp());
+ a_position.m_L2.set_at_begin();
+ }
+ else if (!_check_L1_pos(a_position))
+ return(0);
+ 
+ return n[a_position.m_L1.get_index ()];
+ }
+ 
+ int main (int, char **)
+ {
+ baz obj;
+ CCUTILS_KeyedScalarPosition a_pos;
+ void *ret;
+ int n[5];
+ 
+ obj.n[0] = n;
+ obj.m_cur_array_len = 1;
+ obj.m_timestamp = 42;
+ 
+ a_pos.m_L1.set_pos (0, 42);
+ 
+ ret = obj.next (a_pos);
+ if (ret == 0)
+   abort ();
+ return 0;
+ }


Re: [PATCH] Fix PR50189

2011-10-12 Thread Richard Guenther
On Wed, 12 Oct 2011, Richard Guenther wrote:

 
 This changes VRP to use the type of the variable we record
 an assertion for to look for TYPE_MIN/MAX_VALUEs rather than
 the limit that it is tested against.  That makes sense anyway
 and happens to mitigate the wrong-code bug for the testcase
 in PR50189.
 
 Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Which shows I need to adjust types for plus/minus we build because
of possible mismatches.

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

Richard.

2011-10-12  Paul Koning  pkon...@gcc.gnu.org

PR tree-optimization/50189
* tree-vrp.c (extract_range_from_assert): Use the type of
the variable, not the limit.

* g++.dg/torture/pr50189.C: New testcase.

Index: gcc/tree-vrp.c
===
*** gcc/tree-vrp.c  (revision 179850)
--- gcc/tree-vrp.c  (working copy)
*** extract_range_from_assert (value_range_t
*** 1476,1482 
  
limit = avoid_overflow_infinity (limit);
  
!   type = TREE_TYPE (limit);
gcc_assert (limit != var);
  
/* For pointer arithmetic, we only keep track of pointer equality
--- 1476,1482 
  
limit = avoid_overflow_infinity (limit);
  
!   type = TREE_TYPE (var);
gcc_assert (limit != var);
  
/* For pointer arithmetic, we only keep track of pointer equality
*** extract_range_from_assert (value_range_t
*** 1650,1657 
  /* For LT_EXPR, we create the range [MIN, MAX - 1].  */
  if (cond_code == LT_EXPR)
{
! tree one = build_int_cst (type, 1);
! max = fold_build2 (MINUS_EXPR, type, max, one);
  if (EXPR_P (max))
TREE_NO_WARNING (max) = 1;
}
--- 1650,1657 
  /* For LT_EXPR, we create the range [MIN, MAX - 1].  */
  if (cond_code == LT_EXPR)
{
! tree one = build_int_cst (TREE_TYPE (max), 1);
! max = fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, one);
  if (EXPR_P (max))
TREE_NO_WARNING (max) = 1;
}
*** extract_range_from_assert (value_range_t
*** 1685,1692 
  /* For GT_EXPR, we create the range [MIN + 1, MAX].  */
  if (cond_code == GT_EXPR)
{
! tree one = build_int_cst (type, 1);
! min = fold_build2 (PLUS_EXPR, type, min, one);
  if (EXPR_P (min))
TREE_NO_WARNING (min) = 1;
}
--- 1685,1692 
  /* For GT_EXPR, we create the range [MIN + 1, MAX].  */
  if (cond_code == GT_EXPR)
{
! tree one = build_int_cst (TREE_TYPE (min), 1);
! min = fold_build2 (PLUS_EXPR, TREE_TYPE (min), min, one);
  if (EXPR_P (min))
TREE_NO_WARNING (min) = 1;
}
Index: gcc/testsuite/g++.dg/torture/pr50189.C
===
*** gcc/testsuite/g++.dg/torture/pr50189.C  (revision 0)
--- gcc/testsuite/g++.dg/torture/pr50189.C  (revision 0)
***
*** 0 
--- 1,121 
+ // { dg-do run }
+ // { dg-options -fstrict-enums }
+ 
+ extern C void abort (void);
+ class CCUTILS_KeyedScalarLevelPosition
+ {
+ public:
+ 
+ typedef enum
+ {
+ UNINITED = 0,
+ AT_BEGIN = 1,
+ AT_END = 2,
+ AT_KEY = 3
+ 
+ } position_t;
+ 
+ bool is_init() const
+ { return(m_timestamp != UNINITED); }
+ 
+ bool is_at_begin() const
+ { return(m_timestamp == AT_BEGIN); }
+ 
+ position_t get_state() const
+ {
+ return((m_timestamp = AT_KEY)
+  ? AT_KEY
+  : ((position_t)m_timestamp));
+ }
+ 
+ void set_at_begin()
+ { m_timestamp = AT_BEGIN; }
+ 
+ unsigned int get_index() const
+ { return(m_index); }
+ 
+ void set_pos(unsigned int a_index, unsigned int a_timestmap)
+ {
+ m_index = a_index;
+ m_timestamp = a_timestmap;
+ }
+ 
+ bool check_pos(unsigned int a_num_entries, unsigned int a_timestamp) const
+ {
+ if (get_state() != AT_KEY)
+ return(false);
+ 
+ if (m_timestamp != a_timestamp)
+ return(false);
+ 
+ return(m_index  a_num_entries);
+ }
+ 
+ void set_not_init()
+ { m_timestamp = 0; }
+ 
+ private:
+ 
+ unsigned int m_timestamp;
+ unsigned int m_index;
+ 
+ };
+ 
+ class CCUTILS_KeyedScalarPosition
+ {
+ public:
+ 
+ CCUTILS_KeyedScalarLevelPosition m_L1;
+ CCUTILS_KeyedScalarLevelPosition m_L2;
+ };
+ 
+ class baz
+ {
+ public:
+ int *n[20];
+ unsigned int m_cur_array_len;
+ unsigned int m_timestamp;
+ 
+ unsigned int _get_timestamp() const
+ { return(m_timestamp); }
+ 
+ bool _check_L1_pos(const CCUTILS_KeyedScalarPosition a_position) const
+ {
+ return(a_position.m_L1.check_pos(
+