1/* __builtin_object_size (ptr, object_size_type) computation
2   Copyright (C) 2004-2015 Free Software Foundation, Inc.
3   Contributed by Jakub Jelinek <jakub@redhat.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3.  If not see
19<http://www.gnu.org/licenses/>.  */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "tm.h"
25#include "hash-set.h"
26#include "machmode.h"
27#include "vec.h"
28#include "double-int.h"
29#include "input.h"
30#include "alias.h"
31#include "symtab.h"
32#include "wide-int.h"
33#include "inchash.h"
34#include "tree.h"
35#include "fold-const.h"
36#include "tree-object-size.h"
37#include "diagnostic-core.h"
38#include "gimple-pretty-print.h"
39#include "bitmap.h"
40#include "predict.h"
41#include "hard-reg-set.h"
42#include "input.h"
43#include "function.h"
44#include "dominance.h"
45#include "cfg.h"
46#include "basic-block.h"
47#include "tree-ssa-alias.h"
48#include "internal-fn.h"
49#include "gimple-fold.h"
50#include "gimple-expr.h"
51#include "is-a.h"
52#include "gimple.h"
53#include "gimple-iterator.h"
54#include "gimple-ssa.h"
55#include "stringpool.h"
56#include "tree-ssanames.h"
57#include "tree-pass.h"
58#include "tree-ssa-propagate.h"
59#include "tree-phinodes.h"
60#include "ssa-iterators.h"
61#include "builtins.h"
62
63struct object_size_info
64{
65  int object_size_type;
66  bitmap visited, reexamine;
67  int pass;
68  bool changed;
69  unsigned int *depths;
70  unsigned int *stack, *tos;
71};
72
73static const unsigned HOST_WIDE_INT unknown[4] = { -1, -1, 0, 0 };
74
75static tree compute_object_offset (const_tree, const_tree);
76static unsigned HOST_WIDE_INT addr_object_size (struct object_size_info *,
77						const_tree, int);
78static unsigned HOST_WIDE_INT alloc_object_size (const gcall *, int);
79static tree pass_through_call (const gcall *);
80static void collect_object_sizes_for (struct object_size_info *, tree);
81static void expr_object_size (struct object_size_info *, tree, tree);
82static bool merge_object_sizes (struct object_size_info *, tree, tree,
83				unsigned HOST_WIDE_INT);
84static bool plus_stmt_object_size (struct object_size_info *, tree, gimple);
85static bool cond_expr_object_size (struct object_size_info *, tree, gimple);
86static void init_offset_limit (void);
87static void check_for_plus_in_loops (struct object_size_info *, tree);
88static void check_for_plus_in_loops_1 (struct object_size_info *, tree,
89				       unsigned int);
90
91/* object_sizes[0] is upper bound for number of bytes till the end of
92   the object.
93   object_sizes[1] is upper bound for number of bytes till the end of
94   the subobject (innermost array or field with address taken).
95   object_sizes[2] is lower bound for number of bytes till the end of
96   the object and object_sizes[3] lower bound for subobject.  */
97static vec<unsigned HOST_WIDE_INT> object_sizes[4];
98
99/* Bitmaps what object sizes have been computed already.  */
100static bitmap computed[4];
101
102/* Maximum value of offset we consider to be addition.  */
103static unsigned HOST_WIDE_INT offset_limit;
104
105
106/* Initialize OFFSET_LIMIT variable.  */
107static void
108init_offset_limit (void)
109{
110  if (tree_fits_uhwi_p (TYPE_MAX_VALUE (sizetype)))
111    offset_limit = tree_to_uhwi (TYPE_MAX_VALUE (sizetype));
112  else
113    offset_limit = -1;
114  offset_limit /= 2;
115}
116
117
118/* Compute offset of EXPR within VAR.  Return error_mark_node
119   if unknown.  */
120
121static tree
122compute_object_offset (const_tree expr, const_tree var)
123{
124  enum tree_code code = PLUS_EXPR;
125  tree base, off, t;
126
127  if (expr == var)
128    return size_zero_node;
129
130  switch (TREE_CODE (expr))
131    {
132    case COMPONENT_REF:
133      base = compute_object_offset (TREE_OPERAND (expr, 0), var);
134      if (base == error_mark_node)
135	return base;
136
137      t = TREE_OPERAND (expr, 1);
138      off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
139			size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
140				  / BITS_PER_UNIT));
141      break;
142
143    case REALPART_EXPR:
144    CASE_CONVERT:
145    case VIEW_CONVERT_EXPR:
146    case NON_LVALUE_EXPR:
147      return compute_object_offset (TREE_OPERAND (expr, 0), var);
148
149    case IMAGPART_EXPR:
150      base = compute_object_offset (TREE_OPERAND (expr, 0), var);
151      if (base == error_mark_node)
152	return base;
153
154      off = TYPE_SIZE_UNIT (TREE_TYPE (expr));
155      break;
156
157    case ARRAY_REF:
158      base = compute_object_offset (TREE_OPERAND (expr, 0), var);
159      if (base == error_mark_node)
160	return base;
161
162      t = TREE_OPERAND (expr, 1);
163      if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
164	{
165	  code = MINUS_EXPR;
166	  t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
167	}
168      t = fold_convert (sizetype, t);
169      off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
170      break;
171
172    case MEM_REF:
173      gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR);
174      return wide_int_to_tree (sizetype, mem_ref_offset (expr));
175
176    default:
177      return error_mark_node;
178    }
179
180  return size_binop (code, base, off);
181}
182
183
184/* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
185   OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
186   If unknown, return unknown[object_size_type].  */
187
188static unsigned HOST_WIDE_INT
189addr_object_size (struct object_size_info *osi, const_tree ptr,
190		  int object_size_type)
191{
192  tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
193
194  gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
195
196  pt_var = TREE_OPERAND (ptr, 0);
197  while (handled_component_p (pt_var))
198    pt_var = TREE_OPERAND (pt_var, 0);
199
200  if (pt_var
201      && TREE_CODE (pt_var) == MEM_REF)
202    {
203      unsigned HOST_WIDE_INT sz;
204
205      if (!osi || (object_size_type & 1) != 0
206	  || TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
207	{
208	  sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
209					    object_size_type & ~1);
210	}
211      else
212	{
213	  tree var = TREE_OPERAND (pt_var, 0);
214	  if (osi->pass == 0)
215	    collect_object_sizes_for (osi, var);
216	  if (bitmap_bit_p (computed[object_size_type],
217			    SSA_NAME_VERSION (var)))
218	    sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)];
219	  else
220	    sz = unknown[object_size_type];
221	}
222      if (sz != unknown[object_size_type])
223	{
224	  offset_int dsz = wi::sub (sz, mem_ref_offset (pt_var));
225	  if (wi::neg_p (dsz))
226	    sz = 0;
227	  else if (wi::fits_uhwi_p (dsz))
228	    sz = dsz.to_uhwi ();
229	  else
230	    sz = unknown[object_size_type];
231	}
232
233      if (sz != unknown[object_size_type] && sz < offset_limit)
234	pt_var_size = size_int (sz);
235    }
236  else if (pt_var
237	   && DECL_P (pt_var)
238	   && tree_fits_uhwi_p (DECL_SIZE_UNIT (pt_var))
239	   && tree_to_uhwi (DECL_SIZE_UNIT (pt_var)) < offset_limit)
240    pt_var_size = DECL_SIZE_UNIT (pt_var);
241  else if (pt_var
242	   && TREE_CODE (pt_var) == STRING_CST
243	   && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
244	   && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)))
245	   && tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)))
246	      < offset_limit)
247    pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
248  else
249    return unknown[object_size_type];
250
251  if (pt_var != TREE_OPERAND (ptr, 0))
252    {
253      tree var;
254
255      if (object_size_type & 1)
256	{
257	  var = TREE_OPERAND (ptr, 0);
258
259	  while (var != pt_var
260		 && TREE_CODE (var) != BIT_FIELD_REF
261		 && TREE_CODE (var) != COMPONENT_REF
262		 && TREE_CODE (var) != ARRAY_REF
263		 && TREE_CODE (var) != ARRAY_RANGE_REF
264		 && TREE_CODE (var) != REALPART_EXPR
265		 && TREE_CODE (var) != IMAGPART_EXPR)
266	    var = TREE_OPERAND (var, 0);
267	  if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
268	    var = TREE_OPERAND (var, 0);
269	  if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
270	      || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var)))
271	      || (pt_var_size
272		  && tree_int_cst_lt (pt_var_size,
273				      TYPE_SIZE_UNIT (TREE_TYPE (var)))))
274	    var = pt_var;
275	  else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF)
276	    {
277	      tree v = var;
278	      /* For &X->fld, compute object size only if fld isn't the last
279		 field, as struct { int i; char c[1]; } is often used instead
280		 of flexible array member.  */
281	      while (v && v != pt_var)
282		switch (TREE_CODE (v))
283		  {
284		  case ARRAY_REF:
285		    if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0)))
286			&& TREE_CODE (TREE_OPERAND (v, 1)) == INTEGER_CST)
287		      {
288			tree domain
289			  = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0)));
290			if (domain
291			    && TYPE_MAX_VALUE (domain)
292			    && TREE_CODE (TYPE_MAX_VALUE (domain))
293			       == INTEGER_CST
294			    && tree_int_cst_lt (TREE_OPERAND (v, 1),
295						TYPE_MAX_VALUE (domain)))
296			  {
297			    v = NULL_TREE;
298			    break;
299			  }
300		      }
301		    v = TREE_OPERAND (v, 0);
302		    break;
303		  case REALPART_EXPR:
304		  case IMAGPART_EXPR:
305		    v = NULL_TREE;
306		    break;
307		  case COMPONENT_REF:
308		    if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
309		      {
310			v = NULL_TREE;
311			break;
312		      }
313		    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
314		      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
315			  != UNION_TYPE
316			  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
317			  != QUAL_UNION_TYPE)
318			break;
319		      else
320			v = TREE_OPERAND (v, 0);
321		    if (TREE_CODE (v) == COMPONENT_REF
322			&& TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
323			   == RECORD_TYPE)
324		      {
325			tree fld_chain = DECL_CHAIN (TREE_OPERAND (v, 1));
326			for (; fld_chain; fld_chain = DECL_CHAIN (fld_chain))
327			  if (TREE_CODE (fld_chain) == FIELD_DECL)
328			    break;
329
330			if (fld_chain)
331			  {
332			    v = NULL_TREE;
333			    break;
334			  }
335			v = TREE_OPERAND (v, 0);
336		      }
337		    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
338		      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
339			  != UNION_TYPE
340			  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
341			  != QUAL_UNION_TYPE)
342			break;
343		      else
344			v = TREE_OPERAND (v, 0);
345		    if (v != pt_var)
346		      v = NULL_TREE;
347		    else
348		      v = pt_var;
349		    break;
350		  default:
351		    v = pt_var;
352		    break;
353		  }
354	      if (v == pt_var)
355		var = pt_var;
356	    }
357	}
358      else
359	var = pt_var;
360
361      if (var != pt_var)
362	var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
363      else if (!pt_var_size)
364	return unknown[object_size_type];
365      else
366	var_size = pt_var_size;
367      bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
368      if (bytes != error_mark_node)
369	{
370	  if (TREE_CODE (bytes) == INTEGER_CST
371	      && tree_int_cst_lt (var_size, bytes))
372	    bytes = size_zero_node;
373	  else
374	    bytes = size_binop (MINUS_EXPR, var_size, bytes);
375	}
376      if (var != pt_var
377	  && pt_var_size
378	  && TREE_CODE (pt_var) == MEM_REF
379	  && bytes != error_mark_node)
380	{
381	  tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var);
382	  if (bytes2 != error_mark_node)
383	    {
384	      if (TREE_CODE (bytes2) == INTEGER_CST
385		  && tree_int_cst_lt (pt_var_size, bytes2))
386		bytes2 = size_zero_node;
387	      else
388		bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2);
389	      bytes = size_binop (MIN_EXPR, bytes, bytes2);
390	    }
391	}
392    }
393  else if (!pt_var_size)
394    return unknown[object_size_type];
395  else
396    bytes = pt_var_size;
397
398  if (tree_fits_uhwi_p (bytes))
399    return tree_to_uhwi (bytes);
400
401  return unknown[object_size_type];
402}
403
404
405/* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
406   Handles various allocation calls.  OBJECT_SIZE_TYPE is the second
407   argument from __builtin_object_size.  If unknown, return
408   unknown[object_size_type].  */
409
410static unsigned HOST_WIDE_INT
411alloc_object_size (const gcall *call, int object_size_type)
412{
413  tree callee, bytes = NULL_TREE;
414  tree alloc_size;
415  int arg1 = -1, arg2 = -1;
416
417  gcc_assert (is_gimple_call (call));
418
419  callee = gimple_call_fndecl (call);
420  if (!callee)
421    return unknown[object_size_type];
422
423  alloc_size = lookup_attribute ("alloc_size",
424				 TYPE_ATTRIBUTES (TREE_TYPE (callee)));
425  if (alloc_size && TREE_VALUE (alloc_size))
426    {
427      tree p = TREE_VALUE (alloc_size);
428
429      arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1;
430      if (TREE_CHAIN (p))
431        arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1;
432    }
433
434  if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
435    switch (DECL_FUNCTION_CODE (callee))
436      {
437      case BUILT_IN_CALLOC:
438	arg2 = 1;
439	/* fall through */
440      case BUILT_IN_MALLOC:
441      case BUILT_IN_ALLOCA:
442      case BUILT_IN_ALLOCA_WITH_ALIGN:
443	arg1 = 0;
444      default:
445	break;
446      }
447
448  if (arg1 < 0 || arg1 >= (int)gimple_call_num_args (call)
449      || TREE_CODE (gimple_call_arg (call, arg1)) != INTEGER_CST
450      || (arg2 >= 0
451	  && (arg2 >= (int)gimple_call_num_args (call)
452	      || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST)))
453    return unknown[object_size_type];
454
455  if (arg2 >= 0)
456    bytes = size_binop (MULT_EXPR,
457	fold_convert (sizetype, gimple_call_arg (call, arg1)),
458	fold_convert (sizetype, gimple_call_arg (call, arg2)));
459  else if (arg1 >= 0)
460    bytes = fold_convert (sizetype, gimple_call_arg (call, arg1));
461
462  if (bytes && tree_fits_uhwi_p (bytes))
463    return tree_to_uhwi (bytes);
464
465  return unknown[object_size_type];
466}
467
468
469/* If object size is propagated from one of function's arguments directly
470   to its return value, return that argument for GIMPLE_CALL statement CALL.
471   Otherwise return NULL.  */
472
473static tree
474pass_through_call (const gcall *call)
475{
476  tree callee = gimple_call_fndecl (call);
477
478  if (callee
479      && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
480    switch (DECL_FUNCTION_CODE (callee))
481      {
482      case BUILT_IN_MEMCPY:
483      case BUILT_IN_MEMMOVE:
484      case BUILT_IN_MEMSET:
485      case BUILT_IN_STRCPY:
486      case BUILT_IN_STRNCPY:
487      case BUILT_IN_STRCAT:
488      case BUILT_IN_STRNCAT:
489      case BUILT_IN_MEMCPY_CHK:
490      case BUILT_IN_MEMMOVE_CHK:
491      case BUILT_IN_MEMSET_CHK:
492      case BUILT_IN_STRCPY_CHK:
493      case BUILT_IN_STRNCPY_CHK:
494      case BUILT_IN_STPNCPY_CHK:
495      case BUILT_IN_STRCAT_CHK:
496      case BUILT_IN_STRNCAT_CHK:
497      case BUILT_IN_ASSUME_ALIGNED:
498	if (gimple_call_num_args (call) >= 1)
499	  return gimple_call_arg (call, 0);
500	break;
501      default:
502	break;
503      }
504
505  return NULL_TREE;
506}
507
508
509/* Compute __builtin_object_size value for PTR.  OBJECT_SIZE_TYPE is the
510   second argument from __builtin_object_size.  */
511
512unsigned HOST_WIDE_INT
513compute_builtin_object_size (tree ptr, int object_size_type)
514{
515  gcc_assert (object_size_type >= 0 && object_size_type <= 3);
516
517  if (! offset_limit)
518    init_offset_limit ();
519
520  if (TREE_CODE (ptr) == ADDR_EXPR)
521    return addr_object_size (NULL, ptr, object_size_type);
522
523  if (TREE_CODE (ptr) == SSA_NAME
524      && POINTER_TYPE_P (TREE_TYPE (ptr))
525      && computed[object_size_type] != NULL)
526    {
527      if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
528	{
529	  struct object_size_info osi;
530	  bitmap_iterator bi;
531	  unsigned int i;
532
533	  if (num_ssa_names > object_sizes[object_size_type].length ())
534	    object_sizes[object_size_type].safe_grow (num_ssa_names);
535	  if (dump_file)
536	    {
537	      fprintf (dump_file, "Computing %s %sobject size for ",
538		       (object_size_type & 2) ? "minimum" : "maximum",
539		       (object_size_type & 1) ? "sub" : "");
540	      print_generic_expr (dump_file, ptr, dump_flags);
541	      fprintf (dump_file, ":\n");
542	    }
543
544	  osi.visited = BITMAP_ALLOC (NULL);
545	  osi.reexamine = BITMAP_ALLOC (NULL);
546	  osi.object_size_type = object_size_type;
547	  osi.depths = NULL;
548	  osi.stack = NULL;
549	  osi.tos = NULL;
550
551	  /* First pass: walk UD chains, compute object sizes that
552	     can be computed.  osi.reexamine bitmap at the end will
553	     contain what variables were found in dependency cycles
554	     and therefore need to be reexamined.  */
555	  osi.pass = 0;
556	  osi.changed = false;
557	  collect_object_sizes_for (&osi, ptr);
558
559	  /* Second pass: keep recomputing object sizes of variables
560	     that need reexamination, until no object sizes are
561	     increased or all object sizes are computed.  */
562	  if (! bitmap_empty_p (osi.reexamine))
563	    {
564	      bitmap reexamine = BITMAP_ALLOC (NULL);
565
566	      /* If looking for minimum instead of maximum object size,
567		 detect cases where a pointer is increased in a loop.
568		 Although even without this detection pass 2 would eventually
569		 terminate, it could take a long time.  If a pointer is
570		 increasing this way, we need to assume 0 object size.
571		 E.g. p = &buf[0]; while (cond) p = p + 4;  */
572	      if (object_size_type & 2)
573		{
574		  osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
575		  osi.stack = XNEWVEC (unsigned int, num_ssa_names);
576		  osi.tos = osi.stack;
577		  osi.pass = 1;
578		  /* collect_object_sizes_for is changing
579		     osi.reexamine bitmap, so iterate over a copy.  */
580		  bitmap_copy (reexamine, osi.reexamine);
581		  EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
582		    if (bitmap_bit_p (osi.reexamine, i))
583		      check_for_plus_in_loops (&osi, ssa_name (i));
584
585		  free (osi.depths);
586		  osi.depths = NULL;
587		  free (osi.stack);
588		  osi.stack = NULL;
589		  osi.tos = NULL;
590		}
591
592	      do
593		{
594		  osi.pass = 2;
595		  osi.changed = false;
596		  /* collect_object_sizes_for is changing
597		     osi.reexamine bitmap, so iterate over a copy.  */
598		  bitmap_copy (reexamine, osi.reexamine);
599		  EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
600		    if (bitmap_bit_p (osi.reexamine, i))
601		      {
602			collect_object_sizes_for (&osi, ssa_name (i));
603			if (dump_file && (dump_flags & TDF_DETAILS))
604			  {
605			    fprintf (dump_file, "Reexamining ");
606			    print_generic_expr (dump_file, ssa_name (i),
607						dump_flags);
608			    fprintf (dump_file, "\n");
609			  }
610		      }
611		}
612	      while (osi.changed);
613
614	      BITMAP_FREE (reexamine);
615	    }
616	  EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
617	    bitmap_set_bit (computed[object_size_type], i);
618
619	  /* Debugging dumps.  */
620	  if (dump_file)
621	    {
622	      EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
623		if (object_sizes[object_size_type][i]
624		    != unknown[object_size_type])
625		  {
626		    print_generic_expr (dump_file, ssa_name (i),
627					dump_flags);
628		    fprintf (dump_file,
629			     ": %s %sobject size "
630			     HOST_WIDE_INT_PRINT_UNSIGNED "\n",
631			     (object_size_type & 2) ? "minimum" : "maximum",
632			     (object_size_type & 1) ? "sub" : "",
633			     object_sizes[object_size_type][i]);
634		  }
635	    }
636
637	  BITMAP_FREE (osi.reexamine);
638	  BITMAP_FREE (osi.visited);
639	}
640
641      return object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
642    }
643
644  return unknown[object_size_type];
645}
646
647/* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME.  */
648
649static void
650expr_object_size (struct object_size_info *osi, tree ptr, tree value)
651{
652  int object_size_type = osi->object_size_type;
653  unsigned int varno = SSA_NAME_VERSION (ptr);
654  unsigned HOST_WIDE_INT bytes;
655
656  gcc_assert (object_sizes[object_size_type][varno]
657	      != unknown[object_size_type]);
658  gcc_assert (osi->pass == 0);
659
660  if (TREE_CODE (value) == WITH_SIZE_EXPR)
661    value = TREE_OPERAND (value, 0);
662
663  /* Pointer variables should have been handled by merge_object_sizes.  */
664  gcc_assert (TREE_CODE (value) != SSA_NAME
665	      || !POINTER_TYPE_P (TREE_TYPE (value)));
666
667  if (TREE_CODE (value) == ADDR_EXPR)
668    bytes = addr_object_size (osi, value, object_size_type);
669  else
670    bytes = unknown[object_size_type];
671
672  if ((object_size_type & 2) == 0)
673    {
674      if (object_sizes[object_size_type][varno] < bytes)
675	object_sizes[object_size_type][varno] = bytes;
676    }
677  else
678    {
679      if (object_sizes[object_size_type][varno] > bytes)
680	object_sizes[object_size_type][varno] = bytes;
681    }
682}
683
684
685/* Compute object_sizes for PTR, defined to the result of a call.  */
686
687static void
688call_object_size (struct object_size_info *osi, tree ptr, gcall *call)
689{
690  int object_size_type = osi->object_size_type;
691  unsigned int varno = SSA_NAME_VERSION (ptr);
692  unsigned HOST_WIDE_INT bytes;
693
694  gcc_assert (is_gimple_call (call));
695
696  gcc_assert (object_sizes[object_size_type][varno]
697	      != unknown[object_size_type]);
698  gcc_assert (osi->pass == 0);
699
700  bytes = alloc_object_size (call, object_size_type);
701
702  if ((object_size_type & 2) == 0)
703    {
704      if (object_sizes[object_size_type][varno] < bytes)
705	object_sizes[object_size_type][varno] = bytes;
706    }
707  else
708    {
709      if (object_sizes[object_size_type][varno] > bytes)
710	object_sizes[object_size_type][varno] = bytes;
711    }
712}
713
714
715/* Compute object_sizes for PTR, defined to an unknown value.  */
716
717static void
718unknown_object_size (struct object_size_info *osi, tree ptr)
719{
720  int object_size_type = osi->object_size_type;
721  unsigned int varno = SSA_NAME_VERSION (ptr);
722  unsigned HOST_WIDE_INT bytes;
723
724  gcc_assert (object_sizes[object_size_type][varno]
725	      != unknown[object_size_type]);
726  gcc_assert (osi->pass == 0);
727
728  bytes = unknown[object_size_type];
729
730  if ((object_size_type & 2) == 0)
731    {
732      if (object_sizes[object_size_type][varno] < bytes)
733	object_sizes[object_size_type][varno] = bytes;
734    }
735  else
736    {
737      if (object_sizes[object_size_type][varno] > bytes)
738	object_sizes[object_size_type][varno] = bytes;
739    }
740}
741
742
743/* Merge object sizes of ORIG + OFFSET into DEST.  Return true if
744   the object size might need reexamination later.  */
745
746static bool
747merge_object_sizes (struct object_size_info *osi, tree dest, tree orig,
748		    unsigned HOST_WIDE_INT offset)
749{
750  int object_size_type = osi->object_size_type;
751  unsigned int varno = SSA_NAME_VERSION (dest);
752  unsigned HOST_WIDE_INT orig_bytes;
753
754  if (object_sizes[object_size_type][varno] == unknown[object_size_type])
755    return false;
756  if (offset >= offset_limit)
757    {
758      object_sizes[object_size_type][varno] = unknown[object_size_type];
759      return false;
760    }
761
762  if (osi->pass == 0)
763    collect_object_sizes_for (osi, orig);
764
765  orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
766  if (orig_bytes != unknown[object_size_type])
767    orig_bytes = (offset > orig_bytes)
768		 ? (unsigned HOST_WIDE_INT) 0 : orig_bytes - offset;
769
770  if ((object_size_type & 2) == 0)
771    {
772      if (object_sizes[object_size_type][varno] < orig_bytes)
773	{
774	  object_sizes[object_size_type][varno] = orig_bytes;
775	  osi->changed = true;
776	}
777    }
778  else
779    {
780      if (object_sizes[object_size_type][varno] > orig_bytes)
781	{
782	  object_sizes[object_size_type][varno] = orig_bytes;
783	  osi->changed = true;
784	}
785    }
786  return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig));
787}
788
789
790/* Compute object_sizes for VAR, defined to the result of an assignment
791   with operator POINTER_PLUS_EXPR.  Return true if the object size might
792   need reexamination  later.  */
793
794static bool
795plus_stmt_object_size (struct object_size_info *osi, tree var, gimple stmt)
796{
797  int object_size_type = osi->object_size_type;
798  unsigned int varno = SSA_NAME_VERSION (var);
799  unsigned HOST_WIDE_INT bytes;
800  tree op0, op1;
801
802  if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
803    {
804      op0 = gimple_assign_rhs1 (stmt);
805      op1 = gimple_assign_rhs2 (stmt);
806    }
807  else if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
808    {
809      tree rhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
810      gcc_assert (TREE_CODE (rhs) == MEM_REF);
811      op0 = TREE_OPERAND (rhs, 0);
812      op1 = TREE_OPERAND (rhs, 1);
813    }
814  else
815    gcc_unreachable ();
816
817  if (object_sizes[object_size_type][varno] == unknown[object_size_type])
818    return false;
819
820  /* Handle PTR + OFFSET here.  */
821  if (TREE_CODE (op1) == INTEGER_CST
822      && (TREE_CODE (op0) == SSA_NAME
823	  || TREE_CODE (op0) == ADDR_EXPR))
824    {
825      if (! tree_fits_uhwi_p (op1))
826	bytes = unknown[object_size_type];
827      else if (TREE_CODE (op0) == SSA_NAME)
828	return merge_object_sizes (osi, var, op0, tree_to_uhwi (op1));
829      else
830	{
831	  unsigned HOST_WIDE_INT off = tree_to_uhwi (op1);
832
833          /* op0 will be ADDR_EXPR here.  */
834	  bytes = addr_object_size (osi, op0, object_size_type);
835	  if (bytes == unknown[object_size_type])
836	    ;
837	  else if (off > offset_limit)
838	    bytes = unknown[object_size_type];
839	  else if (off > bytes)
840	    bytes = 0;
841	  else
842	    bytes -= off;
843	}
844    }
845  else
846    bytes = unknown[object_size_type];
847
848  if ((object_size_type & 2) == 0)
849    {
850      if (object_sizes[object_size_type][varno] < bytes)
851	object_sizes[object_size_type][varno] = bytes;
852    }
853  else
854    {
855      if (object_sizes[object_size_type][varno] > bytes)
856	object_sizes[object_size_type][varno] = bytes;
857    }
858  return false;
859}
860
861
862/* Compute object_sizes for VAR, defined at STMT, which is
863   a COND_EXPR.  Return true if the object size might need reexamination
864   later.  */
865
866static bool
867cond_expr_object_size (struct object_size_info *osi, tree var, gimple stmt)
868{
869  tree then_, else_;
870  int object_size_type = osi->object_size_type;
871  unsigned int varno = SSA_NAME_VERSION (var);
872  bool reexamine = false;
873
874  gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR);
875
876  if (object_sizes[object_size_type][varno] == unknown[object_size_type])
877    return false;
878
879  then_ = gimple_assign_rhs2 (stmt);
880  else_ = gimple_assign_rhs3 (stmt);
881
882  if (TREE_CODE (then_) == SSA_NAME)
883    reexamine |= merge_object_sizes (osi, var, then_, 0);
884  else
885    expr_object_size (osi, var, then_);
886
887  if (TREE_CODE (else_) == SSA_NAME)
888    reexamine |= merge_object_sizes (osi, var, else_, 0);
889  else
890    expr_object_size (osi, var, else_);
891
892  return reexamine;
893}
894
895/* Compute object sizes for VAR.
896   For ADDR_EXPR an object size is the number of remaining bytes
897   to the end of the object (where what is considered an object depends on
898   OSI->object_size_type).
899   For allocation GIMPLE_CALL like malloc or calloc object size is the size
900   of the allocation.
901   For POINTER_PLUS_EXPR where second operand is a constant integer,
902   object size is object size of the first operand minus the constant.
903   If the constant is bigger than the number of remaining bytes until the
904   end of the object, object size is 0, but if it is instead a pointer
905   subtraction, object size is unknown[object_size_type].
906   To differentiate addition from subtraction, ADDR_EXPR returns
907   unknown[object_size_type] for all objects bigger than half of the address
908   space, and constants less than half of the address space are considered
909   addition, while bigger constants subtraction.
910   For a memcpy like GIMPLE_CALL that always returns one of its arguments, the
911   object size is object size of that argument.
912   Otherwise, object size is the maximum of object sizes of variables
913   that it might be set to.  */
914
915static void
916collect_object_sizes_for (struct object_size_info *osi, tree var)
917{
918  int object_size_type = osi->object_size_type;
919  unsigned int varno = SSA_NAME_VERSION (var);
920  gimple stmt;
921  bool reexamine;
922
923  if (bitmap_bit_p (computed[object_size_type], varno))
924    return;
925
926  if (osi->pass == 0)
927    {
928      if (bitmap_set_bit (osi->visited, varno))
929	{
930	  object_sizes[object_size_type][varno]
931	    = (object_size_type & 2) ? -1 : 0;
932	}
933      else
934	{
935	  /* Found a dependency loop.  Mark the variable for later
936	     re-examination.  */
937	  bitmap_set_bit (osi->reexamine, varno);
938	  if (dump_file && (dump_flags & TDF_DETAILS))
939	    {
940	      fprintf (dump_file, "Found a dependency loop at ");
941	      print_generic_expr (dump_file, var, dump_flags);
942	      fprintf (dump_file, "\n");
943	    }
944	  return;
945	}
946    }
947
948  if (dump_file && (dump_flags & TDF_DETAILS))
949    {
950      fprintf (dump_file, "Visiting use-def links for ");
951      print_generic_expr (dump_file, var, dump_flags);
952      fprintf (dump_file, "\n");
953    }
954
955  stmt = SSA_NAME_DEF_STMT (var);
956  reexamine = false;
957
958  switch (gimple_code (stmt))
959    {
960    case GIMPLE_ASSIGN:
961      {
962	tree rhs = gimple_assign_rhs1 (stmt);
963        if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
964	    || (gimple_assign_rhs_code (stmt) == ADDR_EXPR
965		&& TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF))
966          reexamine = plus_stmt_object_size (osi, var, stmt);
967	else if (gimple_assign_rhs_code (stmt) == COND_EXPR)
968	  reexamine = cond_expr_object_size (osi, var, stmt);
969        else if (gimple_assign_single_p (stmt)
970                 || gimple_assign_unary_nop_p (stmt))
971          {
972            if (TREE_CODE (rhs) == SSA_NAME
973                && POINTER_TYPE_P (TREE_TYPE (rhs)))
974              reexamine = merge_object_sizes (osi, var, rhs, 0);
975            else
976              expr_object_size (osi, var, rhs);
977          }
978        else
979          unknown_object_size (osi, var);
980        break;
981      }
982
983    case GIMPLE_CALL:
984      {
985	gcall *call_stmt = as_a <gcall *> (stmt);
986        tree arg = pass_through_call (call_stmt);
987        if (arg)
988          {
989            if (TREE_CODE (arg) == SSA_NAME
990                && POINTER_TYPE_P (TREE_TYPE (arg)))
991              reexamine = merge_object_sizes (osi, var, arg, 0);
992            else
993              expr_object_size (osi, var, arg);
994          }
995        else
996          call_object_size (osi, var, call_stmt);
997	break;
998      }
999
1000    case GIMPLE_ASM:
1001      /* Pointers defined by __asm__ statements can point anywhere.  */
1002      object_sizes[object_size_type][varno] = unknown[object_size_type];
1003      break;
1004
1005    case GIMPLE_NOP:
1006      if (SSA_NAME_VAR (var)
1007	  && TREE_CODE (SSA_NAME_VAR (var)) == PARM_DECL)
1008	expr_object_size (osi, var, SSA_NAME_VAR (var));
1009      else
1010	/* Uninitialized SSA names point nowhere.  */
1011	object_sizes[object_size_type][varno] = unknown[object_size_type];
1012      break;
1013
1014    case GIMPLE_PHI:
1015      {
1016	unsigned i;
1017
1018	for (i = 0; i < gimple_phi_num_args (stmt); i++)
1019	  {
1020	    tree rhs = gimple_phi_arg (stmt, i)->def;
1021
1022	    if (object_sizes[object_size_type][varno]
1023		== unknown[object_size_type])
1024	      break;
1025
1026	    if (TREE_CODE (rhs) == SSA_NAME)
1027	      reexamine |= merge_object_sizes (osi, var, rhs, 0);
1028	    else if (osi->pass == 0)
1029	      expr_object_size (osi, var, rhs);
1030	  }
1031	break;
1032      }
1033
1034    default:
1035      gcc_unreachable ();
1036    }
1037
1038  if (! reexamine
1039      || object_sizes[object_size_type][varno] == unknown[object_size_type])
1040    {
1041      bitmap_set_bit (computed[object_size_type], varno);
1042      bitmap_clear_bit (osi->reexamine, varno);
1043    }
1044  else
1045    {
1046      bitmap_set_bit (osi->reexamine, varno);
1047      if (dump_file && (dump_flags & TDF_DETAILS))
1048	{
1049	  fprintf (dump_file, "Need to reexamine ");
1050	  print_generic_expr (dump_file, var, dump_flags);
1051	  fprintf (dump_file, "\n");
1052	}
1053    }
1054}
1055
1056
1057/* Helper function for check_for_plus_in_loops.  Called recursively
1058   to detect loops.  */
1059
1060static void
1061check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
1062			   unsigned int depth)
1063{
1064  gimple stmt = SSA_NAME_DEF_STMT (var);
1065  unsigned int varno = SSA_NAME_VERSION (var);
1066
1067  if (osi->depths[varno])
1068    {
1069      if (osi->depths[varno] != depth)
1070	{
1071	  unsigned int *sp;
1072
1073	  /* Found a loop involving pointer addition.  */
1074	  for (sp = osi->tos; sp > osi->stack; )
1075	    {
1076	      --sp;
1077	      bitmap_clear_bit (osi->reexamine, *sp);
1078	      bitmap_set_bit (computed[osi->object_size_type], *sp);
1079	      object_sizes[osi->object_size_type][*sp] = 0;
1080	      if (*sp == varno)
1081		break;
1082	    }
1083	}
1084      return;
1085    }
1086  else if (! bitmap_bit_p (osi->reexamine, varno))
1087    return;
1088
1089  osi->depths[varno] = depth;
1090  *osi->tos++ = varno;
1091
1092  switch (gimple_code (stmt))
1093    {
1094
1095    case GIMPLE_ASSIGN:
1096      {
1097        if ((gimple_assign_single_p (stmt)
1098             || gimple_assign_unary_nop_p (stmt))
1099            && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
1100          {
1101            tree rhs = gimple_assign_rhs1 (stmt);
1102
1103            check_for_plus_in_loops_1 (osi, rhs, depth);
1104          }
1105        else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1106          {
1107            tree basevar = gimple_assign_rhs1 (stmt);
1108            tree cst = gimple_assign_rhs2 (stmt);
1109
1110            gcc_assert (TREE_CODE (cst) == INTEGER_CST);
1111
1112            check_for_plus_in_loops_1 (osi, basevar,
1113                                       depth + !integer_zerop (cst));
1114          }
1115        else
1116          gcc_unreachable ();
1117        break;
1118      }
1119
1120    case GIMPLE_CALL:
1121      {
1122	gcall *call_stmt = as_a <gcall *> (stmt);
1123        tree arg = pass_through_call (call_stmt);
1124        if (arg)
1125          {
1126            if (TREE_CODE (arg) == SSA_NAME)
1127              check_for_plus_in_loops_1 (osi, arg, depth);
1128            else
1129              gcc_unreachable ();
1130          }
1131        break;
1132      }
1133
1134    case GIMPLE_PHI:
1135      {
1136	unsigned i;
1137
1138	for (i = 0; i < gimple_phi_num_args (stmt); i++)
1139	  {
1140	    tree rhs = gimple_phi_arg (stmt, i)->def;
1141
1142	    if (TREE_CODE (rhs) == SSA_NAME)
1143	      check_for_plus_in_loops_1 (osi, rhs, depth);
1144	  }
1145	break;
1146      }
1147
1148    default:
1149      gcc_unreachable ();
1150    }
1151
1152  osi->depths[varno] = 0;
1153  osi->tos--;
1154}
1155
1156
1157/* Check if some pointer we are computing object size of is being increased
1158   within a loop.  If yes, assume all the SSA variables participating in
1159   that loop have minimum object sizes 0.  */
1160
1161static void
1162check_for_plus_in_loops (struct object_size_info *osi, tree var)
1163{
1164  gimple stmt = SSA_NAME_DEF_STMT (var);
1165
1166  /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here,
1167     and looked for a POINTER_PLUS_EXPR in the pass-through
1168     argument, if any.  In GIMPLE, however, such an expression
1169     is not a valid call operand.  */
1170
1171  if (is_gimple_assign (stmt)
1172      && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1173    {
1174      tree basevar = gimple_assign_rhs1 (stmt);
1175      tree cst = gimple_assign_rhs2 (stmt);
1176
1177      gcc_assert (TREE_CODE (cst) == INTEGER_CST);
1178
1179      if (integer_zerop (cst))
1180        return;
1181
1182      osi->depths[SSA_NAME_VERSION (basevar)] = 1;
1183      *osi->tos++ = SSA_NAME_VERSION (basevar);
1184      check_for_plus_in_loops_1 (osi, var, 2);
1185      osi->depths[SSA_NAME_VERSION (basevar)] = 0;
1186      osi->tos--;
1187    }
1188}
1189
1190
1191/* Initialize data structures for the object size computation.  */
1192
1193void
1194init_object_sizes (void)
1195{
1196  int object_size_type;
1197
1198  if (computed[0])
1199    return;
1200
1201  for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1202    {
1203      object_sizes[object_size_type].safe_grow (num_ssa_names);
1204      computed[object_size_type] = BITMAP_ALLOC (NULL);
1205    }
1206
1207  init_offset_limit ();
1208}
1209
1210
1211/* Destroy data structures after the object size computation.  */
1212
1213static void
1214fini_object_sizes (void)
1215{
1216  int object_size_type;
1217
1218  for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1219    {
1220      object_sizes[object_size_type].release ();
1221      BITMAP_FREE (computed[object_size_type]);
1222    }
1223}
1224
1225
1226/* Simple pass to optimize all __builtin_object_size () builtins.  */
1227
1228namespace {
1229
1230const pass_data pass_data_object_sizes =
1231{
1232  GIMPLE_PASS, /* type */
1233  "objsz", /* name */
1234  OPTGROUP_NONE, /* optinfo_flags */
1235  TV_NONE, /* tv_id */
1236  ( PROP_cfg | PROP_ssa ), /* properties_required */
1237  0, /* properties_provided */
1238  0, /* properties_destroyed */
1239  0, /* todo_flags_start */
1240  0, /* todo_flags_finish */
1241};
1242
1243class pass_object_sizes : public gimple_opt_pass
1244{
1245public:
1246  pass_object_sizes (gcc::context *ctxt)
1247    : gimple_opt_pass (pass_data_object_sizes, ctxt)
1248  {}
1249
1250  /* opt_pass methods: */
1251  opt_pass * clone () { return new pass_object_sizes (m_ctxt); }
1252  virtual unsigned int execute (function *);
1253
1254}; // class pass_object_sizes
1255
1256unsigned int
1257pass_object_sizes::execute (function *fun)
1258{
1259  basic_block bb;
1260  FOR_EACH_BB_FN (bb, fun)
1261    {
1262      gimple_stmt_iterator i;
1263      for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
1264	{
1265	  tree result;
1266	  gimple call = gsi_stmt (i);
1267	  if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE))
1268	    continue;
1269
1270	  init_object_sizes ();
1271
1272	  /* In the first pass instance, only attempt to fold
1273	     __builtin_object_size (x, 1) and __builtin_object_size (x, 3),
1274	     and rather than folding the builtin to the constant if any,
1275	     create a MIN_EXPR or MAX_EXPR of the __builtin_object_size
1276	     call result and the computed constant.  */
1277	  if (first_pass_instance)
1278	    {
1279	      tree ost = gimple_call_arg (call, 1);
1280	      if (tree_fits_uhwi_p (ost))
1281		{
1282		  unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
1283		  tree ptr = gimple_call_arg (call, 0);
1284		  tree lhs = gimple_call_lhs (call);
1285		  if ((object_size_type == 1 || object_size_type == 3)
1286		      && (TREE_CODE (ptr) == ADDR_EXPR
1287			  || TREE_CODE (ptr) == SSA_NAME)
1288		      && lhs)
1289		    {
1290		      tree type = TREE_TYPE (lhs);
1291		      unsigned HOST_WIDE_INT bytes
1292			= compute_builtin_object_size (ptr, object_size_type);
1293		      if (bytes != (unsigned HOST_WIDE_INT) (object_size_type == 1
1294							     ? -1 : 0)
1295			  && wi::fits_to_tree_p (bytes, type))
1296			{
1297			  tree tem = make_ssa_name (type);
1298			  gimple_call_set_lhs (call, tem);
1299			  enum tree_code code
1300			    = object_size_type == 1 ? MIN_EXPR : MAX_EXPR;
1301			  tree cst = build_int_cstu (type, bytes);
1302			  gimple g = gimple_build_assign (lhs, code, tem, cst);
1303			  gsi_insert_after (&i, g, GSI_NEW_STMT);
1304			  update_stmt (call);
1305			}
1306		    }
1307		}
1308	      continue;
1309	    }
1310
1311	  result = fold_call_stmt (as_a <gcall *> (call), false);
1312	  if (!result)
1313	    {
1314	      tree ost = gimple_call_arg (call, 1);
1315
1316	      if (tree_fits_uhwi_p (ost))
1317		{
1318		  unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
1319
1320		  if (object_size_type < 2)
1321		    result = fold_convert (size_type_node,
1322					   integer_minus_one_node);
1323		  else if (object_size_type < 4)
1324		    result = build_zero_cst (size_type_node);
1325		}
1326
1327	      if (!result)
1328		continue;
1329	    }
1330
1331	  gcc_assert (TREE_CODE (result) == INTEGER_CST);
1332
1333	  if (dump_file && (dump_flags & TDF_DETAILS))
1334	    {
1335	      fprintf (dump_file, "Simplified\n  ");
1336	      print_gimple_stmt (dump_file, call, 0, dump_flags);
1337	      fprintf (dump_file, " to ");
1338	      print_generic_expr (dump_file, result, 0);
1339	      fprintf (dump_file, "\n");
1340	    }
1341
1342	  tree lhs = gimple_call_lhs (call);
1343	  if (!lhs)
1344	    continue;
1345
1346	  /* Propagate into all uses and fold those stmts.  */
1347	  gimple use_stmt;
1348	  imm_use_iterator iter;
1349	  FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
1350	    {
1351	      use_operand_p use_p;
1352	      FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
1353		SET_USE (use_p, result);
1354	      gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
1355	      fold_stmt (&gsi);
1356	      update_stmt (gsi_stmt (gsi));
1357	    }
1358	}
1359    }
1360
1361  fini_object_sizes ();
1362  return 0;
1363}
1364
1365} // anon namespace
1366
1367gimple_opt_pass *
1368make_pass_object_sizes (gcc::context *ctxt)
1369{
1370  return new pass_object_sizes (ctxt);
1371}
1372