On Wed, Feb 12, 2014 at 04:28:14PM +0100, Richard Biener wrote:
> On Wed, Feb 12, 2014 at 4:21 PM, Trevor Saunders <tsaund...@mozilla.com> 
> wrote:
> > On Wed, Feb 12, 2014 at 03:09:17PM +0100, Richard Biener wrote:
> >>
> >> The following aims to improve code generation for loops like
> >> those in tree-ssa-alias.c:
> >>
> >>   auto_vec<tree, 16> component_refs1;
> >>   auto_vec<tree, 16> component_refs2;
> >>
> >>   /* Create the stack of handled components for REF1.  */
> >>   while (handled_component_p (ref1))
> >>     {
> >>       component_refs1.safe_push (ref1);
> >>       ref1 = TREE_OPERAND (ref1, 0);
> >>     }
> >>
> >> It does so by making sure the vector itself doesn't necessarily
> >> escape (to vec.c:calculate_allocation) and by simplifying the
> >> way we identify a vector using auto storage.  In the end this
> >> results in us doing better CSE.  But not SRA unfortunately,
> >> as we have
> >>
> >>   component_refs1.m_header.m_alloc = 16;
> >>   component_refs1.m_header.m_using_auto_storage = 1;
> >>   component_refs1.m_header.m_num = 0;
> >>   component_refs1.D.56915.m_vec = &component_refs1.m_header;
> >>
> >> which is what keeps component_refs1 address-taken (no easy
> >> way out of that I fear).
> >>
> >> It also gets rid of the aliasing-suspicious
> >>
> >>     this->m_vec = reinterpret_cast<vec<T, va_heap, vl_embed> *>
> >> (&m_header);
> >>
> >> and the friend declaration in class auto_vec.
> >
> > over all I like this, only two small comments
> >
> >>       (vec_prefix::m_has_auto_buf): Rename to ...
> >>       (vec_prefix::m_using_auto_storage): ... this.
> >
> > One optimization that might be worth doing is if a vector is cleared
> > reseting m_vec to point at the internal storage in which case the old
> > name would be more accurate, on the other hand its probably rare that's
> > useful, and doing it this way is simpler.
> 
> Yeah, I thought about this but disregarded it as not-the-common case.

makes sense.

> >>     ~auto_vec ()
> >> --- 1250,1257 ----
> >>   public:
> >>     auto_vec ()
> >>     {
> >> !     m_auto.embedded_init (MAX (N, 2), 0, 1);
> >> !     this->m_vec = &m_auto;
> >>     }
> >>
> >>     ~auto_vec ()
> >> *************** public:
> >> *** 1246,1255 ****
> >>     }
> >>
> >>   private:
> >> !   friend class vec<T, va_heap, vl_ptr>;
> >> !
> >> !   vec_prefix m_header;
> >> !   T m_data[N];
> >>   };
> >>
> >>   /* auto_vec is a sub class of vec whose storage is released when it is
> >> --- 1260,1267 ----
> >>     }
> >>
> >>   private:
> >> !   vec<T, va_heap, vl_embed> m_auto;
> >> !   T m_data[MAX (N - 1, 1)];
> >
> > why is the MAX() needed? auto_vec<T, 0> is specialized below so someone
> > would need to write auto_vec<T, -x> for N - 1 to be less than 1 which is
> > crazy, and seems like shouldn't be allowed to compile.
> 
> It's for the quite common auto_vec<T, 1> case where T m_data[N-1]
> doesn't work (zero-sized array is a GNU extension).  I've had the
> variant of simply allocating N + 1 elements (and thus using
> m_data[N]) but then the above is closer to what people expect (but
> sets the minimum auto size to two elements).

 I forgot about and then missed embedded vectors having the one internal
 element, so yeah this makes sense.

> Alternatively one could have templated vec<T, va_heap, vl_embed>

yeah, lets not do that its already way too template happy.

> itself with a size for its m_data member.  Or specialize auto_vec
> for N == 1 and leave out the m_data member for that.
> 
> I considered both not worth the trouble ;)

sgtm

Thanks!

Trev

> 
> If you prefer using m_data[N] and thus allocating one more element
> than requested in auto storage I can do that as well.
> 
> Thanks,
> Richard.
> 
> > thanks!
> >
> > Trev
> >
> >>   };
> >>
> >>   /* auto_vec is a sub class of vec whose storage is released when it is
> >> *************** template<typename T>
> >> *** 1396,1402 ****
> >>   inline bool
> >>   vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact 
> >> MEM_STAT_DECL)
> >>   {
> >> !   if (!nelems || space (nelems))
> >>       return false;
> >>
> >>     /* For now play a game with va_heap::reserve to hide our auto storage 
> >> if any,
> >> --- 1408,1414 ----
> >>   inline bool
> >>   vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact 
> >> MEM_STAT_DECL)
> >>   {
> >> !   if (space (nelems))
> >>       return false;
> >>
> >>     /* For now play a game with va_heap::reserve to hide our auto storage 
> >> if any,
> >> *************** vec<T, va_heap, vl_ptr>::release (void)
> >> *** 1462,1468 ****
> >>
> >>     if (using_auto_storage ())
> >>       {
> >> !       static_cast<auto_vec<T, 1> *> (this)->m_header.m_num = 0;
> >>         return;
> >>       }
> >>
> >> --- 1474,1480 ----
> >>
> >>     if (using_auto_storage ())
> >>       {
> >> !       m_vec->m_vecpfx.m_num = 0;
> >>         return;
> >>       }
> >>
> >> *************** template<typename T>
> >> *** 1705,1716 ****
> >>   inline bool
> >>   vec<T, va_heap, vl_ptr>::using_auto_storage () const
> >>   {
> >> !   if (!m_vec->m_vecpfx.m_has_auto_buf)
> >> !     return false;
> >> !
> >> !   const vec_prefix *auto_header
> >> !     = &static_cast<const auto_vec<T, 1> *> (this)->m_header;
> >> !   return reinterpret_cast<vec_prefix *> (m_vec) == auto_header;
> >>   }
> >>
> >>   #if (GCC_VERSION >= 3000)
> >> --- 1717,1723 ----
> >>   inline bool
> >>   vec<T, va_heap, vl_ptr>::using_auto_storage () const
> >>   {
> >> !   return m_vec->m_vecpfx.m_using_auto_storage;
> >>   }
> >>
> >>   #if (GCC_VERSION >= 3000)

Reply via email to