OSDN Git Service

2009-06-19 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 19 Jun 2009 16:47:35 +0000 (16:47 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 19 Jun 2009 16:47:35 +0000 (16:47 +0000)
* tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Handle
ADDR_EXPR pointers.
(ptr_derefs_may_alias_p): Likewise.
(ptr_deref_may_alias_ref_p_1): New function.
(ptr_deref_may_alias_ref_p): Likewise.
(ref_maybe_used_by_call_p_1): Handle builtins that are not
covered by looking at the ESCAPED solution.
(call_may_clobber_ref_p_1): Likewise.
* tree-ssa-structalias.c (get_constraint_for_ptr_offset):
Handle NULL_TREE offset.  Do not produce redundant constraints.
(process_all_all_constraints): New helper function.
(do_structure_copy): Use it.
(handle_lhs_call): Likewise.
(find_func_aliases): Handle some builtins with pointer arguments
and/or return values explicitly.

* gcc.c-torture/execute/20090618-1.c: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@148718 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20090618-1.c [new file with mode: 0644]
gcc/tree-ssa-alias.c
gcc/tree-ssa-structalias.c

index cb34bee..f4e7816 100644 (file)
@@ -1,3 +1,21 @@
+2009-06-19  Richard Guenther  <rguenther@suse.de>
+
+       * tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Handle
+       ADDR_EXPR pointers.
+       (ptr_derefs_may_alias_p): Likewise.
+       (ptr_deref_may_alias_ref_p_1): New function.
+       (ptr_deref_may_alias_ref_p): Likewise.
+       (ref_maybe_used_by_call_p_1): Handle builtins that are not
+       covered by looking at the ESCAPED solution.
+       (call_may_clobber_ref_p_1): Likewise.
+       * tree-ssa-structalias.c (get_constraint_for_ptr_offset):
+       Handle NULL_TREE offset.  Do not produce redundant constraints.
+       (process_all_all_constraints): New helper function.
+       (do_structure_copy): Use it.
+       (handle_lhs_call): Likewise.
+       (find_func_aliases): Handle some builtins with pointer arguments
+       and/or return values explicitly.
+
 2009-06-19  Ian Lance Taylor  <iant@google.com>
 
        * varasm.c (const_rtx_hash_1): Remove const qualifier from shift.
index fec4369..e1ea0a3 100644 (file)
@@ -1,3 +1,7 @@
+2009-06-19  Richard Guenther  <rguenther@suse.de>
+
+       * gcc.c-torture/execute/20090618-1.c: New testcase.
+
 2009-06-19  Ian Lance Taylor  <iant@google.com>
 
        * gcc.dg/Wcxx-compat-17.c: New testcase.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20090618-1.c b/gcc/testsuite/gcc.c-torture/execute/20090618-1.c
new file mode 100644 (file)
index 0000000..f522116
--- /dev/null
@@ -0,0 +1,21 @@
+extern void abort (void);
+
+struct X { int *p; int *q; };
+
+int foo(void)
+{
+  int i = 0, j = 1;
+  struct X x, y;
+  int **p;
+  y.p = &i;
+  x.q = &j;
+  p = __builtin_mempcpy (&x, &y, sizeof (int *));
+  return **p;
+}
+
+int main()
+{
+  if (foo() != 1)
+    abort ();
+  return 0;
+}
index 6cbec5d..c83488b 100644 (file)
@@ -168,14 +168,9 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
 {
   struct ptr_info_def *pi;
 
-  /* ???  During SCCVN/PRE we can end up with *&x during valueizing
-     operands.  Likewise we can end up with dereferencing constant
-     pointers.  Just bail out in these cases for now.  */
-  if (TREE_CODE (ptr) == ADDR_EXPR
-      || TREE_CODE (ptr) == INTEGER_CST)
-    return true;
-
-  gcc_assert (TREE_CODE (ptr) == SSA_NAME
+  gcc_assert ((TREE_CODE (ptr) == SSA_NAME
+              || TREE_CODE (ptr) == ADDR_EXPR
+              || TREE_CODE (ptr) == INTEGER_CST)
              && (TREE_CODE (decl) == VAR_DECL
                  || TREE_CODE (decl) == PARM_DECL
                  || TREE_CODE (decl) == RESULT_DECL));
@@ -184,6 +179,29 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
   if (!may_be_aliased (decl))
     return false;
 
+  /* ADDR_EXPR pointers either just offset another pointer or directly
+     specify the pointed-to set.  */
+  if (TREE_CODE (ptr) == ADDR_EXPR)
+    {
+      tree base = get_base_address (TREE_OPERAND (ptr, 0));
+      if (base
+         && INDIRECT_REF_P (base))
+       ptr = TREE_OPERAND (base, 0);
+      else if (base
+              && SSA_VAR_P (base))
+       return operand_equal_p (base, decl, 0);
+      else if (base
+              && CONSTANT_CLASS_P (base))
+       return false;
+      else
+       return true;
+    }
+
+  /* We can end up with dereferencing constant pointers.
+     Just bail out in this case.  */
+  if (TREE_CODE (ptr) == INTEGER_CST)
+    return true;
+
   /* If we do not have useful points-to information for this pointer
      we cannot disambiguate anything else.  */
   pi = SSA_NAME_PTR_INFO (ptr);
@@ -202,18 +220,46 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
 {
   struct ptr_info_def *pi1, *pi2;
 
-  /* ???  During SCCVN/PRE we can end up with *&x during valueizing
-     operands.  Likewise we can end up with dereferencing constant
-     pointers.  Just bail out in these cases for now.  */
-  if (TREE_CODE (ptr1) == ADDR_EXPR
-      || TREE_CODE (ptr1) == INTEGER_CST
-      || TREE_CODE (ptr2) == ADDR_EXPR
+  gcc_assert ((TREE_CODE (ptr1) == SSA_NAME
+              || TREE_CODE (ptr1) == ADDR_EXPR
+              || TREE_CODE (ptr1) == INTEGER_CST)
+             && (TREE_CODE (ptr2) == SSA_NAME
+                 || TREE_CODE (ptr2) == ADDR_EXPR
+                 || TREE_CODE (ptr2) == INTEGER_CST));
+
+  /* ADDR_EXPR pointers either just offset another pointer or directly
+     specify the pointed-to set.  */
+  if (TREE_CODE (ptr1) == ADDR_EXPR)
+    {
+      tree base = get_base_address (TREE_OPERAND (ptr1, 0));
+      if (base
+         && INDIRECT_REF_P (base))
+       ptr1 = TREE_OPERAND (base, 0);
+      else if (base
+              && SSA_VAR_P (base))
+       return ptr_deref_may_alias_decl_p (ptr2, base);
+      else
+       return true;
+    }
+  if (TREE_CODE (ptr2) == ADDR_EXPR)
+    {
+      tree base = get_base_address (TREE_OPERAND (ptr2, 0));
+      if (base
+         && INDIRECT_REF_P (base))
+       ptr2 = TREE_OPERAND (base, 0);
+      else if (base
+              && SSA_VAR_P (base))
+       return ptr_deref_may_alias_decl_p (ptr1, base);
+      else
+       return true;
+    }
+
+  /* We can end up with dereferencing constant pointers.
+     Just bail out in this case.  */
+  if (TREE_CODE (ptr1) == INTEGER_CST
       || TREE_CODE (ptr2) == INTEGER_CST)
     return true;
 
-  gcc_assert (TREE_CODE (ptr1) == SSA_NAME
-             && TREE_CODE (ptr2) == SSA_NAME);
-
   /* We may end up with two empty points-to solutions for two same pointers.
      In this case we still want to say both pointers alias, so shortcut
      that here.  */
@@ -232,6 +278,31 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
   return pt_solutions_intersect (&pi1->pt, &pi2->pt);
 }
 
+/* Return true if dereferencing PTR may alias *REF.
+   The caller is responsible for applying TBAA to see if PTR
+   may access *REF at all.  */
+
+static bool
+ptr_deref_may_alias_ref_p_1 (tree ptr, ao_ref *ref)
+{
+  tree base = ao_ref_base (ref);
+
+  if (INDIRECT_REF_P (base))
+    return ptr_derefs_may_alias_p (ptr, TREE_OPERAND (base, 0));
+  else if (SSA_VAR_P (base))
+    return ptr_deref_may_alias_decl_p (ptr, base);
+
+  return true;
+}
+
+static bool
+ptr_deref_may_alias_ref_p (tree ptr, tree ref)
+{
+  ao_ref r;
+  ao_ref_init (&r, ref);
+  return ptr_deref_may_alias_ref_p_1 (ptr, &r);
+}
+
 
 /* Dump alias information on FILE.  */
 
@@ -778,7 +849,7 @@ refs_output_dependent_p (tree store1, tree store2)
 static bool
 ref_maybe_used_by_call_p_1 (gimple call, tree ref)
 {
-  tree base;
+  tree base, callee;
   unsigned i;
   int flags = gimple_call_flags (call);
 
@@ -803,13 +874,41 @@ ref_maybe_used_by_call_p_1 (gimple call, tree ref)
       && !is_global_var (base))
     goto process_args;
 
+  callee = gimple_call_fndecl (call);
+
+  /* Handle those builtin functions explicitly that do not act as
+     escape points.  See tree-ssa-structalias.c:find_func_aliases
+     for the list of builtins we might need to handle here.  */
+  if (callee != NULL_TREE
+      && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
+    switch (DECL_FUNCTION_CODE (callee))
+      {
+       /* All the following functions clobber memory pointed to by
+          their first argument.  */
+       case BUILT_IN_STRCPY:
+       case BUILT_IN_STRNCPY:
+       case BUILT_IN_BCOPY:
+       case BUILT_IN_MEMCPY:
+       case BUILT_IN_MEMMOVE:
+       case BUILT_IN_MEMPCPY:
+       case BUILT_IN_STPCPY:
+       case BUILT_IN_STPNCPY:
+       case BUILT_IN_STRCAT:
+       case BUILT_IN_STRNCAT:
+         {
+           tree src = gimple_call_arg (call, 1);
+           return ptr_deref_may_alias_ref_p (src, ref);
+         }
+       default:
+         /* Fallthru to general call handling.  */;
+      }
+
   /* Check if base is a global static variable that is not read
      by the function.  */
   if (TREE_CODE (base) == VAR_DECL
       && TREE_STATIC (base)
       && !TREE_PUBLIC (base))
     {
-      tree callee = gimple_call_fndecl (call);
       bitmap not_read;
 
       if (callee != NULL_TREE
@@ -901,6 +1000,7 @@ static bool
 call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
 {
   tree base;
+  tree callee;
 
   /* If the call is pure or const it cannot clobber anything.  */
   if (gimple_call_flags (call)
@@ -926,18 +1026,87 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
          || !is_global_var (base)))
     return false;
 
+  callee = gimple_call_fndecl (call);
+
+  /* Handle those builtin functions explicitly that do not act as
+     escape points.  See tree-ssa-structalias.c:find_func_aliases
+     for the list of builtins we might need to handle here.  */
+  if (callee != NULL_TREE
+      && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
+    switch (DECL_FUNCTION_CODE (callee))
+      {
+       /* All the following functions clobber memory pointed to by
+          their first argument.  */
+       case BUILT_IN_STRCPY:
+       case BUILT_IN_STRNCPY:
+       case BUILT_IN_BCOPY:
+       case BUILT_IN_MEMCPY:
+       case BUILT_IN_MEMMOVE:
+       case BUILT_IN_MEMPCPY:
+       case BUILT_IN_STPCPY:
+       case BUILT_IN_STPNCPY:
+       case BUILT_IN_STRCAT:
+       case BUILT_IN_STRNCAT:
+         {
+           tree dest = gimple_call_arg (call, 0);
+           return ptr_deref_may_alias_ref_p_1 (dest, ref);
+         }
+       /* Freeing memory kills the pointed-to memory.  More importantly
+          the call has to serve as a barrier for moving loads and stores
+          across it.  Same is true for memset.  */
+       case BUILT_IN_FREE:
+       case BUILT_IN_MEMSET:
+         {
+           tree ptr = gimple_call_arg (call, 0);
+           return ptr_deref_may_alias_ref_p_1 (ptr, ref);
+         }
+       case BUILT_IN_FREXP:
+       case BUILT_IN_FREXPF:
+       case BUILT_IN_FREXPL:
+       case BUILT_IN_GAMMA_R:
+       case BUILT_IN_GAMMAF_R:
+       case BUILT_IN_GAMMAL_R:
+       case BUILT_IN_LGAMMA_R:
+       case BUILT_IN_LGAMMAF_R:
+       case BUILT_IN_LGAMMAL_R:
+       case BUILT_IN_MODF:
+       case BUILT_IN_MODFF:
+       case BUILT_IN_MODFL:
+         {
+           tree out = gimple_call_arg (call, 1);
+           return ptr_deref_may_alias_ref_p_1 (out, ref);
+         }
+       case BUILT_IN_REMQUO:
+       case BUILT_IN_REMQUOF:
+       case BUILT_IN_REMQUOL:
+         {
+           tree out = gimple_call_arg (call, 2);
+           return ptr_deref_may_alias_ref_p_1 (out, ref);
+         }
+       case BUILT_IN_SINCOS:
+       case BUILT_IN_SINCOSF:
+       case BUILT_IN_SINCOSL:
+         {
+           tree sin = gimple_call_arg (call, 1);
+           tree cos = gimple_call_arg (call, 2);
+           return (ptr_deref_may_alias_ref_p_1 (sin, ref)
+                   || ptr_deref_may_alias_ref_p_1 (cos, ref));
+         }
+       default:
+         /* Fallthru to general call handling.  */;
+      }
+
   /* Check if base is a global static variable that is not written
      by the function.  */
-  if (TREE_CODE (base) == VAR_DECL
+  if (callee != NULL_TREE
+      && TREE_CODE (base) == VAR_DECL
       && TREE_STATIC (base)
       && !TREE_PUBLIC (base))
     {
-      tree callee = gimple_call_fndecl (call);
       bitmap not_written;
 
-      if (callee != NULL_TREE
-         && (not_written
-               = ipa_reference_get_not_written_global (cgraph_node (callee)))
+      if ((not_written
+            = ipa_reference_get_not_written_global (cgraph_node (callee)))
          && bitmap_bit_p (not_written, DECL_UID (base)))
        return false;
     }
index 60863d5..bca2145 100644 (file)
@@ -2857,7 +2857,8 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
      in a HOST_WIDE_INT, we have to fall back to a conservative
      solution which includes all sub-fields of all pointed-to
      variables of ptr.  */
-  if (!host_integerp (offset, 0))
+  if (offset == NULL_TREE
+      || !host_integerp (offset, 0))
     rhsoffset = UNKNOWN_OFFSET;
   else
     {
@@ -2896,7 +2897,8 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
              c2.var = temp->id;
              c2.type = ADDRESSOF;
              c2.offset = 0;
-             VEC_safe_push (ce_s, heap, *results, &c2);
+             if (c2.var != c->var)
+               VEC_safe_push (ce_s, heap, *results, &c2);
              temp = temp->next;
            }
          while (temp);
@@ -3239,6 +3241,37 @@ get_constraint_for (tree t, VEC (ce_s, heap) **results)
   get_constraint_for_1 (t, results, false);
 }
 
+
+/* Efficiently generates constraints from all entries in *RHSC to all
+   entries in *LHSC.  */
+
+static void
+process_all_all_constraints (VEC (ce_s, heap) *lhsc, VEC (ce_s, heap) *rhsc)
+{
+  struct constraint_expr *lhsp, *rhsp;
+  unsigned i, j;
+
+  if (VEC_length (ce_s, lhsc) <= 1
+      || VEC_length (ce_s, rhsc) <= 1)
+    {
+      for (i = 0; VEC_iterate (ce_s, lhsc, i, lhsp); ++i)
+       for (j = 0; VEC_iterate (ce_s, rhsc, j, rhsp); ++j)
+         process_constraint (new_constraint (*lhsp, *rhsp));
+    }
+  else
+    {
+      struct constraint_expr tmp;
+      tree tmpvar = create_tmp_var_raw (ptr_type_node, "allallcopytmp");
+      tmp.var = get_vi_for_tree (tmpvar)->id;
+      tmp.type = SCALAR;
+      tmp.offset = 0;
+      for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); ++i)
+       process_constraint (new_constraint (tmp, *rhsp));
+      for (i = 0; VEC_iterate (ce_s, lhsc, i, lhsp); ++i)
+       process_constraint (new_constraint (*lhsp, tmp));
+    }
+}
+
 /* Handle aggregate copies by expanding into copies of the respective
    fields of the structures.  */
 
@@ -3256,18 +3289,7 @@ do_structure_copy (tree lhsop, tree rhsop)
   if (lhsp->type == DEREF
       || (lhsp->type == ADDRESSOF && lhsp->var == anything_id)
       || rhsp->type == DEREF)
-    {
-      struct constraint_expr tmp;
-      tree tmpvar = create_tmp_var_raw (ptr_type_node,
-                                       "structcopydereftmp");
-      tmp.var = get_vi_for_tree (tmpvar)->id;
-      tmp.type = SCALAR;
-      tmp.offset = 0;
-      for (j = 0; VEC_iterate (ce_s, rhsc, j, rhsp); ++j)
-       process_constraint (new_constraint (tmp, *rhsp));
-      for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); ++j)
-       process_constraint (new_constraint (*lhsp, tmp));
-    }
+    process_all_all_constraints (lhsc, rhsc);
   else if (lhsp->type == SCALAR
           && (rhsp->type == SCALAR
               || rhsp->type == ADDRESSOF))
@@ -3426,8 +3448,6 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
     }
   else if (VEC_length (ce_s, rhsc) > 0)
     {
-      struct constraint_expr *lhsp, *rhsp;
-      unsigned int i, j;
       /* If the store is to a global decl make sure to
         add proper escape constraints.  */
       lhs = get_base_address (lhs);
@@ -3441,9 +3461,7 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
          tmpc.type = SCALAR;
          VEC_safe_push (ce_s, heap, lhsc, &tmpc);
        }
-      for (i = 0; VEC_iterate (ce_s, lhsc, i, lhsp); ++i)
-       for (j = 0; VEC_iterate (ce_s, rhsc, j, rhsp); ++j)
-         process_constraint (new_constraint (*lhsp, *rhsp));
+      process_all_all_constraints (lhsc, rhsc);
     }
   VEC_free (ce_s, heap, lhsc);
 }
@@ -3608,6 +3626,108 @@ find_func_aliases (gimple origt)
      pointer passed by address.  */
   else if (is_gimple_call (t))
     {
+      tree fndecl;
+      if ((fndecl = gimple_call_fndecl (t)) != NULL_TREE
+         && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+       /* ???  All builtins that are handled here need to be handled
+          in the alias-oracle query functions explicitly!  */
+       switch (DECL_FUNCTION_CODE (fndecl))
+         {
+         /* All the following functions return a pointer to the same object
+            as their first argument points to.  The functions do not add
+            to the ESCAPED solution.  The functions make the first argument
+            pointed to memory point to what the second argument pointed to
+            memory points to.  */
+         case BUILT_IN_STRCPY:
+         case BUILT_IN_STRNCPY:
+         case BUILT_IN_BCOPY:
+         case BUILT_IN_MEMCPY:
+         case BUILT_IN_MEMMOVE:
+         case BUILT_IN_MEMPCPY:
+         case BUILT_IN_STPCPY:
+         case BUILT_IN_STPNCPY:
+         case BUILT_IN_STRCAT:
+         case BUILT_IN_STRNCAT:
+           {
+             tree res = gimple_call_lhs (t);
+             tree dest = gimple_call_arg (t, 0);
+             tree src = gimple_call_arg (t, 1);
+             if (res != NULL_TREE)
+               {
+                 get_constraint_for (res, &lhsc);
+                 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMPCPY
+                     || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPCPY
+                     || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPNCPY)
+                   get_constraint_for_ptr_offset (dest, NULL_TREE, &rhsc);
+                 else
+                   get_constraint_for (dest, &rhsc);
+                 process_all_all_constraints (lhsc, rhsc);
+                 VEC_free (ce_s, heap, lhsc);
+                 VEC_free (ce_s, heap, rhsc);
+               }
+             get_constraint_for_ptr_offset (dest, NULL_TREE, &lhsc);
+             get_constraint_for_ptr_offset (src, NULL_TREE, &rhsc);
+             do_deref (&lhsc);
+             do_deref (&rhsc);
+             process_all_all_constraints (lhsc, rhsc);
+             VEC_free (ce_s, heap, lhsc);
+             VEC_free (ce_s, heap, rhsc);
+             return;
+           }
+         case BUILT_IN_MEMSET:
+           {
+             tree res = gimple_call_lhs (t);
+             tree dest = gimple_call_arg (t, 0);
+             unsigned i;
+             ce_s *lhsp;
+             struct constraint_expr ac;
+             if (res != NULL_TREE)
+               {
+                 get_constraint_for (res, &lhsc);
+                 get_constraint_for (dest, &rhsc);
+                 process_all_all_constraints (lhsc, rhsc);
+                 VEC_free (ce_s, heap, lhsc);
+                 VEC_free (ce_s, heap, rhsc);
+               }
+             get_constraint_for_ptr_offset (dest, NULL_TREE, &lhsc);
+             do_deref (&lhsc);
+             ac.type = SCALAR;
+             ac.var = integer_id;
+             ac.offset = 0;
+             for (i = 0; VEC_iterate (ce_s, lhsc, i, lhsp); ++i)
+               process_constraint (new_constraint (*lhsp, ac));
+             VEC_free (ce_s, heap, lhsc);
+             return;
+           }
+         /* All the following functions do not return pointers, do not
+            modify the points-to sets of memory reachable from their
+            arguments and do not add to the ESCAPED solution.  */
+         case BUILT_IN_SINCOS:
+         case BUILT_IN_SINCOSF:
+         case BUILT_IN_SINCOSL:
+         case BUILT_IN_FREXP:
+         case BUILT_IN_FREXPF:
+         case BUILT_IN_FREXPL:
+         case BUILT_IN_GAMMA_R:
+         case BUILT_IN_GAMMAF_R:
+         case BUILT_IN_GAMMAL_R:
+         case BUILT_IN_LGAMMA_R:
+         case BUILT_IN_LGAMMAF_R:
+         case BUILT_IN_LGAMMAL_R:
+         case BUILT_IN_MODF:
+         case BUILT_IN_MODFF:
+         case BUILT_IN_MODFL:
+         case BUILT_IN_REMQUO:
+         case BUILT_IN_REMQUOF:
+         case BUILT_IN_REMQUOL:
+         case BUILT_IN_FREE:
+           return;
+         /* printf-style functions may have hooks to set pointers to
+            point to somewhere into the generated string.  Leave them
+            for a later excercise...  */
+         default:
+           /* Fallthru to general call handling.  */;
+         }
       if (!in_ipa_mode)
        {
          VEC(ce_s, heap) *rhsc = NULL;
@@ -3724,7 +3844,6 @@ find_func_aliases (gimple origt)
        do_structure_copy (lhsop, rhsop);
       else
        {
-         unsigned int j;
          struct constraint_expr temp;
          get_constraint_for (lhsop, &lhsc);
 
@@ -3743,14 +3862,7 @@ find_func_aliases (gimple origt)
              temp.offset = 0;
              VEC_safe_push (ce_s, heap, rhsc, &temp);
            }
-         for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
-           {
-             struct constraint_expr *c2;
-             unsigned int k;
-
-             for (k = 0; VEC_iterate (ce_s, rhsc, k, c2); k++)
-               process_constraint (new_constraint (*c, *c2));
-           }
+         process_all_all_constraints (lhsc, rhsc);
        }
       /* If there is a store to a global variable the rhs escapes.  */
       if ((lhsop = get_base_address (lhsop)) != NULL_TREE