]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree-object-size.c
[arm] Perform early splitting of adddi3.
[thirdparty/gcc.git] / gcc / tree-object-size.c
index 459e65d40a6cb73c5a94b5993674b1d3529e96b7..6e79bbd1d917fe8e49869ad4a939e9cfb4578b86 100644 (file)
@@ -1,5 +1,5 @@
 /* __builtin_object_size (ptr, object_size_type) computation
-   Copyright (C) 2004-2015 Free Software Foundation, Inc.
+   Copyright (C) 2004-2019 Free Software Foundation, Inc.
    Contributed by Jakub Jelinek <jakub@redhat.com>
 
 This file is part of GCC.
@@ -32,22 +32,30 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-fold.h"
 #include "gimple-iterator.h"
 #include "tree-cfg.h"
+#include "stringpool.h"
+#include "attribs.h"
 
 struct object_size_info
 {
   int object_size_type;
-  bitmap visited, reexamine;
-  int pass;
+  unsigned char pass;
   bool changed;
+  bitmap visited, reexamine;
   unsigned int *depths;
   unsigned int *stack, *tos;
 };
 
-static const unsigned HOST_WIDE_INT unknown[4] = { -1, -1, 0, 0 };
+static const unsigned HOST_WIDE_INT unknown[4] = {
+  HOST_WIDE_INT_M1U,
+  HOST_WIDE_INT_M1U,
+  0,
+  0
+};
 
 static tree compute_object_offset (const_tree, const_tree);
-static unsigned HOST_WIDE_INT addr_object_size (struct object_size_info *,
-                                               const_tree, int);
+static bool addr_object_size (struct object_size_info *,
+                             const_tree, int, unsigned HOST_WIDE_INT *,
+                             tree * = NULL);
 static unsigned HOST_WIDE_INT alloc_object_size (const gcall *, int);
 static tree pass_through_call (const gcall *);
 static void collect_object_sizes_for (struct object_size_info *, tree);
@@ -133,13 +141,18 @@ compute_object_offset (const_tree expr, const_tree var)
        return base;
 
       t = TREE_OPERAND (expr, 1);
+      tree low_bound, unit_size;
+      low_bound = array_ref_low_bound (CONST_CAST_TREE (expr));
+      unit_size = array_ref_element_size (CONST_CAST_TREE (expr));
+      if (! integer_zerop (low_bound))
+       t = fold_build2 (MINUS_EXPR, TREE_TYPE (t), t, low_bound);
       if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
        {
          code = MINUS_EXPR;
          t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
        }
       t = fold_convert (sizetype, t);
-      off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+      off = size_binop (MULT_EXPR, unit_size, t);
       break;
 
     case MEM_REF:
@@ -158,14 +171,23 @@ compute_object_offset (const_tree expr, const_tree var)
    OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
    If unknown, return unknown[object_size_type].  */
 
-static unsigned HOST_WIDE_INT
+static bool
 addr_object_size (struct object_size_info *osi, const_tree ptr,
-                 int object_size_type)
+                 int object_size_type, unsigned HOST_WIDE_INT *psize,
+                 tree *pdecl /* = NULL */)
 {
   tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
 
+  tree dummy;
+  if (!pdecl)
+    pdecl = &dummy;
+
   gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
 
+  /* Set to unknown and overwrite just before returning if the size
+     could be determined.  */
+  *psize = unknown[object_size_type];
+
   pt_var = TREE_OPERAND (ptr, 0);
   while (handled_component_p (pt_var))
     pt_var = TREE_OPERAND (pt_var, 0);
@@ -178,8 +200,8 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
       if (!osi || (object_size_type & 1) != 0
          || TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
        {
-         sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
-                                           object_size_type & ~1);
+         compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
+                                      object_size_type & ~1, &sz, pdecl);
        }
       else
        {
@@ -194,11 +216,17 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
        }
       if (sz != unknown[object_size_type])
        {
-         offset_int dsz = wi::sub (sz, mem_ref_offset (pt_var));
-         if (wi::neg_p (dsz))
-           sz = 0;
-         else if (wi::fits_uhwi_p (dsz))
-           sz = dsz.to_uhwi ();
+         offset_int mem_offset;
+         if (mem_ref_offset (pt_var).is_constant (&mem_offset))
+           {
+             offset_int dsz = wi::sub (sz, mem_offset);
+             if (wi::neg_p (dsz))
+               sz = 0;
+             else if (wi::fits_uhwi_p (dsz))
+               sz = dsz.to_uhwi ();
+             else
+               sz = unknown[object_size_type];
+           }
          else
            sz = unknown[object_size_type];
        }
