ipa-polymorphic-call.c (extr_type_from_vtbl_store): Do better pattern matching of...
authorJan Hubicka <hubicka@ucw.cz>
Wed, 8 Oct 2014 17:10:00 +0000 (19:10 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 8 Oct 2014 17:10:00 +0000 (17:10 +0000)
* ipa-polymorphic-call.c (extr_type_from_vtbl_store): Do better
pattern matching of MEM_REF.
(check_stmt_for_type_change): Update.

From-SVN: r216010

gcc/ChangeLog
gcc/ipa-polymorphic-call.c

index 5c91c38ffd84f8063951e8fa173dfacfa6b1255a..eefb8fc31309e9e643175d4f05cccc50ce999d5a 100644 (file)
@@ -1,3 +1,9 @@
+2014-10-07  Jan Hubicka  <hubicka@ucw.cz>
+
+       * ipa-polymorphic-call.c (extr_type_from_vtbl_store): Do better
+       pattern matching of MEM_REF.
+       (check_stmt_for_type_change): Update.
+
 2014-10-08  Steve Ellcey  <sellcey@mips.com>
 
        * config/mips/linux64.h: Remove.
index 3e4aa042c3cd8800665b13f3e8db838a90d8ce35..51c6709a86555ff0ffc684bc59b696c099ae6cab 100644 (file)
@@ -1140,7 +1140,8 @@ noncall_stmt_may_be_vtbl_ptr_store (gimple stmt)
 
 /* If STMT can be proved to be an assignment to the virtual method table
    pointer of ANALYZED_OBJ and the type associated with the new table
-   identified, return the type.  Otherwise return NULL_TREE.  */
+   identified, return the type.  Otherwise return NULL_TREE if type changes
+   in unknown way or ERROR_MARK_NODE if type is unchanged.  */
 
 static tree
 extr_type_from_vtbl_ptr_store (gimple stmt, struct type_change_info *tci,
@@ -1167,15 +1168,6 @@ extr_type_from_vtbl_ptr_store (gimple stmt, struct type_change_info *tci,
   else
     {
       base = get_ref_base_and_extent (lhs, &offset, &size, &max_size);
-      if (offset != tci->offset
-         || size != POINTER_SIZE
-         || max_size != POINTER_SIZE)
-       {
-         if (dump_file)
-           fprintf (dump_file, "    wrong offset %i!=%i or size %i\n",
-                    (int)offset, (int)tci->offset, (int)size);
-         return NULL_TREE;
-       }
       if (DECL_P (tci->instance))
        {
          if (base != tci->instance)
@@ -1193,19 +1185,35 @@ extr_type_from_vtbl_ptr_store (gimple stmt, struct type_change_info *tci,
        }
       else if (TREE_CODE (base) == MEM_REF)
        {
-         if (!operand_equal_p (tci->instance, TREE_OPERAND (base, 0), 0)
-             || !integer_zerop (TREE_OPERAND (base, 1)))
+         if (!operand_equal_p (tci->instance, TREE_OPERAND (base, 0), 0))
            {
              if (dump_file)
                {
                  fprintf (dump_file, "    base mem ref:");
                  print_generic_expr (dump_file, base, TDF_SLIM);
-                 fprintf (dump_file, " has nonzero offset or does not match instance:");
+                 fprintf (dump_file, " does not match instance:");
                  print_generic_expr (dump_file, tci->instance, TDF_SLIM);
                  fprintf (dump_file, "\n");
                }
              return NULL_TREE;
            }
+         if (!integer_zerop (TREE_OPERAND (base, 1)))
+           {
+             if (!tree_fits_shwi_p (TREE_OPERAND (base, 1)))
+               {
+                 if (dump_file)
+                   {
+                     fprintf (dump_file, "    base mem ref:");
+                     print_generic_expr (dump_file, base, TDF_SLIM);
+                     fprintf (dump_file, " has non-representable offset:");
+                     print_generic_expr (dump_file, tci->instance, TDF_SLIM);
+                     fprintf (dump_file, "\n");
+                   }
+                 return NULL_TREE;
+               }
+             else
+               offset += tree_to_shwi (TREE_OPERAND (base, 1)) * BITS_PER_UNIT;
+           }
        }
       else if (!operand_equal_p (tci->instance, base, 0)
               || tci->offset)
@@ -1218,7 +1226,19 @@ extr_type_from_vtbl_ptr_store (gimple stmt, struct type_change_info *tci,
              print_generic_expr (dump_file, tci->instance, TDF_SLIM);
              fprintf (dump_file, " with offset %i\n", (int)tci->offset);
            }
-         return NULL_TREE;
+         return tci->offset > GET_MODE_BITSIZE (Pmode) ? error_mark_node : NULL_TREE;
+       }
+      if (offset != tci->offset
+         || size != POINTER_SIZE
+         || max_size != POINTER_SIZE)
+       {
+         if (dump_file)
+           fprintf (dump_file, "    wrong offset %i!=%i or size %i\n",
+                    (int)offset, (int)tci->offset, (int)size);
+         return offset + GET_MODE_BITSIZE (Pmode) <= offset
+                || (max_size != -1
+                    && tci->offset + GET_MODE_BITSIZE (Pmode) > offset + max_size)
+                ? error_mark_node : NULL;
        }
     }
 
@@ -1405,6 +1425,8 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
 
       type = extr_type_from_vtbl_ptr_store (stmt, tci, &offset);
       gcc_assert (!type || TYPE_MAIN_VARIANT (type) == type);
+      if (type == error_mark_node)
+       return false;
       if (!type)
        {
          if (dump_file)