This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: Fix PR tree-optimization/22444


This is the failures related to the is_old_name stuff

I accidently discovered the cause and fix for this bug while testing
some code on the improved-aliasing-branch.  It turns out we are
processing both the original var, and the sub vars, for possible entry
into the addressable var list, instead of just the subvars.  

Only things that make it onto the addressable var list are auto-marked
for renaming.

In a weird set of corner cases, it can turn out that the original var
thinks it is aliased and makes it onto the addressable var list but the
subvars may not be.

The failures in the C++ testcases all involve the result_decl being a
structure type that is aliased with something else in the function,
usually one of the parameters.

The result_decl has subvars, and the subvars can't be aliased (address
never taken, and we are returning a structure).  So they are not in the
addressable var list.  However, the regular var still is.  We decide
something can alias with the regular var, and the code i'm now removing
would then make it alias the subvars instead.

Since they were never marked for renaming, the world blew up.  

The fix, of course, is to not put the regular var in the addressable var
list.  It shouldn't have been there anyway, since it could only cause
false aliasing.  Only the subvars should make it there, if they go
there.

Bootstrapped and regtested on i686-pc-linux-gnu

Since this fixes a regression, i am committing it to mainline.

--Dan

2005-10-16  Daniel Berlin  <dberlin@dberlin.org>

	Fix PR tree-optimization/22444
	* tree-ssa-alias.c (compute_flow_insensitive_aliasing):
	Assert that we don't hit something with subvars.
	(setup_pointers_and_addressables): Don't add things with subvars,
	because we'll already process the subvars for aliasing purposes.