@@ -210,7 +238,10 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
           && DECL_P (pt_var)
           && tree_fits_uhwi_p (DECL_SIZE_UNIT (pt_var))
           && tree_to_uhwi (DECL_SIZE_UNIT (pt_var)) < offset_limit)
-    pt_var_size = DECL_SIZE_UNIT (pt_var);
+    {
+      *pdecl = pt_var;
+      pt_var_size = DECL_SIZE_UNIT (pt_var);
+    }
   else if (pt_var
           && TREE_CODE (pt_var) == STRING_CST
           && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
@@ -219,7 +250,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
              < offset_limit)
     pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
   else
-    return unknown[object_size_type];
+    return false;
 
   if (pt_var != TREE_OPERAND (ptr, 0))
     {
@@ -334,7 +365,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
       if (var != pt_var)
        var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
       else if (!pt_var_size)
-       return unknown[object_size_type];
+       return false;
       else
        var_size = pt_var_size;
       bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
@@ -364,37 +395,43 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
        }
     }
   else if (!pt_var_size)
-    return unknown[object_size_type];
+    return false;
   else
     bytes = pt_var_size;
 
   if (tree_fits_uhwi_p (bytes))
-    return tree_to_uhwi (bytes);
+    {
+      *psize = tree_to_uhwi (bytes);
+      return true;
+    }
 
-  return unknown[object_size_type];
+  return false;
 }
 
 
 /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
-   Handles various allocation calls.  OBJECT_SIZE_TYPE is the second
-   argument from __builtin_object_size.  If unknown, return
-   unknown[object_size_type].  */
+   Handles calls to functions declared with attribute alloc_size.
+   OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
+   If unknown, return unknown[object_size_type].  */
 
 static unsigned HOST_WIDE_INT
 alloc_object_size (const gcall *call, int object_size_type)
 {
-  tree callee, bytes = NULL_TREE;
-  tree alloc_size;
-  int arg1 = -1, arg2 = -1;
-
   gcc_assert (is_gimple_call (call));
 
-  callee = gimple_call_fndecl (call);
-  if (!callee)
+  tree calltype;
+  if (tree callfn = gimple_call_fndecl (call))
+    calltype = TREE_TYPE (callfn);
+  else
+    calltype = gimple_call_fntype (call);
+
+  if (!calltype)
     return unknown[object_size_type];
 
-  alloc_size = lookup_attribute ("alloc_size",
-                                TYPE_ATTRIBUTES (TREE_TYPE (callee)));
+  /* Set to positions of alloc_size arguments.  */
+  int arg1 = -1, arg2 = -1;
+  tree alloc_size = lookup_attribute ("alloc_size",
+                                     TYPE_ATTRIBUTES (calltype));
   if (alloc_size && TREE_VALUE (alloc_size))
     {
       tree p = TREE_VALUE (alloc_size);
@@ -404,20 +441,6 @@ alloc_object_size (const gcall *call, int object_size_type)
         arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1;
     }
 
-  if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
-    switch (DECL_FUNCTION_CODE (callee))
-      {
-      case BUILT_IN_CALLOC:
-       arg2 = 1;
-       /* fall through */
-      case BUILT_IN_MALLOC:
-      case BUILT_IN_ALLOCA:
-      case BUILT_IN_ALLOCA_WITH_ALIGN:
-       arg1 = 0;
-      default:
-       break;
-      }
-
   if (arg1 < 0 || arg1 >= (int)gimple_call_num_args (call)
       || TREE_CODE (gimple_call_arg (call, arg1)) != INTEGER_CST
       || (arg2 >= 0
@@ -425,6 +448,7 @@ alloc_object_size (const gcall *call, int object_size_type)
              || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST)))
     return unknown[object_size_type];
 
