The following patch avoids the cubic search for equal types by
collecting candidates and sorting them.  The length() == 2
qsort optimization probably belongs to vec.h and additionally
we can avoid sorting the other vector if one has length() == 1.

Bootstrapped and tested on x86_64-unknown-linux-gnu, queued
for stage1.

Quick statistics show that for insn-recog we always have 1 - 1
compares (nonoverlapping_component_refs_p was crippled quite a bit
when we stopped stripping outermost non-COMPONENT_REF trees from
MEM_EXPRs).  On this testcase the patch slows down the compiler
consistently by about 1% (but it's called 46 million times as part of
RTL PRE) - it seems we don't inline the fast path of
vec<tree_node const*, va_heap, vl_ptr>::safe_push(tree_node const* 
const&) on auto_vec<>s with a constant initial size.

Eventually this function should move to the tree oracle and should
be made less restrictive as to what input it accepts.  The following
is a patch that shouldn't change behavior in any ways.

Richard.

2014-02-12  Richard Biener  <rguent...@suse.de>

        * alias.c (ncr_compar): New function.
        (nonoverlapping_component_refs_p): Re-implement in O (n log n).

Index: gcc/alias.c
===================================================================
*** gcc/alias.c (revision 207655)
--- gcc/alias.c (working copy)
*************** read_dependence (const_rtx mem, const_rt
*** 2259,2264 ****
--- 2261,2285 ----
    return false;
  }
  
+ /* qsort compare function to sort FIELD_DECLs after their
+    DECL_FIELD_CONTEXT TYPE_UID.  */
+ 
+ static inline int
+ ncr_compar (const void *field1_, const void *field2_)
+ {
+   const_tree field1 = *(const_tree *) const_cast <void *>(field1_);
+   const_tree field2 = *(const_tree *) const_cast <void *>(field2_);
+   unsigned int uid1
+     = TYPE_UID (TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field1)));
+   unsigned int uid2
+     = TYPE_UID (TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field2)));
+   if (uid1 < uid2)
+     return -1;
+   else if (uid1 > uid2)
+     return 1;
+   return 0;
+ }
+ 
  /* Return true if we can determine that the fields referenced cannot
     overlap for any pair of objects.  */
  
*************** static bool
*** 2266,2272 ****
  nonoverlapping_component_refs_p (const_rtx rtlx, const_rtx rtly)
  {
    const_tree x = MEM_EXPR (rtlx), y = MEM_EXPR (rtly);
-   const_tree fieldx, fieldy, typex, typey, orig_y;
  
    if (!flag_strict_aliasing
        || !x || !y
--- 2287,2292 ----
*************** nonoverlapping_component_refs_p (const_r
*** 2274,2322 ****
        || TREE_CODE (y) != COMPONENT_REF)
      return false;
  
!   do
      {
!       /* The comparison has to be done at a common type, since we don't
!        know how the inheritance hierarchy works.  */
!       orig_y = y;
!       do
!       {
!         fieldx = TREE_OPERAND (x, 1);
!         typex = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldx));
! 
!         y = orig_y;
!         do
!           {
!             fieldy = TREE_OPERAND (y, 1);
!             typey = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldy));
! 
!             if (typex == typey)
!               goto found;
! 
!             y = TREE_OPERAND (y, 0);
!           }
!         while (y && TREE_CODE (y) == COMPONENT_REF);
  
!         x = TREE_OPERAND (x, 0);
        }
!       while (x && TREE_CODE (x) == COMPONENT_REF);
!       /* Never found a common type.  */
!       return false;
  
!     found:
!       /* If we're left with accessing different fields of a structure, then no
!        possible overlap, unless they are both bitfields.  */
!       if (TREE_CODE (typex) == RECORD_TYPE && fieldx != fieldy)
!       return !(DECL_BIT_FIELD (fieldx) && DECL_BIT_FIELD (fieldy));
  
!       /* The comparison on the current field failed.  If we're accessing
!        a very nested structure, look at the next outer level.  */
!       x = TREE_OPERAND (x, 0);
!       y = TREE_OPERAND (y, 0);
      }
!   while (x && y
!        && TREE_CODE (x) == COMPONENT_REF
!        && TREE_CODE (y) == COMPONENT_REF);
  
    return false;
  }
--- 2294,2382 ----
        || TREE_CODE (y) != COMPONENT_REF)
      return false;
  
!   auto_vec<const_tree, 16> fieldsx;
!   while (TREE_CODE (x) == COMPONENT_REF)
      {
!       tree field = TREE_OPERAND (x, 1);
!       tree type = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field));
!       if (TREE_CODE (type) == RECORD_TYPE)
!       fieldsx.safe_push (field);
!       x = TREE_OPERAND (x, 0);
!     }
!   if (fieldsx.length () == 0)
!     return false;
!   auto_vec<const_tree, 16> fieldsy;
!   while (TREE_CODE (y) == COMPONENT_REF)
!     {
!       tree field = TREE_OPERAND (y, 1);
!       tree type = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field));
!       if (TREE_CODE (type) == RECORD_TYPE)
!       fieldsy.safe_push (TREE_OPERAND (y, 1));
!       y = TREE_OPERAND (y, 0);
!     }
!   if (fieldsy.length () == 0)
!     return false;
  
!   /* Most common case first.  */
!   if (fieldsx.length () == 1
!       && fieldsy.length () == 1)
!     return ((TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldsx[0]))
!            == TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldsy[0])))
!           && fieldsx[0] != fieldsy[0]
!           && !(DECL_BIT_FIELD (fieldsx[0]) && DECL_BIT_FIELD (fieldsy[0])));
! 
!   if (fieldsx.length () == 2)
!     {
!       if (ncr_compar (&fieldsx[0], &fieldsx[1]) == 1)
!       {
!         const_tree tem = fieldsx[0];
!         fieldsx[0] = fieldsx[1];
!         fieldsx[1] = tem;
        }
!     }
!   else
!     fieldsx.qsort (ncr_compar);
  
!   if (fieldsy.length () == 2)
!     {
!       if (ncr_compar (&fieldsy[0], &fieldsy[1]) == 1)
!       {
!         const_tree tem = fieldsy[0];
!         fieldsy[0] = fieldsy[1];
!         fieldsy[1] = tem;
!       }
!     }
!   else
!     fieldsy.qsort (ncr_compar);
  
!   unsigned i = 0, j = 0;
!   do
!     {
!       const_tree fieldx = fieldsx[i];
!       const_tree fieldy = fieldsy[j];
!       tree typex = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldx));
!       tree typey = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldy));
!       if (typex == typey)
!       {
!         /* We're left with accessing different fields of a structure,
!            no possible overlap, unless they are both bitfields.  */
!         if (fieldx != fieldy)
!           return !(DECL_BIT_FIELD (fieldx) && DECL_BIT_FIELD (fieldy));
!       }
!       if (TYPE_UID (typex) < TYPE_UID (typey))
!       {
!         i++;
!         if (i == fieldsx.length ())
!           break;
!       }
!       else
!       {
!         j++;
!         if (j == fieldsy.length ())
!           break;
!       }
      }
!   while (1);
  
    return false;
  }

Reply via email to