comparison gcc/tree-object-size.c @ 16:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
comparison
equal deleted inserted replaced
15:561a7518be6b 16:04ced10e8804
1 /* __builtin_object_size (ptr, object_size_type) computation 1 /* __builtin_object_size (ptr, object_size_type) computation
2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 2 Copyright (C) 2004-2017 Free Software Foundation, Inc.
3 Free Software Foundation, Inc.
4 Contributed by Jakub Jelinek <jakub@redhat.com> 3 Contributed by Jakub Jelinek <jakub@redhat.com>
5 4
6 This file is part of GCC. 5 This file is part of GCC.
7 6
8 GCC is free software; you can redistribute it and/or modify 7 GCC is free software; you can redistribute it and/or modify
20 <http://www.gnu.org/licenses/>. */ 19 <http://www.gnu.org/licenses/>. */
21 20
22 #include "config.h" 21 #include "config.h"
23 #include "system.h" 22 #include "system.h"
24 #include "coretypes.h" 23 #include "coretypes.h"
25 #include "tm.h" 24 #include "backend.h"
26 #include "tree.h" 25 #include "tree.h"
27 #include "diagnostic-core.h" 26 #include "gimple.h"
28 #include "tree-pretty-print.h" 27 #include "tree-pass.h"
28 #include "ssa.h"
29 #include "gimple-pretty-print.h" 29 #include "gimple-pretty-print.h"
30 #include "tree-flow.h" 30 #include "fold-const.h"
31 #include "tree-pass.h" 31 #include "tree-object-size.h"
32 #include "tree-ssa-propagate.h" 32 #include "gimple-fold.h"
33 #include "gimple-iterator.h"
34 #include "tree-cfg.h"
35 #include "stringpool.h"
36 #include "attribs.h"
33 37
34 struct object_size_info 38 struct object_size_info
35 { 39 {
36 int object_size_type; 40 int object_size_type;
41 unsigned char pass;
42 bool changed;
37 bitmap visited, reexamine; 43 bitmap visited, reexamine;
38 int pass;
39 bool changed;
40 unsigned int *depths; 44 unsigned int *depths;
41 unsigned int *stack, *tos; 45 unsigned int *stack, *tos;
42 }; 46 };
43 47
44 static unsigned HOST_WIDE_INT unknown[4] = { -1, -1, 0, 0 }; 48 static const unsigned HOST_WIDE_INT unknown[4] = {
49 HOST_WIDE_INT_M1U,
50 HOST_WIDE_INT_M1U,
51 0,
52 0
53 };
45 54
46 static tree compute_object_offset (const_tree, const_tree); 55 static tree compute_object_offset (const_tree, const_tree);
47 static unsigned HOST_WIDE_INT addr_object_size (struct object_size_info *, 56 static bool addr_object_size (struct object_size_info *,
48 const_tree, int); 57 const_tree, int, unsigned HOST_WIDE_INT *);
49 static unsigned HOST_WIDE_INT alloc_object_size (const_gimple, int); 58 static unsigned HOST_WIDE_INT alloc_object_size (const gcall *, int);
50 static tree pass_through_call (const_gimple); 59 static tree pass_through_call (const gcall *);
51 static void collect_object_sizes_for (struct object_size_info *, tree); 60 static void collect_object_sizes_for (struct object_size_info *, tree);
52 static void expr_object_size (struct object_size_info *, tree, tree); 61 static void expr_object_size (struct object_size_info *, tree, tree);
53 static bool merge_object_sizes (struct object_size_info *, tree, tree, 62 static bool merge_object_sizes (struct object_size_info *, tree, tree,
54 unsigned HOST_WIDE_INT); 63 unsigned HOST_WIDE_INT);
55 static bool plus_stmt_object_size (struct object_size_info *, tree, gimple); 64 static bool plus_stmt_object_size (struct object_size_info *, tree, gimple *);
56 static bool cond_expr_object_size (struct object_size_info *, tree, tree); 65 static bool cond_expr_object_size (struct object_size_info *, tree, gimple *);
57 static unsigned int compute_object_sizes (void);
58 static void init_offset_limit (void); 66 static void init_offset_limit (void);
59 static void check_for_plus_in_loops (struct object_size_info *, tree); 67 static void check_for_plus_in_loops (struct object_size_info *, tree);
60 static void check_for_plus_in_loops_1 (struct object_size_info *, tree, 68 static void check_for_plus_in_loops_1 (struct object_size_info *, tree,
61 unsigned int); 69 unsigned int);
62 70
64 the object. 72 the object.
65 object_sizes[1] is upper bound for number of bytes till the end of 73 object_sizes[1] is upper bound for number of bytes till the end of
66 the subobject (innermost array or field with address taken). 74 the subobject (innermost array or field with address taken).
67 object_sizes[2] is lower bound for number of bytes till the end of 75 object_sizes[2] is lower bound for number of bytes till the end of
68 the object and object_sizes[3] lower bound for subobject. */ 76 the object and object_sizes[3] lower bound for subobject. */
69 static unsigned HOST_WIDE_INT *object_sizes[4]; 77 static vec<unsigned HOST_WIDE_INT> object_sizes[4];
70 78
71 /* Bitmaps what object sizes have been computed already. */ 79 /* Bitmaps what object sizes have been computed already. */
72 static bitmap computed[4]; 80 static bitmap computed[4];
73 81
74 /* Maximum value of offset we consider to be addition. */ 82 /* Maximum value of offset we consider to be addition. */
77 85
78 /* Initialize OFFSET_LIMIT variable. */ 86 /* Initialize OFFSET_LIMIT variable. */
79 static void 87 static void
80 init_offset_limit (void) 88 init_offset_limit (void)
81 { 89 {
82 if (host_integerp (TYPE_MAX_VALUE (sizetype), 1)) 90 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (sizetype)))
83 offset_limit = tree_low_cst (TYPE_MAX_VALUE (sizetype), 1); 91 offset_limit = tree_to_uhwi (TYPE_MAX_VALUE (sizetype));
84 else 92 else
85 offset_limit = -1; 93 offset_limit = -1;
86 offset_limit /= 2; 94 offset_limit /= 2;
87 } 95 }
88 96
106 if (base == error_mark_node) 114 if (base == error_mark_node)
107 return base; 115 return base;
108 116
109 t = TREE_OPERAND (expr, 1); 117 t = TREE_OPERAND (expr, 1);
110 off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t), 118 off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
111 size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1) 119 size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
112 / BITS_PER_UNIT)); 120 / BITS_PER_UNIT));
113 break; 121 break;
114 122
115 case REALPART_EXPR: 123 case REALPART_EXPR:
116 CASE_CONVERT: 124 CASE_CONVERT:
130 base = compute_object_offset (TREE_OPERAND (expr, 0), var); 138 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
131 if (base == error_mark_node) 139 if (base == error_mark_node)
132 return base; 140 return base;
133 141
134 t = TREE_OPERAND (expr, 1); 142 t = TREE_OPERAND (expr, 1);
143 tree low_bound, unit_size;
144 low_bound = array_ref_low_bound (CONST_CAST_TREE (expr));
145 unit_size = array_ref_element_size (CONST_CAST_TREE (expr));
146 if (! integer_zerop (low_bound))
147 t = fold_build2 (MINUS_EXPR, TREE_TYPE (t), t, low_bound);
135 if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0) 148 if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
136 { 149 {
137 code = MINUS_EXPR; 150 code = MINUS_EXPR;
138 t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t); 151 t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
139 } 152 }
140 t = fold_convert (sizetype, t); 153 t = fold_convert (sizetype, t);
141 off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t); 154 off = size_binop (MULT_EXPR, unit_size, t);
142 break; 155 break;
143 156
144 case MEM_REF: 157 case MEM_REF:
145 gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR); 158 gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR);
146 return double_int_to_tree (sizetype, mem_ref_offset (expr)); 159 return wide_int_to_tree (sizetype, mem_ref_offset (expr));
147 160
148 default: 161 default:
149 return error_mark_node; 162 return error_mark_node;
150 } 163 }
151 164
155 168
156 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR. 169 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
157 OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. 170 OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
158 If unknown, return unknown[object_size_type]. */ 171 If unknown, return unknown[object_size_type]. */
159 172
160 static unsigned HOST_WIDE_INT 173 static bool
161 addr_object_size (struct object_size_info *osi, const_tree ptr, 174 addr_object_size (struct object_size_info *osi, const_tree ptr,
162 int object_size_type) 175 int object_size_type, unsigned HOST_WIDE_INT *psize)
163 { 176 {
164 tree pt_var, pt_var_size = NULL_TREE, var_size, bytes; 177 tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
165 178
166 gcc_assert (TREE_CODE (ptr) == ADDR_EXPR); 179 gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
167 180
181 /* Set to unknown and overwrite just before returning if the size
182 could be determined. */
183 *psize = unknown[object_size_type];
184
168 pt_var = TREE_OPERAND (ptr, 0); 185 pt_var = TREE_OPERAND (ptr, 0);
169 if (REFERENCE_CLASS_P (pt_var)) 186 while (handled_component_p (pt_var))
170 pt_var = get_base_address (pt_var); 187 pt_var = TREE_OPERAND (pt_var, 0);
171 188
172 if (pt_var 189 if (pt_var
173 && TREE_CODE (pt_var) == MEM_REF 190 && TREE_CODE (pt_var) == MEM_REF)
174 && TREE_CODE (TREE_OPERAND (pt_var, 0)) == SSA_NAME
175 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (pt_var, 0))))
176 { 191 {
177 unsigned HOST_WIDE_INT sz; 192 unsigned HOST_WIDE_INT sz;
178 193
179 if (!osi || (object_size_type & 1) != 0) 194 if (!osi || (object_size_type & 1) != 0
180 { 195 || TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
181 sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0), 196 {
182 object_size_type & ~1); 197 compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
183 if (host_integerp (TREE_OPERAND (pt_var, 1), 0)) 198 object_size_type & ~1, &sz);
184 sz -= TREE_INT_CST_LOW (TREE_OPERAND (pt_var, 1));
185 else
186 sz = offset_limit;
187 } 199 }
188 else 200 else
189 { 201 {
190 tree var = TREE_OPERAND (pt_var, 0); 202 tree var = TREE_OPERAND (pt_var, 0);
191 if (osi->pass == 0) 203 if (osi->pass == 0)
193 if (bitmap_bit_p (computed[object_size_type], 205 if (bitmap_bit_p (computed[object_size_type],
194 SSA_NAME_VERSION (var))) 206 SSA_NAME_VERSION (var)))
195 sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)]; 207 sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)];
196 else 208 else
197 sz = unknown[object_size_type]; 209 sz = unknown[object_size_type];
198 if (host_integerp (TREE_OPERAND (pt_var, 1), 0)) 210 }
199 sz -= TREE_INT_CST_LOW (TREE_OPERAND (pt_var, 1)); 211 if (sz != unknown[object_size_type])
212 {
213 offset_int dsz = wi::sub (sz, mem_ref_offset (pt_var));
214 if (wi::neg_p (dsz))
215 sz = 0;
216 else if (wi::fits_uhwi_p (dsz))
217 sz = dsz.to_uhwi ();
200 else 218 else
201 sz = offset_limit; 219 sz = unknown[object_size_type];
202 } 220 }
203 221
204 if (sz != unknown[object_size_type] && sz < offset_limit) 222 if (sz != unknown[object_size_type] && sz < offset_limit)
205 pt_var_size = size_int (sz); 223 pt_var_size = size_int (sz);
206 } 224 }
207 else if (pt_var 225 else if (pt_var
208 && (SSA_VAR_P (pt_var) || TREE_CODE (pt_var) == STRING_CST) 226 && DECL_P (pt_var)
227 && tree_fits_uhwi_p (DECL_SIZE_UNIT (pt_var))
228 && tree_to_uhwi (DECL_SIZE_UNIT (pt_var)) < offset_limit)
229 pt_var_size = DECL_SIZE_UNIT (pt_var);
230 else if (pt_var
231 && TREE_CODE (pt_var) == STRING_CST
209 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var)) 232 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
210 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1) 233 && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)))
211 && (unsigned HOST_WIDE_INT) 234 && tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)))
212 tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
213 < offset_limit) 235 < offset_limit)
214 pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var)); 236 pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
215 else 237 else
216 return unknown[object_size_type]; 238 return false;
217 239
218 if (pt_var != TREE_OPERAND (ptr, 0)) 240 if (pt_var != TREE_OPERAND (ptr, 0))
219 { 241 {
220 tree var; 242 tree var;
221 243
232 && TREE_CODE (var) != IMAGPART_EXPR) 254 && TREE_CODE (var) != IMAGPART_EXPR)
233 var = TREE_OPERAND (var, 0); 255 var = TREE_OPERAND (var, 0);
234 if (var != pt_var && TREE_CODE (var) == ARRAY_REF) 256 if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
235 var = TREE_OPERAND (var, 0); 257 var = TREE_OPERAND (var, 0);
236 if (! TYPE_SIZE_UNIT (TREE_TYPE (var)) 258 if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
237 || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1) 259 || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var)))
238 || (pt_var_size 260 || (pt_var_size
239 && tree_int_cst_lt (pt_var_size, 261 && tree_int_cst_lt (pt_var_size,
240 TYPE_SIZE_UNIT (TREE_TYPE (var))))) 262 TYPE_SIZE_UNIT (TREE_TYPE (var)))))
241 var = pt_var; 263 var = pt_var;
242 else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF) 264 else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF)
326 var = pt_var; 348 var = pt_var;
327 349
328 if (var != pt_var) 350 if (var != pt_var)
329 var_size = TYPE_SIZE_UNIT (TREE_TYPE (var)); 351 var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
330 else if (!pt_var_size) 352 else if (!pt_var_size)
331 return unknown[object_size_type]; 353 return false;
332 else 354 else
333 var_size = pt_var_size; 355 var_size = pt_var_size;
334 bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var); 356 bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
335 if (bytes != error_mark_node) 357 if (bytes != error_mark_node)
336 { 358 {
346 && bytes != error_mark_node) 368 && bytes != error_mark_node)
347 { 369 {
348 tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var); 370 tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var);
349 if (bytes2 != error_mark_node) 371 if (bytes2 != error_mark_node)
350 { 372 {
351 bytes2 = size_binop (PLUS_EXPR, bytes2,
352 TREE_OPERAND (pt_var, 1));
353 if (TREE_CODE (bytes2) == INTEGER_CST 373 if (TREE_CODE (bytes2) == INTEGER_CST
354 && tree_int_cst_lt (pt_var_size, bytes2)) 374 && tree_int_cst_lt (pt_var_size, bytes2))
355 bytes2 = size_zero_node; 375 bytes2 = size_zero_node;
356 else 376 else
357 bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2); 377 bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2);
358 bytes = size_binop (MIN_EXPR, bytes, bytes2); 378 bytes = size_binop (MIN_EXPR, bytes, bytes2);
359 } 379 }
360 } 380 }
361 } 381 }
362 else if (!pt_var_size) 382 else if (!pt_var_size)
363 return unknown[object_size_type]; 383 return false;
364 else 384 else
365 bytes = pt_var_size; 385 bytes = pt_var_size;
366 386
367 if (host_integerp (bytes, 1)) 387 if (tree_fits_uhwi_p (bytes))
368 return tree_low_cst (bytes, 1); 388 {
369 389 *psize = tree_to_uhwi (bytes);
370 return unknown[object_size_type]; 390 return true;
391 }
392
393 return false;
371 } 394 }
372 395
373 396
374 /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL. 397 /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
375 Handles various allocation calls. OBJECT_SIZE_TYPE is the second 398 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
376 argument from __builtin_object_size. If unknown, return 399 argument from __builtin_object_size. If unknown, return
377 unknown[object_size_type]. */ 400 unknown[object_size_type]. */
378 401
379 static unsigned HOST_WIDE_INT 402 static unsigned HOST_WIDE_INT
380 alloc_object_size (const_gimple call, int object_size_type) 403 alloc_object_size (const gcall *call, int object_size_type)
381 { 404 {
382 tree callee, bytes = NULL_TREE; 405 tree callee, bytes = NULL_TREE;
383 tree alloc_size; 406 tree alloc_size;
384 int arg1 = -1, arg2 = -1; 407 int arg1 = -1, arg2 = -1;
385 408
387 410
388 callee = gimple_call_fndecl (call); 411 callee = gimple_call_fndecl (call);
389 if (!callee) 412 if (!callee)
390 return unknown[object_size_type]; 413 return unknown[object_size_type];
391 414
392 alloc_size = lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (TREE_TYPE(callee))); 415 alloc_size = lookup_attribute ("alloc_size",
416 TYPE_ATTRIBUTES (TREE_TYPE (callee)));
393 if (alloc_size && TREE_VALUE (alloc_size)) 417 if (alloc_size && TREE_VALUE (alloc_size))
394 { 418 {
395 tree p = TREE_VALUE (alloc_size); 419 tree p = TREE_VALUE (alloc_size);
396 420
397 arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1; 421 arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1;
404 { 428 {
405 case BUILT_IN_CALLOC: 429 case BUILT_IN_CALLOC:
406 arg2 = 1; 430 arg2 = 1;
407 /* fall through */ 431 /* fall through */
408 case BUILT_IN_MALLOC: 432 case BUILT_IN_MALLOC:
409 case BUILT_IN_ALLOCA: 433 CASE_BUILT_IN_ALLOCA:
410 arg1 = 0; 434 arg1 = 0;
411 default: 435 default:
412 break; 436 break;
413 } 437 }
414 438
424 fold_convert (sizetype, gimple_call_arg (call, arg1)), 448 fold_convert (sizetype, gimple_call_arg (call, arg1)),
425 fold_convert (sizetype, gimple_call_arg (call, arg2))); 449 fold_convert (sizetype, gimple_call_arg (call, arg2)));
426 else if (arg1 >= 0) 450 else if (arg1 >= 0)
427 bytes = fold_convert (sizetype, gimple_call_arg (call, arg1)); 451 bytes = fold_convert (sizetype, gimple_call_arg (call, arg1));
428 452
429 if (bytes && host_integerp (bytes, 1)) 453 if (bytes && tree_fits_uhwi_p (bytes))
430 return tree_low_cst (bytes, 1); 454 return tree_to_uhwi (bytes);
431 455
432 return unknown[object_size_type]; 456 return unknown[object_size_type];
433 } 457 }
434 458
435 459
436 /* If object size is propagated from one of function's arguments directly 460 /* If object size is propagated from one of function's arguments directly
437 to its return value, return that argument for GIMPLE_CALL statement CALL. 461 to its return value, return that argument for GIMPLE_CALL statement CALL.
438 Otherwise return NULL. */ 462 Otherwise return NULL. */
439 463
440 static tree 464 static tree
441 pass_through_call (const_gimple call) 465 pass_through_call (const gcall *call)
442 { 466 {
443 tree callee = gimple_call_fndecl (call); 467 tree callee = gimple_call_fndecl (call);
444 468
445 if (callee 469 if (callee
446 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) 470 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
456 case BUILT_IN_MEMCPY_CHK: 480 case BUILT_IN_MEMCPY_CHK:
457 case BUILT_IN_MEMMOVE_CHK: 481 case BUILT_IN_MEMMOVE_CHK:
458 case BUILT_IN_MEMSET_CHK: 482 case BUILT_IN_MEMSET_CHK:
459 case BUILT_IN_STRCPY_CHK: 483 case BUILT_IN_STRCPY_CHK:
460 case BUILT_IN_STRNCPY_CHK: 484 case BUILT_IN_STRNCPY_CHK:
485 case BUILT_IN_STPNCPY_CHK:
461 case BUILT_IN_STRCAT_CHK: 486 case BUILT_IN_STRCAT_CHK:
462 case BUILT_IN_STRNCAT_CHK: 487 case BUILT_IN_STRNCAT_CHK:
488 case BUILT_IN_ASSUME_ALIGNED:
463 if (gimple_call_num_args (call) >= 1) 489 if (gimple_call_num_args (call) >= 1)
464 return gimple_call_arg (call, 0); 490 return gimple_call_arg (call, 0);
465 break; 491 break;
466 default: 492 default:
467 break; 493 break;
469 495
470 return NULL_TREE; 496 return NULL_TREE;
471 } 497 }
472 498
473 499
474 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the 500 /* Compute __builtin_object_size value for PTR and set *PSIZE to
475 second argument from __builtin_object_size. */ 501 the resulting value. OBJECT_SIZE_TYPE is the second argument
476 502 to __builtin_object_size. Return true on success and false
477 unsigned HOST_WIDE_INT 503 when the object size could not be determined. */
478 compute_builtin_object_size (tree ptr, int object_size_type) 504
505 bool
506 compute_builtin_object_size (tree ptr, int object_size_type,
507 unsigned HOST_WIDE_INT *psize)
479 { 508 {
480 gcc_assert (object_size_type >= 0 && object_size_type <= 3); 509 gcc_assert (object_size_type >= 0 && object_size_type <= 3);
510
511 /* Set to unknown and overwrite just before returning if the size
512 could be determined. */
513 *psize = unknown[object_size_type];
481 514
482 if (! offset_limit) 515 if (! offset_limit)
483 init_offset_limit (); 516 init_offset_limit ();
484 517
485 if (TREE_CODE (ptr) == ADDR_EXPR) 518 if (TREE_CODE (ptr) == ADDR_EXPR)
486 return addr_object_size (NULL, ptr, object_size_type); 519 return addr_object_size (NULL, ptr, object_size_type, psize);
487 520
488 if (TREE_CODE (ptr) == SSA_NAME 521 if (TREE_CODE (ptr) != SSA_NAME
489 && POINTER_TYPE_P (TREE_TYPE (ptr)) 522 || !POINTER_TYPE_P (TREE_TYPE (ptr)))
490 && object_sizes[object_size_type] != NULL) 523 return false;
491 { 524
492 if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr))) 525 if (computed[object_size_type] == NULL)
493 { 526 {
494 struct object_size_info osi; 527 if (optimize || object_size_type & 1)
495 bitmap_iterator bi; 528 return false;
496 unsigned int i; 529
497 530 /* When not optimizing, rather than failing, make a small effort
498 if (dump_file) 531 to determine the object size without the full benefit of
532 the (costly) computation below. */
533 gimple *def = SSA_NAME_DEF_STMT (ptr);
534 if (gimple_code (def) == GIMPLE_ASSIGN)
535 {
536 tree_code code = gimple_assign_rhs_code (def);
537 if (code == POINTER_PLUS_EXPR)
499 { 538 {
500 fprintf (dump_file, "Computing %s %sobject size for ", 539 tree offset = gimple_assign_rhs2 (def);
501 (object_size_type & 2) ? "minimum" : "maximum", 540 ptr = gimple_assign_rhs1 (def);
502 (object_size_type & 1) ? "sub" : ""); 541
503 print_generic_expr (dump_file, ptr, dump_flags); 542 if (tree_fits_shwi_p (offset)
504 fprintf (dump_file, ":\n"); 543 && compute_builtin_object_size (ptr, object_size_type, psize))
544 {
545 /* Return zero when the offset is out of bounds. */
546 unsigned HOST_WIDE_INT off = tree_to_shwi (offset);
547 *psize = off < *psize ? *psize - off : 0;
548 return true;
549 }
505 } 550 }
506 551 }
507 osi.visited = BITMAP_ALLOC (NULL); 552 return false;
508 osi.reexamine = BITMAP_ALLOC (NULL); 553 }
509 osi.object_size_type = object_size_type; 554
510 osi.depths = NULL; 555 if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
511 osi.stack = NULL; 556 {
512 osi.tos = NULL; 557 struct object_size_info osi;
513 558 bitmap_iterator bi;
514 /* First pass: walk UD chains, compute object sizes that 559 unsigned int i;
515 can be computed. osi.reexamine bitmap at the end will 560
516 contain what variables were found in dependency cycles 561 if (num_ssa_names > object_sizes[object_size_type].length ())
517 and therefore need to be reexamined. */ 562 object_sizes[object_size_type].safe_grow (num_ssa_names);
518 osi.pass = 0; 563 if (dump_file)
519 osi.changed = false; 564 {
520 collect_object_sizes_for (&osi, ptr); 565 fprintf (dump_file, "Computing %s %sobject size for ",
521 566 (object_size_type & 2) ? "minimum" : "maximum",
522 /* Second pass: keep recomputing object sizes of variables 567 (object_size_type & 1) ? "sub" : "");
523 that need reexamination, until no object sizes are 568 print_generic_expr (dump_file, ptr, dump_flags);
524 increased or all object sizes are computed. */ 569 fprintf (dump_file, ":\n");
525 if (! bitmap_empty_p (osi.reexamine)) 570 }
571
572 osi.visited = BITMAP_ALLOC (NULL);
573 osi.reexamine = BITMAP_ALLOC (NULL);
574 osi.object_size_type = object_size_type;
575 osi.depths = NULL;
576 osi.stack = NULL;
577 osi.tos = NULL;
578
579 /* First pass: walk UD chains, compute object sizes that
580 can be computed. osi.reexamine bitmap at the end will
581 contain what variables were found in dependency cycles
582 and therefore need to be reexamined. */
583 osi.pass = 0;
584 osi.changed = false;
585 collect_object_sizes_for (&osi, ptr);
586
587 /* Second pass: keep recomputing object sizes of variables
588 that need reexamination, until no object sizes are
589 increased or all object sizes are computed. */
590 if (! bitmap_empty_p (osi.reexamine))
591 {
592 bitmap reexamine = BITMAP_ALLOC (NULL);
593
594 /* If looking for minimum instead of maximum object size,
595 detect cases where a pointer is increased in a loop.
596 Although even without this detection pass 2 would eventually
597 terminate, it could take a long time. If a pointer is
598 increasing this way, we need to assume 0 object size.
599 E.g. p = &buf[0]; while (cond) p = p + 4; */
600 if (object_size_type & 2)
526 { 601 {
527 bitmap reexamine = BITMAP_ALLOC (NULL); 602 osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
528 603 osi.stack = XNEWVEC (unsigned int, num_ssa_names);
529 /* If looking for minimum instead of maximum object size, 604 osi.tos = osi.stack;
530 detect cases where a pointer is increased in a loop. 605 osi.pass = 1;
531 Although even without this detection pass 2 would eventually 606 /* collect_object_sizes_for is changing
532 terminate, it could take a long time. If a pointer is 607 osi.reexamine bitmap, so iterate over a copy. */
533 increasing this way, we need to assume 0 object size. 608 bitmap_copy (reexamine, osi.reexamine);
534 E.g. p = &buf[0]; while (cond) p = p + 4; */ 609 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
535 if (object_size_type & 2) 610 if (bitmap_bit_p (osi.reexamine, i))
536 { 611 check_for_plus_in_loops (&osi, ssa_name (i));
537 osi.depths = XCNEWVEC (unsigned int, num_ssa_names); 612
538 osi.stack = XNEWVEC (unsigned int, num_ssa_names); 613 free (osi.depths);
539 osi.tos = osi.stack; 614 osi.depths = NULL;
540 osi.pass = 1; 615 free (osi.stack);
541 /* collect_object_sizes_for is changing 616 osi.stack = NULL;
542 osi.reexamine bitmap, so iterate over a copy. */ 617 osi.tos = NULL;
543 bitmap_copy (reexamine, osi.reexamine); 618 }
544 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi) 619
545 if (bitmap_bit_p (osi.reexamine, i)) 620 do
546 check_for_plus_in_loops (&osi, ssa_name (i)); 621 {
547 622 osi.pass = 2;
548 free (osi.depths); 623 osi.changed = false;
549 osi.depths = NULL; 624 /* collect_object_sizes_for is changing
550 free (osi.stack); 625 osi.reexamine bitmap, so iterate over a copy. */
551 osi.stack = NULL; 626 bitmap_copy (reexamine, osi.reexamine);
552 osi.tos = NULL; 627 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
553 } 628 if (bitmap_bit_p (osi.reexamine, i))
554 629 {
555 do 630 collect_object_sizes_for (&osi, ssa_name (i));
556 { 631 if (dump_file && (dump_flags & TDF_DETAILS))
557 osi.pass = 2;
558 osi.changed = false;
559 /* collect_object_sizes_for is changing
560 osi.reexamine bitmap, so iterate over a copy. */
561 bitmap_copy (reexamine, osi.reexamine);
562 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
563 if (bitmap_bit_p (osi.reexamine, i))
564 { 632 {
565 collect_object_sizes_for (&osi, ssa_name (i)); 633 fprintf (dump_file, "Reexamining ");
566 if (dump_file && (dump_flags & TDF_DETAILS)) 634 print_generic_expr (dump_file, ssa_name (i),
567 { 635 dump_flags);
568 fprintf (dump_file, "Reexamining "); 636 fprintf (dump_file, "\n");
569 print_generic_expr (dump_file, ssa_name (i),
570 dump_flags);
571 fprintf (dump_file, "\n");
572 }
573 } 637 }
574 }
575 while (osi.changed);
576
577 BITMAP_FREE (reexamine);
578 }
579 EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
580 bitmap_set_bit (computed[object_size_type], i);
581
582 /* Debugging dumps. */
583 if (dump_file)
584 {
585 EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
586 if (object_sizes[object_size_type][i]
587 != unknown[object_size_type])
588 {
589 print_generic_expr (dump_file, ssa_name (i),
590 dump_flags);
591 fprintf (dump_file,
592 ": %s %sobject size "
593 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
594 (object_size_type & 2) ? "minimum" : "maximum",
595 (object_size_type & 1) ? "sub" : "",
596 object_sizes[object_size_type][i]);
597 } 638 }
598 } 639 }
599 640 while (osi.changed);
600 BITMAP_FREE (osi.reexamine); 641
601 BITMAP_FREE (osi.visited); 642 BITMAP_FREE (reexamine);
602 } 643 }
603 644 EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
604 return object_sizes[object_size_type][SSA_NAME_VERSION (ptr)]; 645 bitmap_set_bit (computed[object_size_type], i);
605 } 646
606 647 /* Debugging dumps. */
607 return unknown[object_size_type]; 648 if (dump_file)
649 {
650 EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
651 if (object_sizes[object_size_type][i]
652 != unknown[object_size_type])
653 {
654 print_generic_expr (dump_file, ssa_name (i),
655 dump_flags);
656 fprintf (dump_file,
657 ": %s %sobject size "
658 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
659 (object_size_type & 2) ? "minimum" : "maximum",
660 (object_size_type & 1) ? "sub" : "",
661 object_sizes[object_size_type][i]);
662 }
663 }
664
665 BITMAP_FREE (osi.reexamine);
666 BITMAP_FREE (osi.visited);
667 }
668
669 *psize = object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
670 return *psize != unknown[object_size_type];
608 } 671 }
609 672
610 /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */ 673 /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */
611 674
612 static void 675 static void
626 /* Pointer variables should have been handled by merge_object_sizes. */ 689 /* Pointer variables should have been handled by merge_object_sizes. */
627 gcc_assert (TREE_CODE (value) != SSA_NAME 690 gcc_assert (TREE_CODE (value) != SSA_NAME
628 || !POINTER_TYPE_P (TREE_TYPE (value))); 691 || !POINTER_TYPE_P (TREE_TYPE (value)));
629 692
630 if (TREE_CODE (value) == ADDR_EXPR) 693 if (TREE_CODE (value) == ADDR_EXPR)
631 bytes = addr_object_size (osi, value, object_size_type); 694 addr_object_size (osi, value, object_size_type, &bytes);
632 else 695 else
633 bytes = unknown[object_size_type]; 696 bytes = unknown[object_size_type];
634 697
635 if ((object_size_type & 2) == 0) 698 if ((object_size_type & 2) == 0)
636 { 699 {
646 709
647 710
648 /* Compute object_sizes for PTR, defined to the result of a call. */ 711 /* Compute object_sizes for PTR, defined to the result of a call. */
649 712
650 static void 713 static void
651 call_object_size (struct object_size_info *osi, tree ptr, gimple call) 714 call_object_size (struct object_size_info *osi, tree ptr, gcall *call)
652 { 715 {
653 int object_size_type = osi->object_size_type; 716 int object_size_type = osi->object_size_type;
654 unsigned int varno = SSA_NAME_VERSION (ptr); 717 unsigned int varno = SSA_NAME_VERSION (ptr);
655 unsigned HOST_WIDE_INT bytes; 718 unsigned HOST_WIDE_INT bytes;
656 719
726 collect_object_sizes_for (osi, orig); 789 collect_object_sizes_for (osi, orig);
727 790
728 orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)]; 791 orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
729 if (orig_bytes != unknown[object_size_type]) 792 if (orig_bytes != unknown[object_size_type])
730 orig_bytes = (offset > orig_bytes) 793 orig_bytes = (offset > orig_bytes)
731 ? (unsigned HOST_WIDE_INT) 0 : orig_bytes - offset; 794 ? HOST_WIDE_INT_0U : orig_bytes - offset;
732 795
733 if ((object_size_type & 2) == 0) 796 if ((object_size_type & 2) == 0)
734 { 797 {
735 if (object_sizes[object_size_type][varno] < orig_bytes) 798 if (object_sizes[object_size_type][varno] < orig_bytes)
736 { 799 {
753 /* Compute object_sizes for VAR, defined to the result of an assignment 816 /* Compute object_sizes for VAR, defined to the result of an assignment
754 with operator POINTER_PLUS_EXPR. Return true if the object size might 817 with operator POINTER_PLUS_EXPR. Return true if the object size might
755 need reexamination later. */ 818 need reexamination later. */
756 819
757 static bool 820 static bool
758 plus_stmt_object_size (struct object_size_info *osi, tree var, gimple stmt) 821 plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt)
759 { 822 {
760 int object_size_type = osi->object_size_type; 823 int object_size_type = osi->object_size_type;
761 unsigned int varno = SSA_NAME_VERSION (var); 824 unsigned int varno = SSA_NAME_VERSION (var);
762 unsigned HOST_WIDE_INT bytes; 825 unsigned HOST_WIDE_INT bytes;
763 tree op0, op1; 826 tree op0, op1;
783 /* Handle PTR + OFFSET here. */ 846 /* Handle PTR + OFFSET here. */
784 if (TREE_CODE (op1) == INTEGER_CST 847 if (TREE_CODE (op1) == INTEGER_CST
785 && (TREE_CODE (op0) == SSA_NAME 848 && (TREE_CODE (op0) == SSA_NAME
786 || TREE_CODE (op0) == ADDR_EXPR)) 849 || TREE_CODE (op0) == ADDR_EXPR))
787 { 850 {
788 if (! host_integerp (op1, 1)) 851 if (! tree_fits_uhwi_p (op1))
789 bytes = unknown[object_size_type]; 852 bytes = unknown[object_size_type];
790 else if (TREE_CODE (op0) == SSA_NAME) 853 else if (TREE_CODE (op0) == SSA_NAME)
791 return merge_object_sizes (osi, var, op0, tree_low_cst (op1, 1)); 854 return merge_object_sizes (osi, var, op0, tree_to_uhwi (op1));
792 else 855 else
793 { 856 {
794 unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1); 857 unsigned HOST_WIDE_INT off = tree_to_uhwi (op1);
795 858
796 /* op0 will be ADDR_EXPR here. */ 859 /* op0 will be ADDR_EXPR here. */
797 bytes = addr_object_size (osi, op0, object_size_type); 860 addr_object_size (osi, op0, object_size_type, &bytes);
798 if (bytes == unknown[object_size_type]) 861 if (bytes == unknown[object_size_type])
799 ; 862 ;
800 else if (off > offset_limit) 863 else if (off > offset_limit)
801 bytes = unknown[object_size_type]; 864 bytes = unknown[object_size_type];
802 else if (off > bytes) 865 else if (off > bytes)
820 } 883 }
821 return false; 884 return false;
822 } 885 }
823 886
824 887
825 /* Compute object_sizes for VAR, defined to VALUE, which is 888 /* Compute object_sizes for VAR, defined at STMT, which is
826 a COND_EXPR. Return true if the object size might need reexamination 889 a COND_EXPR. Return true if the object size might need reexamination
827 later. */ 890 later. */
828 891
829 static bool 892 static bool
830 cond_expr_object_size (struct object_size_info *osi, tree var, tree value) 893 cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt)
831 { 894 {
832 tree then_, else_; 895 tree then_, else_;
833 int object_size_type = osi->object_size_type; 896 int object_size_type = osi->object_size_type;
834 unsigned int varno = SSA_NAME_VERSION (var); 897 unsigned int varno = SSA_NAME_VERSION (var);
835 bool reexamine = false; 898 bool reexamine = false;
836 899
837 gcc_assert (TREE_CODE (value) == COND_EXPR); 900 gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR);
838 901
839 if (object_sizes[object_size_type][varno] == unknown[object_size_type]) 902 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
840 return false; 903 return false;
841 904
842 then_ = COND_EXPR_THEN (value); 905 then_ = gimple_assign_rhs2 (stmt);
843 else_ = COND_EXPR_ELSE (value); 906 else_ = gimple_assign_rhs3 (stmt);
844 907
845 if (TREE_CODE (then_) == SSA_NAME) 908 if (TREE_CODE (then_) == SSA_NAME)
846 reexamine |= merge_object_sizes (osi, var, then_, 0); 909 reexamine |= merge_object_sizes (osi, var, then_, 0);
847 else 910 else
848 expr_object_size (osi, var, then_); 911 expr_object_size (osi, var, then_);
878 static void 941 static void
879 collect_object_sizes_for (struct object_size_info *osi, tree var) 942 collect_object_sizes_for (struct object_size_info *osi, tree var)
880 { 943 {
881 int object_size_type = osi->object_size_type; 944 int object_size_type = osi->object_size_type;
882 unsigned int varno = SSA_NAME_VERSION (var); 945 unsigned int varno = SSA_NAME_VERSION (var);
883 gimple stmt; 946 gimple *stmt;
884 bool reexamine; 947 bool reexamine;
885 948
886 if (bitmap_bit_p (computed[object_size_type], varno)) 949 if (bitmap_bit_p (computed[object_size_type], varno))
887 return; 950 return;
888 951
925 tree rhs = gimple_assign_rhs1 (stmt); 988 tree rhs = gimple_assign_rhs1 (stmt);
926 if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR 989 if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
927 || (gimple_assign_rhs_code (stmt) == ADDR_EXPR 990 || (gimple_assign_rhs_code (stmt) == ADDR_EXPR
928 && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF)) 991 && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF))
929 reexamine = plus_stmt_object_size (osi, var, stmt); 992 reexamine = plus_stmt_object_size (osi, var, stmt);
993 else if (gimple_assign_rhs_code (stmt) == COND_EXPR)
994 reexamine = cond_expr_object_size (osi, var, stmt);
930 else if (gimple_assign_single_p (stmt) 995 else if (gimple_assign_single_p (stmt)
931 || gimple_assign_unary_nop_p (stmt)) 996 || gimple_assign_unary_nop_p (stmt))
932 { 997 {
933 if (TREE_CODE (rhs) == SSA_NAME 998 if (TREE_CODE (rhs) == SSA_NAME
934 && POINTER_TYPE_P (TREE_TYPE (rhs))) 999 && POINTER_TYPE_P (TREE_TYPE (rhs)))
935 reexamine = merge_object_sizes (osi, var, rhs, 0); 1000 reexamine = merge_object_sizes (osi, var, rhs, 0);
936 else if (TREE_CODE (rhs) == COND_EXPR)
937 reexamine = cond_expr_object_size (osi, var, rhs);
938 else 1001 else
939 expr_object_size (osi, var, rhs); 1002 expr_object_size (osi, var, rhs);
940 } 1003 }
941 else 1004 else
942 unknown_object_size (osi, var); 1005 unknown_object_size (osi, var);
943 break; 1006 break;
944 } 1007 }
945 1008
946 case GIMPLE_CALL: 1009 case GIMPLE_CALL:
947 { 1010 {
948 tree arg = pass_through_call (stmt); 1011 gcall *call_stmt = as_a <gcall *> (stmt);
1012 tree arg = pass_through_call (call_stmt);
949 if (arg) 1013 if (arg)
950 { 1014 {
951 if (TREE_CODE (arg) == SSA_NAME 1015 if (TREE_CODE (arg) == SSA_NAME
952 && POINTER_TYPE_P (TREE_TYPE (arg))) 1016 && POINTER_TYPE_P (TREE_TYPE (arg)))
953 reexamine = merge_object_sizes (osi, var, arg, 0); 1017 reexamine = merge_object_sizes (osi, var, arg, 0);
954 else if (TREE_CODE (arg) == COND_EXPR)
955 reexamine = cond_expr_object_size (osi, var, arg);
956 else 1018 else
957 expr_object_size (osi, var, arg); 1019 expr_object_size (osi, var, arg);
958 } 1020 }
959 else 1021 else
960 call_object_size (osi, var, stmt); 1022 call_object_size (osi, var, call_stmt);
961 break; 1023 break;
962 } 1024 }
963 1025
964 case GIMPLE_ASM: 1026 case GIMPLE_ASM:
965 /* Pointers defined by __asm__ statements can point anywhere. */ 1027 /* Pointers defined by __asm__ statements can point anywhere. */
966 object_sizes[object_size_type][varno] = unknown[object_size_type]; 1028 object_sizes[object_size_type][varno] = unknown[object_size_type];
967 break; 1029 break;
968 1030
969 case GIMPLE_NOP: 1031 case GIMPLE_NOP:
970 { 1032 if (SSA_NAME_VAR (var)
971 tree decl = SSA_NAME_VAR (var); 1033 && TREE_CODE (SSA_NAME_VAR (var)) == PARM_DECL)
972 1034 expr_object_size (osi, var, SSA_NAME_VAR (var));
973 if (TREE_CODE (decl) != PARM_DECL && DECL_INITIAL (decl)) 1035 else
974 expr_object_size (osi, var, DECL_INITIAL (decl)); 1036 /* Uninitialized SSA names point nowhere. */
975 else 1037 object_sizes[object_size_type][varno] = unknown[object_size_type];
976 expr_object_size (osi, var, decl);
977 }
978 break; 1038 break;
979 1039
980 case GIMPLE_PHI: 1040 case GIMPLE_PHI:
981 { 1041 {
982 unsigned i; 1042 unsigned i;
1025 1085
1026 static void 1086 static void
1027 check_for_plus_in_loops_1 (struct object_size_info *osi, tree var, 1087 check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
1028 unsigned int depth) 1088 unsigned int depth)
1029 { 1089 {
1030 gimple stmt = SSA_NAME_DEF_STMT (var); 1090 gimple *stmt = SSA_NAME_DEF_STMT (var);
1031 unsigned int varno = SSA_NAME_VERSION (var); 1091 unsigned int varno = SSA_NAME_VERSION (var);
1032 1092
1033 if (osi->depths[varno]) 1093 if (osi->depths[varno])
1034 { 1094 {
1035 if (osi->depths[varno] != depth) 1095 if (osi->depths[varno] != depth)
1083 break; 1143 break;
1084 } 1144 }
1085 1145
1086 case GIMPLE_CALL: 1146 case GIMPLE_CALL:
1087 { 1147 {
1088 tree arg = pass_through_call (stmt); 1148 gcall *call_stmt = as_a <gcall *> (stmt);
1149 tree arg = pass_through_call (call_stmt);
1089 if (arg) 1150 if (arg)
1090 { 1151 {
1091 if (TREE_CODE (arg) == SSA_NAME) 1152 if (TREE_CODE (arg) == SSA_NAME)
1092 check_for_plus_in_loops_1 (osi, arg, depth); 1153 check_for_plus_in_loops_1 (osi, arg, depth);
1093 else 1154 else
1124 that loop have minimum object sizes 0. */ 1185 that loop have minimum object sizes 0. */
1125 1186
1126 static void 1187 static void
1127 check_for_plus_in_loops (struct object_size_info *osi, tree var) 1188 check_for_plus_in_loops (struct object_size_info *osi, tree var)
1128 { 1189 {
1129 gimple stmt = SSA_NAME_DEF_STMT (var); 1190 gimple *stmt = SSA_NAME_DEF_STMT (var);
1130 1191
1131 /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here, 1192 /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here,
1132 and looked for a POINTER_PLUS_EXPR in the pass-through 1193 and looked for a POINTER_PLUS_EXPR in the pass-through
1133 argument, if any. In GIMPLE, however, such an expression 1194 argument, if any. In GIMPLE, however, such an expression
1134 is not a valid call operand. */ 1195 is not a valid call operand. */
1158 void 1219 void
1159 init_object_sizes (void) 1220 init_object_sizes (void)
1160 { 1221 {
1161 int object_size_type; 1222 int object_size_type;
1162 1223
1163 if (object_sizes[0]) 1224 if (computed[0])
1164 return; 1225 return;
1165 1226
1166 for (object_size_type = 0; object_size_type <= 3; object_size_type++) 1227 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1167 { 1228 {
1168 object_sizes[object_size_type] = XNEWVEC (unsigned HOST_WIDE_INT, num_ssa_names); 1229 object_sizes[object_size_type].safe_grow (num_ssa_names);
1169 computed[object_size_type] = BITMAP_ALLOC (NULL); 1230 computed[object_size_type] = BITMAP_ALLOC (NULL);
1170 } 1231 }
1171 1232
1172 init_offset_limit (); 1233 init_offset_limit ();
1173 } 1234 }
1180 { 1241 {
1181 int object_size_type; 1242 int object_size_type;
1182 1243
1183 for (object_size_type = 0; object_size_type <= 3; object_size_type++) 1244 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1184 { 1245 {
1185 free (object_sizes[object_size_type]); 1246 object_sizes[object_size_type].release ();
1186 BITMAP_FREE (computed[object_size_type]); 1247 BITMAP_FREE (computed[object_size_type]);
1187 object_sizes[object_size_type] = NULL;
1188 } 1248 }
1189 } 1249 }
1190 1250
1191 1251
1192 /* Simple pass to optimize all __builtin_object_size () builtins. */ 1252 /* Simple pass to optimize all __builtin_object_size () builtins. */
1193 1253
1194 static unsigned int 1254 namespace {
1195 compute_object_sizes (void) 1255
1256 const pass_data pass_data_object_sizes =
1257 {
1258 GIMPLE_PASS, /* type */
1259 "objsz", /* name */
1260 OPTGROUP_NONE, /* optinfo_flags */
1261 TV_NONE, /* tv_id */
1262 ( PROP_cfg | PROP_ssa ), /* properties_required */
1263 0, /* properties_provided */
1264 0, /* properties_destroyed */
1265 0, /* todo_flags_start */
1266 0, /* todo_flags_finish */
1267 };
1268
1269 class pass_object_sizes : public gimple_opt_pass
1270 {
1271 public:
1272 pass_object_sizes (gcc::context *ctxt)
1273 : gimple_opt_pass (pass_data_object_sizes, ctxt), insert_min_max_p (false)
1274 {}
1275
1276 /* opt_pass methods: */
1277 opt_pass * clone () { return new pass_object_sizes (m_ctxt); }
1278 void set_pass_param (unsigned int n, bool param)
1279 {
1280 gcc_assert (n == 0);
1281 insert_min_max_p = param;
1282 }
1283 virtual unsigned int execute (function *);
1284
1285 private:
1286 /* Determines whether the pass instance creates MIN/MAX_EXPRs. */
1287 bool insert_min_max_p;
1288 }; // class pass_object_sizes
1289
1290 /* Dummy valueize function. */
1291
1292 static tree
1293 do_valueize (tree t)
1294 {
1295 return t;
1296 }
1297
1298 unsigned int
1299 pass_object_sizes::execute (function *fun)
1196 { 1300 {
1197 basic_block bb; 1301 basic_block bb;
1198 FOR_EACH_BB (bb) 1302 FOR_EACH_BB_FN (bb, fun)
1199 { 1303 {
1200 gimple_stmt_iterator i; 1304 gimple_stmt_iterator i;
1201 for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) 1305 for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
1202 { 1306 {
1203 tree callee, result; 1307 tree result;
1204 gimple call = gsi_stmt (i); 1308 gimple *call = gsi_stmt (i);
1205 1309 if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE))
1206 if (gimple_code (call) != GIMPLE_CALL)
1207 continue; 1310 continue;
1208 1311
1209 callee = gimple_call_fndecl (call); 1312 init_object_sizes ();
1210 if (!callee 1313
1211 || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL 1314 /* If insert_min_max_p, only attempt to fold
1212 || DECL_FUNCTION_CODE (callee) != BUILT_IN_OBJECT_SIZE) 1315 __builtin_object_size (x, 1) and __builtin_object_size (x, 3),
1316 and rather than folding the builtin to the constant if any,
1317 create a MIN_EXPR or MAX_EXPR of the __builtin_object_size
1318 call result and the computed constant. */
1319 if (insert_min_max_p)
1320 {
1321 tree ost = gimple_call_arg (call, 1);
1322 if (tree_fits_uhwi_p (ost))
1323 {
1324 unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
1325 tree ptr = gimple_call_arg (call, 0);
1326 tree lhs = gimple_call_lhs (call);
1327 if ((object_size_type == 1 || object_size_type == 3)
1328 && (TREE_CODE (ptr) == ADDR_EXPR
1329 || TREE_CODE (ptr) == SSA_NAME)
1330 && lhs)
1331 {
1332 tree type = TREE_TYPE (lhs);
1333 unsigned HOST_WIDE_INT bytes;
1334 if (compute_builtin_object_size (ptr, object_size_type,
1335 &bytes)
1336 && wi::fits_to_tree_p (bytes, type))
1337 {
1338 tree tem = make_ssa_name (type);
1339 gimple_call_set_lhs (call, tem);
1340 enum tree_code code
1341 = object_size_type == 1 ? MIN_EXPR : MAX_EXPR;
1342 tree cst = build_int_cstu (type, bytes);
1343 gimple *g
1344 = gimple_build_assign (lhs, code, tem, cst);
1345 gsi_insert_after (&i, g, GSI_NEW_STMT);
1346 update_stmt (call);
1347 }
1348 }
1349 }
1350 continue;
1351 }
1352
1353 tree lhs = gimple_call_lhs (call);
1354 if (!lhs)
1213 continue; 1355 continue;
1214 1356
1215 init_object_sizes (); 1357 result = gimple_fold_stmt_to_constant (call, do_valueize);
1216 result = fold_call_stmt (call, false);
1217 if (!result) 1358 if (!result)
1218 { 1359 {
1219 if (gimple_call_num_args (call) == 2 1360 tree ost = gimple_call_arg (call, 1);
1220 && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, 0)))) 1361
1362 if (tree_fits_uhwi_p (ost))
1221 { 1363 {
1222 tree ost = gimple_call_arg (call, 1); 1364 unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
1223 1365
1224 if (host_integerp (ost, 1)) 1366 if (object_size_type < 2)
1225 { 1367 result = fold_convert (size_type_node,
1226 unsigned HOST_WIDE_INT object_size_type 1368 integer_minus_one_node);
1227 = tree_low_cst (ost, 1); 1369 else if (object_size_type < 4)
1228 1370 result = build_zero_cst (size_type_node);
1229 if (object_size_type < 2)
1230 result = fold_convert (size_type_node,
1231 integer_minus_one_node);
1232 else if (object_size_type < 4)
1233 result = build_zero_cst (size_type_node);
1234 }
1235 } 1371 }
1236 1372
1237 if (!result) 1373 if (!result)
1238 continue; 1374 continue;
1239 } 1375 }
1376
1377 gcc_assert (TREE_CODE (result) == INTEGER_CST);
1240 1378
1241 if (dump_file && (dump_flags & TDF_DETAILS)) 1379 if (dump_file && (dump_flags & TDF_DETAILS))
1242 { 1380 {
1243 fprintf (dump_file, "Simplified\n "); 1381 fprintf (dump_file, "Simplified\n ");
1244 print_gimple_stmt (dump_file, call, 0, dump_flags); 1382 print_gimple_stmt (dump_file, call, 0, dump_flags);
1245 } 1383 fprintf (dump_file, " to ");
1246 1384 print_generic_expr (dump_file, result);
1247 if (!update_call_from_tree (&i, result))
1248 gcc_unreachable ();
1249
1250 /* NOTE: In the pre-tuples code, we called update_stmt here. This is
1251 now handled by gsi_replace, called from update_call_from_tree. */
1252
1253 if (dump_file && (dump_flags & TDF_DETAILS))
1254 {
1255 fprintf (dump_file, "to\n ");
1256 print_gimple_stmt (dump_file, call, 0, dump_flags);
1257 fprintf (dump_file, "\n"); 1385 fprintf (dump_file, "\n");
1258 } 1386 }
1387
1388 /* Propagate into all uses and fold those stmts. */
1389 replace_uses_by (lhs, result);
1259 } 1390 }
1260 } 1391 }
1261 1392
1262 fini_object_sizes (); 1393 fini_object_sizes ();
1263 return 0; 1394 return 0;
1264 } 1395 }
1265 1396
1266 struct gimple_opt_pass pass_object_sizes = 1397 } // anon namespace
1267 { 1398
1268 { 1399 gimple_opt_pass *
1269 GIMPLE_PASS, 1400 make_pass_object_sizes (gcc::context *ctxt)
1270 "objsz", /* name */ 1401 {
1271 NULL, /* gate */ 1402 return new pass_object_sizes (ctxt);
1272 compute_object_sizes, /* execute */ 1403 }
1273 NULL, /* sub */
1274 NULL, /* next */
1275 0, /* static_pass_number */
1276 TV_NONE, /* tv_id */
1277 PROP_cfg | PROP_ssa, /* properties_required */
1278 0, /* properties_provided */
1279 0, /* properties_destroyed */
1280 0, /* todo_flags_start */
1281 TODO_dump_func | TODO_verify_ssa /* todo_flags_finish */
1282 }
1283 };