+  tree bytes = NULL_TREE;
   if (arg2 >= 0)
     bytes = size_binop (MULT_EXPR,
        fold_convert (sizetype, gimple_call_arg (call, arg1)),
@@ -446,175 +470,197 @@ alloc_object_size (const gcall *call, int object_size_type)
 static tree
 pass_through_call (const gcall *call)
 {
-  tree callee = gimple_call_fndecl (call);
+  unsigned rf = gimple_call_return_flags (call);
+  if (rf & ERF_RETURNS_ARG)
+    {
+      unsigned argnum = rf & ERF_RETURN_ARG_MASK;
+      if (argnum < gimple_call_num_args (call))
+       return gimple_call_arg (call, argnum);
+    }
 
-  if (callee
-      && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
-    switch (DECL_FUNCTION_CODE (callee))
-      {
-      case BUILT_IN_MEMCPY:
-      case BUILT_IN_MEMMOVE:
-      case BUILT_IN_MEMSET:
-      case BUILT_IN_STRCPY:
-      case BUILT_IN_STRNCPY:
-      case BUILT_IN_STRCAT:
-      case BUILT_IN_STRNCAT:
-      case BUILT_IN_MEMCPY_CHK:
-      case BUILT_IN_MEMMOVE_CHK:
-      case BUILT_IN_MEMSET_CHK:
-      case BUILT_IN_STRCPY_CHK:
-      case BUILT_IN_STRNCPY_CHK:
-      case BUILT_IN_STPNCPY_CHK:
-      case BUILT_IN_STRCAT_CHK:
-      case BUILT_IN_STRNCAT_CHK:
-      case BUILT_IN_ASSUME_ALIGNED:
-       if (gimple_call_num_args (call) >= 1)
-         return gimple_call_arg (call, 0);
-       break;
-      default:
-       break;
-      }
+  /* __builtin_assume_aligned is intentionally not marked RET1.  */
+  if (gimple_call_builtin_p (call, BUILT_IN_ASSUME_ALIGNED))
+    return gimple_call_arg (call, 0);
 
   return NULL_TREE;
 }
 
 
-/* Compute __builtin_object_size value for PTR.  OBJECT_SIZE_TYPE is the
-   second argument from __builtin_object_size.  */
+/* Compute __builtin_object_size value for PTR and set *PSIZE to
+   the resulting value.  If the declared object is known and PDECL
+   is nonnull, sets *PDECL to the object's DECL.  OBJECT_SIZE_TYPE
+   is the second argument   to __builtin_object_size.
+   Returns true on success and false when the object size could not
+   be determined.  */
 
-unsigned HOST_WIDE_INT
-compute_builtin_object_size (tree ptr, int object_size_type)
+bool
+compute_builtin_object_size (tree ptr, int object_size_type,
+                            unsigned HOST_WIDE_INT *psize,
+                            tree *pdecl /* = NULL */)
 {
   gcc_assert (object_size_type >= 0 && object_size_type <= 3);
 
+  /* Set to unknown and overwrite just before returning if the size
+     could be determined.  */
+  *psize = unknown[object_size_type];
+
   if (! offset_limit)
     init_offset_limit ();
 
   if (TREE_CODE (ptr) == ADDR_EXPR)
-    return addr_object_size (NULL, ptr, object_size_type);
+    return addr_object_size (NULL, ptr, object_size_type, psize, pdecl);
 
-  if (TREE_CODE (ptr) == SSA_NAME
-      && POINTER_TYPE_P (TREE_TYPE (ptr))
-      && computed[object_size_type] != NULL)
+  if (TREE_CODE (ptr) != SSA_NAME
+      || !POINTER_TYPE_P (TREE_TYPE (ptr)))
+      return false;
+
+  if (computed[object_size_type] == NULL)
     {
-      if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
+      if (optimize || object_size_type & 1)
+       return false;
+
+      /* When not optimizing, rather than failing, make a small effort
+        to determine the object size without the full benefit of
+        the (costly) computation below.  */
+      gimple *def = SSA_NAME_DEF_STMT (ptr);
+      if (gimple_code (def) == GIMPLE_ASSIGN)
        {
-         struct object_size_info osi;
-         bitmap_iterator bi;
-         unsigned int i;
-
-         if (num_ssa_names > object_sizes[object_size_type].length ())
-           object_sizes[object_size_type].safe_grow (num_ssa_names);
-         if (dump_file)
+         tree_code code = gimple_assign_rhs_code (def);
+         if (code == POINTER_PLUS_EXPR)
            {
-             fprintf (dump_file, "Computing %s %sobject size for ",
-                      (object_size_type & 2) ? "minimum" : "maximum",
-                      (object_size_type & 1) ? "sub" : "");
-             print_generic_expr (dump_file, ptr, dump_flags);
-             fprintf (dump_file, ":\n");
-           }
+             tree offset = gimple_assign_rhs2 (def);
+             ptr = gimple_assign_rhs1 (def);
 
-         osi.visited = BITMAP_ALLOC (NULL);
-         osi.reexamine = BITMAP_ALLOC (NULL);
-         osi.object_size_type = object_size_type;
-         osi.depths = NULL;
-         osi.stack = NULL;
-         osi.tos = NULL;
-
-         /* First pass: walk UD chains, compute object sizes that
-            can be computed.  osi.reexamine bitmap at the end will
-            contain what variables were found in dependency cycles
-            and therefore need to be reexamined.  */
-         osi.pass = 0;
-         osi.changed = false;
-         collect_object_sizes_for (&osi, ptr);
-
-         /* Second pass: keep recomputing object sizes of variables
-            that need reexamination, until no object sizes are
-            increased or all object sizes are computed.  */
-         if (! bitmap_empty_p (osi.reexamine))
-           {
-             bitmap reexamine = BITMAP_ALLOC (NULL);
-
-             /* If looking for minimum instead of maximum object size,
-                detect cases where a pointer is increased in a loop.
-                Although even without this detection pass 2 would eventually
-                terminate, it could take a long time.  If a pointer is
-                increasing this way, we need to assume 0 object size.
-                E.g. p = &buf[0]; while (cond) p = p + 4;  */
-             if (object_size_type & 2)
+             if (tree_fits_shwi_p (offset)
+                 && compute_builtin_object_size (ptr, object_size_type,
+                                                 psize, pdecl))
                {
-                 osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
-                 osi.stack = XNEWVEC (unsigned int, num_ssa_names);
-                 osi.tos = osi.stack;
-                 osi.pass = 1;
-                 /* collect_object_sizes_for is changing
-                    osi.reexamine bitmap, so iterate over a copy.  */
-                 bitmap_copy (reexamine, osi.reexamine);
-                 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
-                   if (bitmap_bit_p (osi.reexamine, i))
-                     check_for_plus_in_loops (&osi, ssa_name (i));
-
-                 free (osi.depths);
-                 osi.depths = NULL;
-                 free (osi.stack);
-                 osi.stack = NULL;
-                 osi.tos = NULL;
+                 /* Return zero when the offset is out of bounds.  */
+                 unsigned HOST_WIDE_INT off = tree_to_shwi (offset);
+                 *psize = off < *psize ? *psize - off : 0;
+                 return true;
                }
+           }
+       }
+      return false;
+    }
 
-             do
-               {
-                 osi.pass = 2;
-                 osi.changed = false;
-                 /* collect_object_sizes_for is changing
-                    osi.reexamine bitmap, so iterate over a copy.  */
-                 bitmap_copy (reexamine, osi.reexamine);
-                 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
-                   if (bitmap_bit_p (osi.reexamine, i))
-                     {
-                       collect_object_sizes_for (&osi, ssa_name (i));
-                       if (dump_file && (dump_flags & TDF_DETAILS))
-                         {
-                           fprintf (dump_file, "Reexamining ");
-                           print_generic_expr (dump_file, ssa_name (i),
-                                               dump_flags);
-                           fprintf (dump_file, "\n");
-                         }
-                     }
-               }
-             while (osi.changed);
+  if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
+    {
+      struct object_size_info osi;
+      bitmap_iterator bi;
+      unsigned int i;
+
+      if (num_ssa_names > object_sizes[object_size_type].length ())
+       object_sizes[object_size_type].safe_grow (num_ssa_names);
+      if (dump_file)
+       {
+         fprintf (dump_file, "Computing %s %sobject size for ",
+                  (object_size_type & 2) ? "minimum" : "maximum",
+                  (object_size_type & 1) ? "sub" : "");
+         print_generic_expr (dump_file, ptr, dump_flags);
+         fprintf (dump_file, ":\n");
+       }
 
-             BITMAP_FREE (reexamine);
+      osi.visited = BITMAP_ALLOC (NULL);
+      osi.reexamine = BITMAP_ALLOC (NULL);
+      osi.object_size_type = object_size_type;
+      osi.depths = NULL;
+      osi.stack = NULL;
+      osi.tos = NULL;
+
+      /* First pass: walk UD chains, compute object sizes that
+        can be computed.  osi.reexamine bitmap at the end will
+        contain what variables were found in dependency cycles
+        and therefore need to be reexamined.  */
+      osi.pass = 0;
+      osi.changed = false;
+      collect_object_sizes_for (&osi, ptr);
+
+      /* Second pass: keep recomputing object sizes of variables
+        that need reexamination, until no object sizes are
+        increased or all object sizes are computed.  */
+      if (! bitmap_empty_p (osi.reexamine))
+       {
+         bitmap reexamine = BITMAP_ALLOC (NULL);
+
+         /* If looking for minimum instead of maximum object size,
+            detect cases where a pointer is increased in a loop.
+            Although even without this detection pass 2 would eventually
+            terminate, it could take a long time.  If a pointer is
+            increasing this way, we need to assume 0 object size.
+            E.g. p = &buf[0]; while (cond) p = p + 4;  */
+         if (object_size_type & 2)
+           {
+             osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
+             osi.stack = XNEWVEC (unsigned int, num_ssa_names);
+             osi.tos = osi.stack;
+             osi.pass = 1;
+             /* collect_object_sizes_for is changing
+                osi.reexamine bitmap, so iterate over a copy.  */
+             bitmap_copy (reexamine, osi.reexamine);
+             EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
+               if (bitmap_bit_p (osi.reexamine, i))
+                 check_for_plus_in_loops (&osi, ssa_name (i));
+
+             free (osi.depths);
+             osi.depths = NULL;
+             free (osi.stack);
+             osi.stack = NULL;
+             osi.tos = NULL;
            }
-         EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
-           bitmap_set_bit (computed[object_size_type], i);
 
-         /* Debugging dumps.  */
-         if (dump_file)
+         do
            {
-             EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
-               if (object_sizes[object_size_type][i]
-                   != unknown[object_size_type])
+             osi.pass = 2;
+             osi.changed = false;
+             /* collect_object_sizes_for is changing
+                osi.reexamine bitmap, so iterate over a copy.  */
+             bitmap_copy (reexamine, osi.reexamine);
+             EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
+               if (bitmap_bit_p (osi.reexamine, i))
                  {
-                   print_generic_expr (dump_file, ssa_name (i),
-                                       dump_flags);
-                   fprintf (dump_file,
-                            ": %s %sobject size "
-                            HOST_WIDE_INT_PRINT_UNSIGNED "\n",
-                            (object_size_type & 2) ? "minimum" : "maximum",
-                            (object_size_type & 1) ? "sub" : "",
-                            object_sizes[object_size_type][i]);
+                   collect_object_sizes_for (&osi, ssa_name (i));
+                   if (dump_file && (dump_flags & TDF_DETAILS))
+                     {
+                       fprintf (dump_file, "Reexamining ");
+                       print_generic_expr (dump_file, ssa_name (i),
+                                           dump_flags);
+                       fprintf (dump_file, "\n");
+                     }
                  }
            }
+         while (osi.changed);
 
-         BITMAP_FREE (osi.reexamine);
-         BITMAP_FREE (osi.visited);
+         BITMAP_FREE (reexamine);
        }
+      EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
+       bitmap_set_bit (computed[object_size_type], i);
 
-      return object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
+      /* Debugging dumps.  */
+      if (dump_file)
+       {
+         EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
+           if (object_sizes[object_size_type][i]
+               != unknown[object_size_type])
+             {
+               print_generic_expr (dump_file, ssa_name (i),
+                                   dump_flags);
+               fprintf (dump_file,
+                        ": %s %sobject size "
+                        HOST_WIDE_INT_PRINT_UNSIGNED "\n",
+                        (object_size_type & 2) ? "minimum" : "maximum",
+                        (object_size_type & 1) ? "sub" : "",
+                        object_sizes[object_size_type][i]);
+             }
+       }
+
+      BITMAP_FREE (osi.reexamine);
+      BITMAP_FREE (osi.visited);
     }
 
-  return unknown[object_size_type];
+  *psize = object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
+  return *psize != unknown[object_size_type];
 }
 
 /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME.  */
@@ -638,7 +684,7 @@ expr_object_size (struct object_size_info *osi, tree ptr, tree value)
              || !POINTER_TYPE_P (TREE_TYPE (value)));
 
   if (TREE_CODE (value) == ADDR_EXPR)
-    bytes = addr_object_size (osi, value, object_size_type);
+    addr_object_size (osi, value, object_size_type, &bytes);
   else
     bytes = unknown[object_size_type];
 
@@ -738,7 +784,7 @@ merge_object_sizes (struct object_size_info *osi, tree dest, tree orig,
   orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
   if (orig_bytes != unknown[object_size_type])
     orig_bytes = (offset > orig_bytes)
-                ? (unsigned HOST_WIDE_INT) 0 : orig_bytes - offset;
+                ? HOST_WIDE_INT_0U : orig_bytes - offset;
 
   if ((object_size_type & 2) == 0)
     {
@@ -804,7 +850,7 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt)
          unsigned HOST_WIDE_INT off = tree_to_uhwi (op1);
 
           /* op0 will be ADDR_EXPR here.  */
-         bytes = addr_object_size (osi, op0, object_size_type);
+         addr_object_size (osi, op0, object_size_type, &bytes);
          if (bytes == unknown[object_size_type])
            ;
          else if (off > offset_limit)
@@ -857,6 +903,9 @@ cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt)
   else
     expr_object_size (osi, var, then_);
 
+  if (object_sizes[object_size_type][varno] == unknown[object_size_type])
+    return reexamine;
+
   if (TREE_CODE (else_) == SSA_NAME)
     reexamine |= merge_object_sizes (osi, var, else_, 0);
   else
@@ -1183,7 +1232,7 @@ init_object_sizes (void)
 
 /* Destroy data structures after the object size computation.  */
 
-static void
+void
 fini_object_sizes (void)
 {
   int object_size_type;
@@ -1277,10 +1326,9 @@ pass_object_sizes::execute (function *fun)
                      && lhs)
                    {
                      tree type = TREE_TYPE (lhs);
-                     unsigned HOST_WIDE_INT bytes
-                       = compute_builtin_object_size (ptr, object_size_type);
-                     if (bytes != (unsigned HOST_WIDE_INT) (object_size_type == 1
-                                                            ? -1 : 0)
+                     unsigned HOST_WIDE_INT bytes;
+                     if (compute_builtin_object_size (ptr, object_size_type,
+                                                      &bytes)
                          && wi::fits_to_tree_p (bytes, type))
                        {
                          tree tem = make_ssa_name (type);
@@ -1329,7 +1377,7 @@ pass_object_sizes::execute (function *fun)
              fprintf (dump_file, "Simplified\n  ");
              print_gimple_stmt (dump_file, call, 0, dump_flags);
              fprintf (dump_file, " to ");
-             print_generic_expr (dump_file, result, 0);
+             print_generic_expr (dump_file, result);
              fprintf (dump_file, "\n");
            }