Index: tree-ssa-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-alias.c,v
retrieving revision 2.111
diff -u -p -r2.111 tree-ssa-alias.c
--- tree-ssa-alias.c	6 Oct 2005 16:20:13 -0000	2.111
+++ tree-ssa-alias.c	17 Oct 2005 00:46:29 -0000
@@ -799,7 +799,6 @@ compute_flow_insensitive_aliasing (struc
 	     
 	  if (may_alias_p (p_map->var, p_map->set, var, v_map->set, false))
 	    {
-	      subvar_t svars;
 	      size_t num_tag_refs, num_var_refs;
 
 	      num_tag_refs = NUM_REFERENCES (tag_ann);
@@ -807,28 +806,15 @@ compute_flow_insensitive_aliasing (struc
 
 	      /* Add VAR to TAG's may-aliases set.  */
 
-	      /* If this is an aggregate, we may have subvariables for it
-		 that need to be pointed to.  */
-	      if (var_can_have_subvars (var)
-		  && (svars = get_subvars_for_var (var)))
-		{
-		  subvar_t sv;
-
-		  for (sv = svars; sv; sv = sv->next)
-		    {
-		      add_may_alias (tag, sv->var);
-		      /* Update the bitmap used to represent TAG's alias set
-			 in case we need to group aliases.  */
-		      bitmap_set_bit (p_map->may_aliases, DECL_UID (sv->var));
-		    }
-		}
-	      else
-		{
-		  add_may_alias (tag, var);
-		  /* Update the bitmap used to represent TAG's alias set
-		     in case we need to group aliases.  */
-		  bitmap_set_bit (p_map->may_aliases, DECL_UID (var));
-		}
+	      /* We should never have a var with subvars here, because
+	         they shouldn't get into the set of addressable vars */
+	      gcc_assert (!var_can_have_subvars (var)
+			  || get_subvars_for_var (var) == NULL);
+
+	      add_may_alias (tag, var);
+	      /* Update the bitmap used to represent TAG's alias set
+		 in case we need to group aliases.  */
+	      bitmap_set_bit (p_map->may_aliases, DECL_UID (var));
 
 	      /* Update the total number of virtual operands due to
 		 aliasing.  Since we are adding one more alias to TAG's
@@ -1280,7 +1266,9 @@ setup_pointers_and_addressables (struct 
 
       /* Global variables and addressable locals may be aliased.  Create an
          entry in ADDRESSABLE_VARS for VAR.  */
-      if (may_be_aliased (var))
+      if (may_be_aliased (var)	  
+	  && (!var_can_have_subvars (var) 
+	      || get_subvars_for_var (var) == NULL))
 	{
 	  create_alias_map_for (var, ai);
 	  mark_sym_for_renaming (var);
Index: testsuite/g++.dg/tree-ssa/pr22444.C
===================================================================
RCS file: testsuite/g++.dg/tree-ssa/pr22444.C
diff -N testsuite/g++.dg/tree-ssa/pr22444.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/g++.dg/tree-ssa/pr22444.C	17 Oct 2005 01:02:01 -0000
@@ -0,0 +1,141 @@
+// PR tree-optimization/22444
+// When creating SFT's, we shouldn't add the original variable
+// to the addressable vars list, because this may cause false aliasing
+// with the subvars leading to the subvars not being renamed when they should
+// { dg-do compile }
+// { dg-options "-O2" }
+typedef int ptrdiff_t;
+typedef unsigned int size_t;
+namespace std
+{
+  template<class _T1, class _T2> struct pair
+  {
+    _T1 first;
+    _T2 second;
+    pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) { }
+  };
+}
+namespace __gnu_internal
+{
+  typedef char __one;
+  template<typename _Tp> __one __test_type(int _Tp::*);
+}
+namespace std
+{
+  template<typename _Tp> struct __is_pod
+  {
+    enum { __value = (sizeof(__gnu_internal::__test_type<_Tp>(0))!= sizeof(__gnu_internal::__one)) };
+  };
+  template<typename _Category, typename _Tp, typename _Distance = ptrdiff_t, typename _Pointer = _Tp*, typename _Reference = _Tp&> struct iterator
+  { };
+  template<typename _Iterator> struct iterator_traits
+  {
+    typedef typename _Iterator::difference_type difference_type;
+  };
+  template<typename _Iterator> class reverse_iterator : public iterator<typename iterator_traits<_Iterator>::iterator_category, typename iterator_traits<_Iterator>::value_type, typename iterator_traits<_Iterator>::difference_type, typename iterator_traits<_Iterator>::pointer, typename iterator_traits<_Iterator>::reference>
+  {
+    typedef _Iterator iterator_type;
+    typedef typename iterator_traits<_Iterator>::difference_type difference_type;
+    typedef typename iterator_traits<_Iterator>::reference reference;
+    reverse_iterator operator+(difference_type __n) const {}
+    reverse_iterator& operator+=(difference_type __n) { }
+    reference operator[](difference_type __n) const { }
+  };
+}
+namespace __gnu_cxx
+{
+  template<bool _Thread> class __pool;
+  template<template <bool> class _PoolTp, bool _Thread> struct __common_pool_policy;
+  template<typename _Tp> class __mt_alloc_base
+  {
+    typedef ptrdiff_t difference_type;
+    typedef _Tp* pointer;
+  };
+  template<typename _Tp, typename _Poolp = __common_pool_policy<__pool, true> > class __mt_alloc : public __mt_alloc_base<_Tp>
+  {
+    typedef size_t size_type;
+  };
+}
+namespace std
+{
+  template<typename _Tp> struct allocator:public __gnu_cxx::__mt_alloc<_Tp>
+  {
+    template<typename _Tp1> struct rebind
+    {
+      typedef allocator<_Tp1> other;
+    };
+  };
+  template <class _Arg, class _Result> struct unary_function  { };
+  template <class _Arg1, class _Arg2, class _Result> struct binary_function
+  {
+    typedef _Arg2 second_argument_type;
+  };
+  template <class _Tp> struct less : public binary_function<_Tp, _Tp, bool>
+  {
+    bool operator()(const _Tp& __x, const _Tp& __y) const { }
+  };
+  template <class _Tp> struct _Identity : public unary_function<_Tp,_Tp> { };
+  struct _Rb_tree_node_base
+  {
+    typedef _Rb_tree_node_base* _Base_ptr;
+    typedef const _Rb_tree_node_base* _Const_Base_ptr;
+    _Base_ptr _M_right;
+    static _Base_ptr _S_minimum(_Base_ptr __x) { }
+    static _Base_ptr _S_maximum(_Base_ptr __x) { }
+  };
+  template<typename _Val> struct _Rb_tree_node { };
+  template<typename _Tp> struct _Rb_tree_iterator
+  {
+    typedef _Tp* pointer;
+    typedef _Rb_tree_iterator<_Tp> _Self;
+    typedef _Rb_tree_node_base::_Base_ptr _Base_ptr;
+    pointer operator->() const { }
+    _Self operator++(int) { }
+    _Base_ptr _M_node;
+  };
+  template<typename _Tp> struct _Rb_tree_const_iterator
+  {
+    typedef const _Tp* pointer;
+    typedef _Rb_tree_iterator<_Tp> iterator;
+    typedef _Rb_tree_node_base::_Const_Base_ptr _Base_ptr;
+    _Rb_tree_const_iterator(const iterator& __it) : _M_node(__it._M_node) { }
+    _Base_ptr _M_node;
+  };
+  template<typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, typename _Alloc = allocator<_Val> > struct _Rb_tree
+  {
+    typedef typename _Alloc::template rebind<_Rb_tree_node<_Val> >::other _Node_allocator;
+    typedef _Rb_tree_node_base* _Base_ptr;
+    typedef const _Rb_tree_node_base* _Const_Base_ptr;
+    typedef _Rb_tree_node<_Val> _Rb_tree_node;
+    typedef _Key key_type;
+    typedef _Val value_type;
+    typedef value_type* pointer;
+    typedef _Rb_tree_node* _Link_type;
+    template<typename _Key_compare, bool _Is_pod_comparator = std::__is_pod<_Key_compare>::__value> struct _Rb_tree_impl
+      : _Node_allocator
+    {
+      _Rb_tree_node_base _M_header;
+    };
+    _Rb_tree_impl<_Compare> _M_impl;
+    typedef _Rb_tree_iterator<value_type> iterator;
+    typedef _Rb_tree_const_iterator<value_type> const_iterator;
+    typedef std::reverse_iterator<iterator> reverse_iterator;
+    pair<iterator,bool> insert_unique(const value_type& __x);
+  };
+  template<class _Key, class _Compare, class _Alloc> class set
+  {
+    typedef _Key key_type;
+    typedef _Key value_type;
+    typedef _Compare key_compare;
+    typedef typename _Alloc::template rebind<_Key>::other _Key_alloc_type;
+    typedef _Rb_tree<_Key, value_type, _Identity<value_type>, key_compare, _Key_alloc_type> _Rep_type;
+    _Rep_type _M_t;
+    typedef typename _Rep_type::const_iterator iterator;
+    std::pair<iterator,bool> insert(const value_type& __x)
+    {
+      std::pair<typename _Rep_type::iterator, bool> __p = _M_t.insert_unique(__x);
+      return std::pair<iterator, bool>(__p.first, __p.second);
+    }
+  };
+}
+template class std::set<int, std::less<int>, std::allocator<char> >;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]