Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-struct-reorg.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* Struct-reorg optimization. | |
2 Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. | |
3 Contributed by Olga Golovanevsky <olga@il.ibm.com> | |
4 (Initial version of this code was developed | |
5 by Caroline Tice and Mostafa Hagog.) | |
6 | |
7 This file is part of GCC. | |
8 | |
9 GCC is free software; you can redistribute it and/or modify it under | |
10 the terms of the GNU General Public License as published by the Free | |
11 Software Foundation; either version 3, or (at your option) any later | |
12 version. | |
13 | |
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with GCC; see the file COPYING3. If not see | |
21 <http://www.gnu.org/licenses/>. */ | |
22 | |
23 #include "config.h" | |
24 #include "system.h" | |
25 #include "coretypes.h" | |
26 #include "tm.h" | |
27 #include "ggc.h" | |
28 #include "tree.h" | |
29 #include "rtl.h" | |
30 #include "gimple.h" | |
31 #include "tree-inline.h" | |
32 #include "tree-flow.h" | |
33 #include "tree-flow-inline.h" | |
34 #include "langhooks.h" | |
35 #include "pointer-set.h" | |
36 #include "hashtab.h" | |
37 #include "c-tree.h" | |
38 #include "toplev.h" | |
39 #include "flags.h" | |
40 #include "debug.h" | |
41 #include "target.h" | |
42 #include "cgraph.h" | |
43 #include "diagnostic.h" | |
44 #include "timevar.h" | |
45 #include "params.h" | |
46 #include "fibheap.h" | |
47 #include "intl.h" | |
48 #include "function.h" | |
49 #include "basic-block.h" | |
50 #include "tree-iterator.h" | |
51 #include "tree-pass.h" | |
52 #include "ipa-struct-reorg.h" | |
53 #include "opts.h" | |
54 #include "ipa-type-escape.h" | |
55 #include "tree-dump.h" | |
56 #include "c-common.h" | |
57 #include "gimple.h" | |
58 | |
59 /* This optimization implements structure peeling. | |
60 | |
61 For example, given a structure type: | |
62 typedef struct | |
63 { | |
64 int a; | |
65 float b; | |
66 int c; | |
67 }str_t; | |
68 | |
69 it can be peeled into two structure types as follows: | |
70 | |
71 typedef struct and typedef struct | |
72 { { | |
73 int a; float b; | |
74 int c; } str_t_1; | |
75 }str_t_0; | |
76 | |
77 or can be fully peeled: | |
78 | |
79 typedef struct | |
80 { | |
81 int a; | |
82 }str_t_0; | |
83 | |
84 typedef struct | |
85 { | |
86 float b; | |
87 }str_t_1; | |
88 | |
89 typedef struct | |
90 { | |
91 int c; | |
92 }str_t_2; | |
93 | |
94 When structure type is peeled all instances and their accesses | |
95 in the program are updated accordingly. For example, if there is | |
96 array of structures: | |
97 | |
98 str_t A[N]; | |
99 | |
100 and structure type str_t was peeled into two structures str_t_0 | |
101 and str_t_1 as it was shown above, then array A will be replaced | |
102 by two arrays as follows: | |
103 | |
104 str_t_0 A_0[N]; | |
105 str_t_1 A_1[N]; | |
106 | |
107 The field access of field a of element i of array A: A[i].a will be | |
108 replaced by an access to field a of element i of array A_0: A_0[i].a. | |
109 | |
110 This optimization also supports dynamically allocated arrays. | |
111 If array of structures was allocated by malloc function: | |
112 | |
113 str_t * p = (str_t *) malloc (sizeof (str_t) * N) | |
114 | |
115 the allocation site will be replaced to reflect new structure types: | |
116 | |
117 str_t_0 * p_0 = (str_t_0 *) malloc (sizeof (str_t_0) * N) | |
118 str_t_1 * p_1 = (str_t_1 *) malloc (sizeof (str_t_1) * N) | |
119 | |
120 The field access through the pointer p[i].a will be changed by p_0[i].a. | |
121 | |
122 The goal of structure peeling is to improve spatial locality. | |
123 For example, if one of the fields of a structure is accessed frequently | |
124 in the loop: | |
125 | |
126 for (i = 0; i < N; i++) | |
127 { | |
128 ... = A[i].a; | |
129 } | |
130 | |
131 the allocation of field a of str_t contiguously in memory will | |
132 increase the chances of fetching the field from cache. | |
133 | |
134 The analysis part of this optimization is based on the frequency of | |
135 field accesses, which are collected all over the program. | |
136 Then the fields with the frequencies that satisfy the following condition | |
137 get peeled out of the structure: | |
138 | |
139 freq(f) > C * max_field_freq_in_struct | |
140 | |
141 where max_field_freq_in_struct is the maximum field frequency | |
142 in the structure. C is a constant defining which portion of | |
143 max_field_freq_in_struct the fields should have in order to be peeled. | |
144 | |
145 If profiling information is provided, it is used to calculate the | |
146 frequency of field accesses. Otherwise, the structure is fully peeled. | |
147 | |
148 IPA type-escape analysis is used to determine when it is safe | |
149 to peel a structure. | |
150 | |
151 The optimization is activated by flag -fipa-struct-reorg. */ | |
152 | |
153 /* New variables created by this optimization. | |
154 When doing struct peeling, each variable of | |
155 the original struct type will be replaced by | |
156 the set of new variables corresponding to | |
157 the new structure types. */ | |
158 struct new_var_data { | |
159 /* VAR_DECL for original struct type. */ | |
160 tree orig_var; | |
161 /* Vector of new variables. */ | |
162 VEC(tree, heap) *new_vars; | |
163 }; | |
164 | |
165 typedef struct new_var_data *new_var; | |
166 typedef const struct new_var_data *const_new_var; | |
167 | |
168 /* This structure represents allocation site of the structure. */ | |
169 typedef struct alloc_site | |
170 { | |
171 gimple stmt; | |
172 d_str str; | |
173 } alloc_site_t; | |
174 | |
175 DEF_VEC_O (alloc_site_t); | |
176 DEF_VEC_ALLOC_O (alloc_site_t, heap); | |
177 | |
178 /* Allocation sites that belong to the same function. */ | |
179 struct func_alloc_sites | |
180 { | |
181 tree func; | |
182 /* Vector of allocation sites for function. */ | |
183 VEC (alloc_site_t, heap) *allocs; | |
184 }; | |
185 | |
186 typedef struct func_alloc_sites *fallocs_t; | |
187 typedef const struct func_alloc_sites *const_fallocs_t; | |
188 | |
189 /* All allocation sites in the program. */ | |
190 htab_t alloc_sites = NULL; | |
191 | |
192 /* New global variables. Generated once for whole program. */ | |
193 htab_t new_global_vars; | |
194 | |
195 /* New local variables. Generated per-function. */ | |
196 htab_t new_local_vars; | |
197 | |
198 /* Vector of structures to be transformed. */ | |
199 typedef struct data_structure structure; | |
200 DEF_VEC_O (structure); | |
201 DEF_VEC_ALLOC_O (structure, heap); | |
202 VEC (structure, heap) *structures; | |
203 | |
204 /* Forward declarations. */ | |
205 static bool is_equal_types (tree, tree); | |
206 | |
207 /* Strip structure TYPE from pointers and arrays. */ | |
208 | |
209 static inline tree | |
210 strip_type (tree type) | |
211 { | |
212 gcc_assert (TYPE_P (type)); | |
213 | |
214 while (POINTER_TYPE_P (type) | |
215 || TREE_CODE (type) == ARRAY_TYPE) | |
216 type = TREE_TYPE (type); | |
217 | |
218 return type; | |
219 } | |
220 | |
221 /* This function returns type of VAR. */ | |
222 | |
223 static inline tree | |
224 get_type_of_var (tree var) | |
225 { | |
226 if (!var) | |
227 return NULL; | |
228 | |
229 if (TREE_CODE (var) == PARM_DECL) | |
230 return DECL_ARG_TYPE (var); | |
231 else | |
232 return TREE_TYPE (var); | |
233 } | |
234 | |
235 /* Set of actions we do for each newly generated STMT. */ | |
236 | |
237 static inline void | |
238 finalize_stmt (gimple stmt) | |
239 { | |
240 update_stmt (stmt); | |
241 mark_symbols_for_renaming (stmt); | |
242 } | |
243 | |
244 /* This function finalizes STMT and appends it to the list STMTS. */ | |
245 | |
246 static inline void | |
247 finalize_stmt_and_append (gimple_seq *stmts, gimple stmt) | |
248 { | |
249 gimple_seq_add_stmt (stmts, stmt); | |
250 finalize_stmt (stmt); | |
251 } | |
252 | |
253 /* Given structure type SRT_TYPE and field FIELD, | |
254 this function is looking for a field with the same name | |
255 and type as FIELD in STR_TYPE. It returns it if found, | |
256 or NULL_TREE otherwise. */ | |
257 | |
258 static tree | |
259 find_field_in_struct_1 (tree str_type, tree field) | |
260 { | |
261 tree str_field; | |
262 | |
263 for (str_field = TYPE_FIELDS (str_type); str_field; | |
264 str_field = TREE_CHAIN (str_field)) | |
265 { | |
266 const char * str_field_name; | |
267 const char * field_name; | |
268 | |
269 str_field_name = IDENTIFIER_POINTER (DECL_NAME (str_field)); | |
270 field_name = IDENTIFIER_POINTER (DECL_NAME (field)); | |
271 | |
272 gcc_assert (str_field_name); | |
273 gcc_assert (field_name); | |
274 | |
275 if (!strcmp (str_field_name, field_name)) | |
276 { | |
277 /* Check field types. */ | |
278 if (is_equal_types (TREE_TYPE (str_field), TREE_TYPE (field))) | |
279 return str_field; | |
280 } | |
281 } | |
282 | |
283 return NULL_TREE; | |
284 } | |
285 | |
286 /* Given a field declaration FIELD_DECL, this function | |
287 returns corresponding field entry in structure STR. */ | |
288 | |
289 static struct field_entry * | |
290 find_field_in_struct (d_str str, tree field_decl) | |
291 { | |
292 int i; | |
293 | |
294 tree field = find_field_in_struct_1 (str->decl, field_decl); | |
295 | |
296 for (i = 0; i < str->num_fields; i++) | |
297 if (str->fields[i].decl == field) | |
298 return &(str->fields[i]); | |
299 | |
300 return NULL; | |
301 } | |
302 | |
303 /* This function checks whether ARG is a result of multiplication | |
304 of some number by STRUCT_SIZE. If yes, the function returns true | |
305 and this number is filled into NUM. */ | |
306 | |
307 static bool | |
308 is_result_of_mult (tree arg, tree *num, tree struct_size) | |
309 { | |
310 gimple size_def_stmt = SSA_NAME_DEF_STMT (arg); | |
311 | |
312 /* If the allocation statement was of the form | |
313 D.2229_10 = <alloc_func> (D.2228_9); | |
314 then size_def_stmt can be D.2228_9 = num.3_8 * 8; */ | |
315 | |
316 if (size_def_stmt && is_gimple_assign (size_def_stmt)) | |
317 { | |
318 tree lhs = gimple_assign_lhs (size_def_stmt); | |
319 | |
320 /* We expect temporary here. */ | |
321 if (!is_gimple_reg (lhs)) | |
322 return false; | |
323 | |
324 if (gimple_assign_rhs_code (size_def_stmt) == MULT_EXPR) | |
325 { | |
326 tree arg0 = gimple_assign_rhs1 (size_def_stmt); | |
327 tree arg1 = gimple_assign_rhs2 (size_def_stmt); | |
328 | |
329 if (operand_equal_p (arg0, struct_size, OEP_ONLY_CONST)) | |
330 { | |
331 *num = arg1; | |
332 return true; | |
333 } | |
334 | |
335 if (operand_equal_p (arg1, struct_size, OEP_ONLY_CONST)) | |
336 { | |
337 *num = arg0; | |
338 return true; | |
339 } | |
340 } | |
341 } | |
342 | |
343 *num = NULL_TREE; | |
344 return false; | |
345 } | |
346 | |
347 | |
348 /* This function returns true if access ACC corresponds to the pattern | |
349 generated by compiler when an address of element i of an array | |
350 of structures STR_DECL (pointed by p) is calculated (p[i]). If this | |
351 pattern is recognized correctly, this function returns true | |
352 and fills missing fields in ACC. Otherwise it returns false. */ | |
353 | |
354 static bool | |
355 decompose_indirect_ref_acc (tree str_decl, struct field_access_site *acc) | |
356 { | |
357 tree ref_var; | |
358 tree struct_size, op0, op1; | |
359 tree before_cast; | |
360 enum tree_code rhs_code; | |
361 | |
362 ref_var = TREE_OPERAND (acc->ref, 0); | |
363 | |
364 if (TREE_CODE (ref_var) != SSA_NAME) | |
365 return false; | |
366 | |
367 acc->ref_def_stmt = SSA_NAME_DEF_STMT (ref_var); | |
368 if (!(acc->ref_def_stmt) | |
369 || (gimple_code (acc->ref_def_stmt) != GIMPLE_ASSIGN)) | |
370 return false; | |
371 | |
372 rhs_code = gimple_assign_rhs_code (acc->ref_def_stmt); | |
373 | |
374 if (rhs_code != PLUS_EXPR | |
375 && rhs_code != MINUS_EXPR | |
376 && rhs_code != POINTER_PLUS_EXPR) | |
377 return false; | |
378 | |
379 op0 = gimple_assign_rhs1 (acc->ref_def_stmt); | |
380 op1 = gimple_assign_rhs2 (acc->ref_def_stmt); | |
381 | |
382 if (!is_array_access_through_pointer_and_index (rhs_code, op0, op1, | |
383 &acc->base, &acc->offset, | |
384 &acc->cast_stmt)) | |
385 return false; | |
386 | |
387 if (acc->cast_stmt) | |
388 before_cast = SINGLE_SSA_TREE_OPERAND (acc->cast_stmt, SSA_OP_USE); | |
389 else | |
390 before_cast = acc->offset; | |
391 | |
392 if (!before_cast) | |
393 return false; | |
394 | |
395 | |
396 if (SSA_NAME_IS_DEFAULT_DEF (before_cast)) | |
397 return false; | |
398 | |
399 struct_size = TYPE_SIZE_UNIT (str_decl); | |
400 | |
401 if (!is_result_of_mult (before_cast, &acc->num, struct_size)) | |
402 return false; | |
403 | |
404 return true; | |
405 } | |
406 | |
407 | |
408 /* This function checks whether the access ACC of structure type STR | |
409 is of the form suitable for transformation. If yes, it returns true. | |
410 False otherwise. */ | |
411 | |
412 static bool | |
413 decompose_access (tree str_decl, struct field_access_site *acc) | |
414 { | |
415 gcc_assert (acc->ref); | |
416 | |
417 if (TREE_CODE (acc->ref) == INDIRECT_REF) | |
418 return decompose_indirect_ref_acc (str_decl, acc); | |
419 else if (TREE_CODE (acc->ref) == ARRAY_REF) | |
420 return true; | |
421 else if (TREE_CODE (acc->ref) == VAR_DECL) | |
422 return true; | |
423 | |
424 return false; | |
425 } | |
426 | |
427 /* This function creates empty field_access_site node. */ | |
428 | |
429 static inline struct field_access_site * | |
430 make_field_acc_node (void) | |
431 { | |
432 int size = sizeof (struct field_access_site); | |
433 | |
434 return (struct field_access_site *) xcalloc (1, size); | |
435 } | |
436 | |
437 /* This function returns the structure field access, defined by STMT, | |
438 if it is already in hashtable of function accesses F_ACCS. */ | |
439 | |
440 static struct field_access_site * | |
441 is_in_field_accs (gimple stmt, htab_t f_accs) | |
442 { | |
443 return (struct field_access_site *) | |
444 htab_find_with_hash (f_accs, stmt, htab_hash_pointer (stmt)); | |
445 } | |
446 | |
447 /* This function adds an access ACC to the hashtable | |
448 F_ACCS of field accesses. */ | |
449 | |
450 static void | |
451 add_field_acc_to_acc_sites (struct field_access_site *acc, | |
452 htab_t f_accs) | |
453 { | |
454 void **slot; | |
455 | |
456 gcc_assert (!is_in_field_accs (acc->stmt, f_accs)); | |
457 slot = htab_find_slot_with_hash (f_accs, acc->stmt, | |
458 htab_hash_pointer (acc->stmt), | |
459 INSERT); | |
460 *slot = acc; | |
461 } | |
462 | |
463 /* This function adds the VAR to vector of variables of | |
464 an access site defined by statement STMT. If access entry | |
465 with statement STMT does not exist in hashtable of | |
466 accesses ACCS, this function creates it. */ | |
467 | |
468 static void | |
469 add_access_to_acc_sites (gimple stmt, tree var, htab_t accs) | |
470 { | |
471 struct access_site *acc; | |
472 | |
473 acc = (struct access_site *) | |
474 htab_find_with_hash (accs, stmt, htab_hash_pointer (stmt)); | |
475 | |
476 if (!acc) | |
477 { | |
478 void **slot; | |
479 | |
480 acc = (struct access_site *) xmalloc (sizeof (struct access_site)); | |
481 acc->stmt = stmt; | |
482 acc->vars = VEC_alloc (tree, heap, 10); | |
483 slot = htab_find_slot_with_hash (accs, stmt, | |
484 htab_hash_pointer (stmt), INSERT); | |
485 *slot = acc; | |
486 | |
487 } | |
488 VEC_safe_push (tree, heap, acc->vars, var); | |
489 } | |
490 | |
491 /* This function adds NEW_DECL to function | |
492 referenced vars, and marks it for renaming. */ | |
493 | |
494 static void | |
495 finalize_var_creation (tree new_decl) | |
496 { | |
497 add_referenced_var (new_decl); | |
498 if (is_global_var (new_decl)) | |
499 mark_call_clobbered (new_decl, ESCAPE_UNKNOWN); | |
500 mark_sym_for_renaming (new_decl); | |
501 } | |
502 | |
503 /* This function finalizes VAR creation if it is a global VAR_DECL. */ | |
504 | |
505 static void | |
506 finalize_global_creation (tree var) | |
507 { | |
508 if (TREE_CODE (var) == VAR_DECL | |
509 && is_global_var (var)) | |
510 finalize_var_creation (var); | |
511 } | |
512 | |
513 /* This function inserts NEW_DECL to varpool. */ | |
514 | |
515 static inline void | |
516 insert_global_to_varpool (tree new_decl) | |
517 { | |
518 struct varpool_node *new_node; | |
519 | |
520 new_node = varpool_node (new_decl); | |
521 notice_global_symbol (new_decl); | |
522 varpool_mark_needed_node (new_node); | |
523 varpool_finalize_decl (new_decl); | |
524 } | |
525 | |
526 /* This function finalizes the creation of new variables, | |
527 defined by *SLOT->new_vars. */ | |
528 | |
529 static int | |
530 finalize_new_vars_creation (void **slot, void *data ATTRIBUTE_UNUSED) | |
531 { | |
532 new_var n_var = *(new_var *) slot; | |
533 unsigned i; | |
534 tree var; | |
535 | |
536 for (i = 0; VEC_iterate (tree, n_var->new_vars, i, var); i++) | |
537 finalize_var_creation (var); | |
538 return 1; | |
539 } | |
540 | |
541 /* This function looks for the variable of NEW_TYPE type, stored in VAR. | |
542 It returns it, if found, and NULL_TREE otherwise. */ | |
543 | |
544 static tree | |
545 find_var_in_new_vars_vec (new_var var, tree new_type) | |
546 { | |
547 tree n_var; | |
548 unsigned i; | |
549 | |
550 for (i = 0; VEC_iterate (tree, var->new_vars, i, n_var); i++) | |
551 { | |
552 tree type = strip_type(get_type_of_var (n_var)); | |
553 gcc_assert (type); | |
554 | |
555 if (type == new_type) | |
556 return n_var; | |
557 } | |
558 | |
559 return NULL_TREE; | |
560 } | |
561 | |
562 /* This function returns new_var node, the orig_var of which is DECL. | |
563 It looks for new_var's in NEW_VARS_HTAB. If not found, | |
564 the function returns NULL. */ | |
565 | |
566 static new_var | |
567 is_in_new_vars_htab (tree decl, htab_t new_vars_htab) | |
568 { | |
569 return (new_var) htab_find_with_hash (new_vars_htab, decl, | |
570 htab_hash_pointer (decl)); | |
571 } | |
572 | |
573 /* Given original variable ORIG_VAR, this function returns | |
574 new variable corresponding to it of NEW_TYPE type. */ | |
575 | |
576 static tree | |
577 find_new_var_of_type (tree orig_var, tree new_type) | |
578 { | |
579 new_var var; | |
580 gcc_assert (orig_var && new_type); | |
581 | |
582 if (TREE_CODE (orig_var) == SSA_NAME) | |
583 orig_var = SSA_NAME_VAR (orig_var); | |
584 | |
585 var = is_in_new_vars_htab (orig_var, new_global_vars); | |
586 if (!var) | |
587 var = is_in_new_vars_htab (orig_var, new_local_vars); | |
588 gcc_assert (var); | |
589 return find_var_in_new_vars_vec (var, new_type); | |
590 } | |
591 | |
592 /* This function generates stmt: | |
593 res = NUM * sizeof(TYPE) and returns it. | |
594 res is filled into RES. */ | |
595 | |
596 static gimple | |
597 gen_size (tree num, tree type, tree *res) | |
598 { | |
599 tree struct_size = TYPE_SIZE_UNIT (type); | |
600 HOST_WIDE_INT struct_size_int = TREE_INT_CST_LOW (struct_size); | |
601 gimple new_stmt; | |
602 | |
603 *res = create_tmp_var (TREE_TYPE (num), NULL); | |
604 | |
605 if (*res) | |
606 add_referenced_var (*res); | |
607 | |
608 if (exact_log2 (struct_size_int) == -1) | |
609 { | |
610 tree size = build_int_cst (TREE_TYPE (num), struct_size_int); | |
611 new_stmt = gimple_build_assign_with_ops (MULT_EXPR, *res, num, size); | |
612 } | |
613 else | |
614 { | |
615 tree C = build_int_cst (TREE_TYPE (num), exact_log2 (struct_size_int)); | |
616 | |
617 new_stmt = gimple_build_assign_with_ops (LSHIFT_EXPR, *res, num, C); | |
618 } | |
619 | |
620 finalize_stmt (new_stmt); | |
621 return new_stmt; | |
622 } | |
623 | |
624 /* This function generates and returns a statement, that cast variable | |
625 BEFORE_CAST to NEW_TYPE. The cast result variable is stored | |
626 into RES_P. ORIG_CAST_STMT is the original cast statement. */ | |
627 | |
628 static gimple | |
629 gen_cast_stmt (tree before_cast, tree new_type, gimple orig_cast_stmt, | |
630 tree *res_p) | |
631 { | |
632 tree lhs, new_lhs; | |
633 gimple new_stmt; | |
634 | |
635 lhs = gimple_assign_lhs (orig_cast_stmt); | |
636 new_lhs = find_new_var_of_type (lhs, new_type); | |
637 gcc_assert (new_lhs); | |
638 | |
639 new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_lhs, before_cast, 0); | |
640 finalize_stmt (new_stmt); | |
641 *res_p = new_lhs; | |
642 return new_stmt; | |
643 } | |
644 | |
645 /* This function builds an edge between BB and E->dest and updates | |
646 phi nodes of E->dest. It returns newly created edge. */ | |
647 | |
648 static edge | |
649 make_edge_and_fix_phis_of_dest (basic_block bb, edge e) | |
650 { | |
651 edge new_e; | |
652 tree arg; | |
653 gimple_stmt_iterator si; | |
654 | |
655 new_e = make_edge (bb, e->dest, e->flags); | |
656 | |
657 for (si = gsi_start_phis (new_e->dest); !gsi_end_p (si); gsi_next (&si)) | |
658 { | |
659 gimple phi = gsi_stmt (si); | |
660 arg = PHI_ARG_DEF_FROM_EDGE (phi, e); | |
661 add_phi_arg (phi, arg, new_e); | |
662 } | |
663 | |
664 return new_e; | |
665 } | |
666 | |
667 /* This function inserts NEW_STMT before STMT. */ | |
668 | |
669 static void | |
670 insert_before_stmt (gimple stmt, gimple new_stmt) | |
671 { | |
672 gimple_stmt_iterator bsi; | |
673 | |
674 if (!stmt || !new_stmt) | |
675 return; | |
676 | |
677 bsi = gsi_for_stmt (stmt); | |
678 gsi_insert_before (&bsi, new_stmt, GSI_SAME_STMT); | |
679 } | |
680 | |
681 /* Insert NEW_STMTS after STMT. */ | |
682 | |
683 static void | |
684 insert_seq_after_stmt (gimple stmt, gimple_seq new_stmts) | |
685 { | |
686 gimple_stmt_iterator bsi; | |
687 | |
688 if (!stmt || !new_stmts) | |
689 return; | |
690 | |
691 bsi = gsi_for_stmt (stmt); | |
692 gsi_insert_seq_after (&bsi, new_stmts, GSI_SAME_STMT); | |
693 } | |
694 | |
695 /* Insert NEW_STMT after STMT. */ | |
696 | |
697 static void | |
698 insert_after_stmt (gimple stmt, gimple new_stmt) | |
699 { | |
700 gimple_stmt_iterator bsi; | |
701 | |
702 if (!stmt || !new_stmt) | |
703 return; | |
704 | |
705 bsi = gsi_for_stmt (stmt); | |
706 gsi_insert_after (&bsi, new_stmt, GSI_SAME_STMT); | |
707 } | |
708 | |
709 /* This function returns vector of allocation sites | |
710 that appear in function FN_DECL. */ | |
711 | |
712 static fallocs_t | |
713 get_fallocs (tree fn_decl) | |
714 { | |
715 return (fallocs_t) htab_find_with_hash (alloc_sites, fn_decl, | |
716 htab_hash_pointer (fn_decl)); | |
717 } | |
718 | |
719 /* If ALLOC_STMT is D.2225_7 = <alloc_func> (D.2224_6); | |
720 and it is a part of allocation of a structure, | |
721 then it is usually followed by a cast stmt | |
722 p_8 = (struct str_t *) D.2225_7; | |
723 which is returned by this function. */ | |
724 | |
725 static gimple | |
726 get_final_alloc_stmt (gimple alloc_stmt) | |
727 { | |
728 gimple final_stmt; | |
729 use_operand_p use_p; | |
730 tree alloc_res; | |
731 | |
732 if (!alloc_stmt) | |
733 return NULL; | |
734 | |
735 if (!is_gimple_call (alloc_stmt)) | |
736 return NULL; | |
737 | |
738 alloc_res = gimple_get_lhs (alloc_stmt); | |
739 | |
740 if (TREE_CODE (alloc_res) != SSA_NAME) | |
741 return NULL; | |
742 | |
743 if (!single_imm_use (alloc_res, &use_p, &final_stmt)) | |
744 return NULL; | |
745 else | |
746 return final_stmt; | |
747 } | |
748 | |
749 /* This function returns true if STMT is one of allocation | |
750 sites of function FN_DECL. It returns false otherwise. */ | |
751 | |
752 static bool | |
753 is_part_of_malloc (gimple stmt, tree fn_decl) | |
754 { | |
755 fallocs_t fallocs = get_fallocs (fn_decl); | |
756 | |
757 if (fallocs) | |
758 { | |
759 alloc_site_t *call; | |
760 unsigned i; | |
761 | |
762 for (i = 0; VEC_iterate (alloc_site_t, fallocs->allocs, i, call); i++) | |
763 if (call->stmt == stmt | |
764 || get_final_alloc_stmt (call->stmt) == stmt) | |
765 return true; | |
766 } | |
767 return false; | |
768 } | |
769 | |
770 /* Auxiliary structure for a lookup over field accesses. */ | |
771 struct find_stmt_data | |
772 { | |
773 bool found; | |
774 gimple stmt; | |
775 }; | |
776 | |
777 /* This function looks for DATA->stmt among | |
778 the statements involved in the field access, | |
779 defined by SLOT. It stops when it's found. */ | |
780 | |
781 static int | |
782 find_in_field_accs (void **slot, void *data) | |
783 { | |
784 struct field_access_site *f_acc = *(struct field_access_site **) slot; | |
785 gimple stmt = ((struct find_stmt_data *)data)->stmt; | |
786 | |
787 if (f_acc->stmt == stmt | |
788 || f_acc->ref_def_stmt == stmt | |
789 || f_acc->cast_stmt == stmt) | |
790 { | |
791 ((struct find_stmt_data *)data)->found = true; | |
792 return 0; | |
793 } | |
794 else | |
795 return 1; | |
796 } | |
797 | |
798 /* This function checks whether STMT is part of field | |
799 accesses of structure STR. It returns true, if found, | |
800 and false otherwise. */ | |
801 | |
802 static bool | |
803 is_part_of_field_access (gimple stmt, d_str str) | |
804 { | |
805 int i; | |
806 | |
807 for (i = 0; i < str->num_fields; i++) | |
808 { | |
809 struct find_stmt_data data; | |
810 data.found = false; | |
811 data.stmt = stmt; | |
812 | |
813 if (str->fields[i].acc_sites) | |
814 htab_traverse (str->fields[i].acc_sites, find_in_field_accs, &data); | |
815 | |
816 if (data.found) | |
817 return true; | |
818 } | |
819 | |
820 return false; | |
821 } | |
822 | |
823 /* Auxiliary data for exclude_from_accs function. */ | |
824 | |
825 struct exclude_data | |
826 { | |
827 tree fn_decl; | |
828 d_str str; | |
829 }; | |
830 | |
831 /* This function returns component_ref with the BASE and | |
832 field named FIELD_ID from structure TYPE. */ | |
833 | |
834 static inline tree | |
835 build_comp_ref (tree base, tree field_id, tree type) | |
836 { | |
837 tree field; | |
838 bool found = false; | |
839 | |
840 | |
841 /* Find field of structure type with the same name as field_id. */ | |
842 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) | |
843 { | |
844 if (DECL_NAME (field) == field_id) | |
845 { | |
846 found = true; | |
847 break; | |
848 } | |
849 } | |
850 | |
851 gcc_assert (found); | |
852 | |
853 return build3 (COMPONENT_REF, TREE_TYPE (field), base, field, NULL_TREE); | |
854 } | |
855 | |
856 | |
857 /* This struct represent data used for walk_tree | |
858 called from function find_pos_in_stmt. | |
859 - ref is a tree to be found, | |
860 - and pos is a pointer that points to ref in stmt. */ | |
861 struct ref_pos | |
862 { | |
863 tree *pos; | |
864 tree ref; | |
865 }; | |
866 | |
867 | |
868 /* This is a callback function for walk_tree, called from | |
869 collect_accesses_in_bb function. DATA is a pointer to ref_pos structure. | |
870 When *TP is equal to DATA->ref, the walk_tree stops, | |
871 and found position, equal to TP, is assigned to DATA->pos. */ | |
872 | |
873 static tree | |
874 find_pos_in_stmt_1 (tree *tp, int *walk_subtrees, void * data) | |
875 { | |
876 struct walk_stmt_info *wi = (struct walk_stmt_info *) data; | |
877 struct ref_pos *r_pos = (struct ref_pos *) wi->info; | |
878 tree ref = r_pos->ref; | |
879 tree t = *tp; | |
880 | |
881 if (t == ref || (TREE_CODE (t) == SSA_NAME && SSA_NAME_VAR (t) == ref)) | |
882 { | |
883 r_pos->pos = tp; | |
884 return t; | |
885 } | |
886 | |
887 *walk_subtrees = 1; | |
888 return NULL_TREE; | |
889 } | |
890 | |
891 | |
892 /* This function looks for the pointer of REF in STMT, | |
893 It returns it, if found, and NULL otherwise. */ | |
894 | |
895 static tree * | |
896 find_pos_in_stmt (gimple stmt, tree ref) | |
897 { | |
898 struct ref_pos r_pos; | |
899 struct walk_stmt_info wi; | |
900 | |
901 r_pos.ref = ref; | |
902 r_pos.pos = NULL; | |
903 memset (&wi, 0, sizeof (wi)); | |
904 wi.info = &r_pos; | |
905 walk_gimple_op (stmt, find_pos_in_stmt_1, &wi); | |
906 | |
907 return r_pos.pos; | |
908 } | |
909 | |
910 /* This structure is used to represent array | |
911 or pointer-to wrappers of structure type. | |
912 For example, if type1 is structure type, | |
913 then for type1 ** we generate two type_wrapper | |
914 structures with wrap = 0 each one. | |
915 It's used to unwind the original type up to | |
916 structure type, replace it with the new structure type | |
917 and wrap it back in the opposite order. */ | |
918 | |
919 typedef struct type_wrapper | |
920 { | |
921 /* 0 stand for pointer wrapper, and 1 for array wrapper. */ | |
922 bool wrap; | |
923 | |
924 /* Relevant for arrays as domain or index. */ | |
925 tree domain; | |
926 }type_wrapper_t; | |
927 | |
928 DEF_VEC_O (type_wrapper_t); | |
929 DEF_VEC_ALLOC_O (type_wrapper_t, heap); | |
930 | |
931 /* This function replace field access ACC by the new | |
932 field access of structure type NEW_TYPE. */ | |
933 | |
934 static void | |
935 replace_field_acc (struct field_access_site *acc, tree new_type) | |
936 { | |
937 tree ref_var = acc->ref; | |
938 tree new_ref; | |
939 tree lhs, rhs; | |
940 tree *pos; | |
941 tree new_acc; | |
942 tree field_id = DECL_NAME (acc->field_decl); | |
943 VEC (type_wrapper_t, heap) *wrapper = VEC_alloc (type_wrapper_t, heap, 10); | |
944 type_wrapper_t *wr_p = NULL; | |
945 | |
946 while (TREE_CODE (ref_var) == INDIRECT_REF | |
947 || TREE_CODE (ref_var) == ARRAY_REF) | |
948 { | |
949 type_wrapper_t wr; | |
950 | |
951 if ( TREE_CODE (ref_var) == INDIRECT_REF) | |
952 { | |
953 wr.wrap = 0; | |
954 wr.domain = 0; | |
955 } | |
956 else | |
957 { | |
958 wr.wrap = 1; | |
959 wr.domain = TREE_OPERAND (ref_var, 1); | |
960 } | |
961 | |
962 VEC_safe_push (type_wrapper_t, heap, wrapper, &wr); | |
963 ref_var = TREE_OPERAND (ref_var, 0); | |
964 } | |
965 | |
966 new_ref = find_new_var_of_type (ref_var, new_type); | |
967 finalize_global_creation (new_ref); | |
968 | |
969 while (VEC_length (type_wrapper_t, wrapper) != 0) | |
970 { | |
971 tree type = TREE_TYPE (TREE_TYPE (new_ref)); | |
972 | |
973 wr_p = VEC_last (type_wrapper_t, wrapper); | |
974 if (wr_p->wrap) /* Array. */ | |
975 new_ref = build4 (ARRAY_REF, type, new_ref, | |
976 wr_p->domain, NULL_TREE, NULL_TREE); | |
977 else /* Pointer. */ | |
978 new_ref = build1 (INDIRECT_REF, type, new_ref); | |
979 VEC_pop (type_wrapper_t, wrapper); | |
980 } | |
981 | |
982 new_acc = build_comp_ref (new_ref, field_id, new_type); | |
983 VEC_free (type_wrapper_t, heap, wrapper); | |
984 | |
985 if (is_gimple_assign (acc->stmt)) | |
986 { | |
987 lhs = gimple_assign_lhs (acc->stmt); | |
988 rhs = gimple_assign_rhs1 (acc->stmt); | |
989 | |
990 if (lhs == acc->comp_ref) | |
991 gimple_assign_set_lhs (acc->stmt, new_acc); | |
992 else if (rhs == acc->comp_ref) | |
993 gimple_assign_set_rhs1 (acc->stmt, new_acc); | |
994 else | |
995 { | |
996 pos = find_pos_in_stmt (acc->stmt, acc->comp_ref); | |
997 gcc_assert (pos); | |
998 *pos = new_acc; | |
999 } | |
1000 } | |
1001 else | |
1002 { | |
1003 pos = find_pos_in_stmt (acc->stmt, acc->comp_ref); | |
1004 gcc_assert (pos); | |
1005 *pos = new_acc; | |
1006 } | |
1007 | |
1008 finalize_stmt (acc->stmt); | |
1009 } | |
1010 | |
1011 /* This function replace field access ACC by a new field access | |
1012 of structure type NEW_TYPE. */ | |
1013 | |
1014 static void | |
1015 replace_field_access_stmt (struct field_access_site *acc, tree new_type) | |
1016 { | |
1017 | |
1018 if (TREE_CODE (acc->ref) == INDIRECT_REF | |
1019 ||TREE_CODE (acc->ref) == ARRAY_REF | |
1020 ||TREE_CODE (acc->ref) == VAR_DECL) | |
1021 replace_field_acc (acc, new_type); | |
1022 else | |
1023 gcc_unreachable (); | |
1024 } | |
1025 | |
1026 /* This function looks for d_str, represented by TYPE, in the structures | |
1027 vector. If found, it returns an index of found structure. Otherwise | |
1028 it returns a length of the structures vector. */ | |
1029 | |
1030 static unsigned | |
1031 find_structure (tree type) | |
1032 { | |
1033 d_str str; | |
1034 unsigned i; | |
1035 | |
1036 type = TYPE_MAIN_VARIANT (type); | |
1037 | |
1038 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
1039 if (is_equal_types (str->decl, type)) | |
1040 return i; | |
1041 | |
1042 return VEC_length (structure, structures); | |
1043 } | |
1044 | |
1045 /* In this function we create new statements that have the same | |
1046 form as ORIG_STMT, but of type NEW_TYPE. The statements | |
1047 treated by this function are simple assignments, | |
1048 like assignments: p.8_7 = p; or statements with rhs of | |
1049 tree codes PLUS_EXPR and MINUS_EXPR. */ | |
1050 | |
1051 static gimple | |
1052 create_base_plus_offset (gimple orig_stmt, tree new_type, tree offset) | |
1053 { | |
1054 tree lhs; | |
1055 tree new_lhs; | |
1056 gimple new_stmt; | |
1057 tree new_op0 = NULL_TREE, new_op1 = NULL_TREE; | |
1058 | |
1059 lhs = gimple_assign_lhs (orig_stmt); | |
1060 | |
1061 gcc_assert (TREE_CODE (lhs) == VAR_DECL | |
1062 || TREE_CODE (lhs) == SSA_NAME); | |
1063 | |
1064 new_lhs = find_new_var_of_type (lhs, new_type); | |
1065 gcc_assert (new_lhs); | |
1066 finalize_var_creation (new_lhs); | |
1067 | |
1068 switch (gimple_assign_rhs_code (orig_stmt)) | |
1069 { | |
1070 case PLUS_EXPR: | |
1071 case MINUS_EXPR: | |
1072 case POINTER_PLUS_EXPR: | |
1073 { | |
1074 tree op0 = gimple_assign_rhs1 (orig_stmt); | |
1075 tree op1 = gimple_assign_rhs2 (orig_stmt); | |
1076 unsigned str0, str1; | |
1077 unsigned length = VEC_length (structure, structures); | |
1078 | |
1079 | |
1080 str0 = find_structure (strip_type (get_type_of_var (op0))); | |
1081 str1 = find_structure (strip_type (get_type_of_var (op1))); | |
1082 gcc_assert ((str0 != length) || (str1 != length)); | |
1083 | |
1084 if (str0 != length) | |
1085 new_op0 = find_new_var_of_type (op0, new_type); | |
1086 if (str1 != length) | |
1087 new_op1 = find_new_var_of_type (op1, new_type); | |
1088 | |
1089 if (!new_op0) | |
1090 new_op0 = offset; | |
1091 if (!new_op1) | |
1092 new_op1 = offset; | |
1093 } | |
1094 break; | |
1095 | |
1096 default: | |
1097 gcc_unreachable(); | |
1098 } | |
1099 | |
1100 new_stmt = gimple_build_assign_with_ops (gimple_assign_rhs_code (orig_stmt), | |
1101 new_lhs, new_op0, new_op1); | |
1102 finalize_stmt (new_stmt); | |
1103 | |
1104 return new_stmt; | |
1105 } | |
1106 | |
1107 /* Given a field access F_ACC of the FIELD, this function | |
1108 replaces it by the new field access. */ | |
1109 | |
1110 static void | |
1111 create_new_field_access (struct field_access_site *f_acc, | |
1112 struct field_entry field) | |
1113 { | |
1114 tree new_type = field.field_mapping; | |
1115 gimple new_stmt; | |
1116 tree size_res; | |
1117 gimple mult_stmt; | |
1118 gimple cast_stmt; | |
1119 tree cast_res = NULL; | |
1120 | |
1121 if (f_acc->num) | |
1122 { | |
1123 mult_stmt = gen_size (f_acc->num, new_type, &size_res); | |
1124 insert_before_stmt (f_acc->ref_def_stmt, mult_stmt); | |
1125 } | |
1126 | |
1127 if (f_acc->cast_stmt) | |
1128 { | |
1129 cast_stmt = gen_cast_stmt (size_res, new_type, | |
1130 f_acc->cast_stmt, &cast_res); | |
1131 insert_after_stmt (f_acc->cast_stmt, cast_stmt); | |
1132 } | |
1133 | |
1134 if (f_acc->ref_def_stmt) | |
1135 { | |
1136 tree offset; | |
1137 if (cast_res) | |
1138 offset = cast_res; | |
1139 else | |
1140 offset = size_res; | |
1141 | |
1142 new_stmt = create_base_plus_offset (f_acc->ref_def_stmt, | |
1143 new_type, offset); | |
1144 insert_after_stmt (f_acc->ref_def_stmt, new_stmt); | |
1145 } | |
1146 | |
1147 /* In stmt D.2163_19 = D.2162_18->b; we replace variable | |
1148 D.2162_18 by an appropriate variable of new_type type. */ | |
1149 replace_field_access_stmt (f_acc, new_type); | |
1150 } | |
1151 | |
1152 /* This function creates a new condition statement | |
1153 corresponding to the original COND_STMT, adds new basic block | |
1154 and redirects condition edges. NEW_VAR is a new condition | |
1155 variable located in the condition statement at the position POS. */ | |
1156 | |
1157 static void | |
1158 create_new_stmts_for_cond_expr_1 (tree new_var, gimple cond_stmt, unsigned pos) | |
1159 { | |
1160 gimple new_stmt; | |
1161 edge true_e = NULL, false_e = NULL; | |
1162 basic_block new_bb; | |
1163 gimple_stmt_iterator si; | |
1164 | |
1165 extract_true_false_edges_from_block (gimple_bb (cond_stmt), | |
1166 &true_e, &false_e); | |
1167 | |
1168 new_stmt = gimple_build_cond (gimple_cond_code (cond_stmt), | |
1169 pos == 0 ? new_var : gimple_cond_lhs (cond_stmt), | |
1170 pos == 1 ? new_var : gimple_cond_rhs (cond_stmt), | |
1171 NULL_TREE, | |
1172 NULL_TREE); | |
1173 | |
1174 finalize_stmt (new_stmt); | |
1175 | |
1176 /* Create new basic block after bb. */ | |
1177 new_bb = create_empty_bb (gimple_bb (cond_stmt)); | |
1178 | |
1179 /* Add new condition stmt to the new_bb. */ | |
1180 si = gsi_start_bb (new_bb); | |
1181 gsi_insert_after (&si, new_stmt, GSI_NEW_STMT); | |
1182 | |
1183 /* Create false and true edges from new_bb. */ | |
1184 make_edge_and_fix_phis_of_dest (new_bb, true_e); | |
1185 make_edge_and_fix_phis_of_dest (new_bb, false_e); | |
1186 | |
1187 /* Redirect one of original edges to point to new_bb. */ | |
1188 if (gimple_cond_code (cond_stmt) == NE_EXPR) | |
1189 redirect_edge_succ (true_e, new_bb); | |
1190 else | |
1191 redirect_edge_succ (false_e, new_bb); | |
1192 } | |
1193 | |
1194 /* This function creates new condition statements corresponding | |
1195 to original condition STMT, one for each new type, and | |
1196 recursively redirect edges to newly generated basic blocks. */ | |
1197 | |
1198 static void | |
1199 create_new_stmts_for_cond_expr (gimple stmt) | |
1200 { | |
1201 tree arg0, arg1, arg; | |
1202 unsigned str0, str1; | |
1203 bool s0, s1; | |
1204 d_str str; | |
1205 tree type; | |
1206 unsigned pos; | |
1207 int i; | |
1208 unsigned length = VEC_length (structure, structures); | |
1209 | |
1210 gcc_assert (gimple_cond_code (stmt) == EQ_EXPR | |
1211 || gimple_cond_code (stmt) == NE_EXPR); | |
1212 | |
1213 arg0 = gimple_cond_lhs (stmt); | |
1214 arg1 = gimple_cond_rhs (stmt); | |
1215 | |
1216 str0 = find_structure (strip_type (get_type_of_var (arg0))); | |
1217 str1 = find_structure (strip_type (get_type_of_var (arg1))); | |
1218 | |
1219 s0 = (str0 != length) ? true : false; | |
1220 s1 = (str1 != length) ? true : false; | |
1221 | |
1222 gcc_assert (s0 || s1); | |
1223 /* For now we allow only comparison with 0 or NULL. */ | |
1224 gcc_assert (integer_zerop (arg0) || integer_zerop (arg1)); | |
1225 | |
1226 str = integer_zerop (arg0) ? | |
1227 VEC_index (structure, structures, str1): | |
1228 VEC_index (structure, structures, str0); | |
1229 arg = integer_zerop (arg0) ? arg1 : arg0; | |
1230 pos = integer_zerop (arg0) ? 1 : 0; | |
1231 | |
1232 for (i = 0; VEC_iterate (tree, str->new_types, i, type); i++) | |
1233 { | |
1234 tree new_arg; | |
1235 | |
1236 new_arg = find_new_var_of_type (arg, type); | |
1237 create_new_stmts_for_cond_expr_1 (new_arg, stmt, pos); | |
1238 } | |
1239 } | |
1240 | |
1241 /* Create a new general access to replace original access ACC | |
1242 for structure type NEW_TYPE. */ | |
1243 | |
1244 static gimple | |
1245 create_general_new_stmt (struct access_site *acc, tree new_type) | |
1246 { | |
1247 gimple old_stmt = acc->stmt; | |
1248 tree var; | |
1249 gimple new_stmt = gimple_copy (old_stmt); | |
1250 unsigned i; | |
1251 | |
1252 for (i = 0; VEC_iterate (tree, acc->vars, i, var); i++) | |
1253 { | |
1254 tree *pos; | |
1255 tree new_var = find_new_var_of_type (var, new_type); | |
1256 tree lhs, rhs = NULL_TREE; | |
1257 | |
1258 gcc_assert (new_var); | |
1259 finalize_var_creation (new_var); | |
1260 | |
1261 if (is_gimple_assign (new_stmt)) | |
1262 { | |
1263 lhs = gimple_assign_lhs (new_stmt); | |
1264 | |
1265 if (TREE_CODE (lhs) == SSA_NAME) | |
1266 lhs = SSA_NAME_VAR (lhs); | |
1267 if (gimple_assign_rhs_code (new_stmt) == SSA_NAME) | |
1268 rhs = SSA_NAME_VAR (gimple_assign_rhs1 (new_stmt)); | |
1269 | |
1270 /* It can happen that rhs is a constructor. | |
1271 Then we have to replace it to be of new_type. */ | |
1272 if (gimple_assign_rhs_code (new_stmt) == CONSTRUCTOR) | |
1273 { | |
1274 /* Dealing only with empty constructors right now. */ | |
1275 gcc_assert (VEC_empty (constructor_elt, | |
1276 CONSTRUCTOR_ELTS (rhs))); | |
1277 rhs = build_constructor (new_type, 0); | |
1278 gimple_assign_set_rhs1 (new_stmt, rhs); | |
1279 } | |
1280 | |
1281 if (lhs == var) | |
1282 gimple_assign_set_lhs (new_stmt, new_var); | |
1283 else if (rhs == var) | |
1284 gimple_assign_set_rhs1 (new_stmt, new_var); | |
1285 else | |
1286 { | |
1287 pos = find_pos_in_stmt (new_stmt, var); | |
1288 gcc_assert (pos); | |
1289 *pos = new_var; | |
1290 } | |
1291 } | |
1292 else | |
1293 { | |
1294 pos = find_pos_in_stmt (new_stmt, var); | |
1295 gcc_assert (pos); | |
1296 *pos = new_var; | |
1297 } | |
1298 } | |
1299 | |
1300 finalize_stmt (new_stmt); | |
1301 return new_stmt; | |
1302 } | |
1303 | |
1304 /* For each new type in STR this function creates new general accesses | |
1305 corresponding to the original access ACC. */ | |
1306 | |
1307 static void | |
1308 create_new_stmts_for_general_acc (struct access_site *acc, d_str str) | |
1309 { | |
1310 tree type; | |
1311 gimple stmt = acc->stmt; | |
1312 unsigned i; | |
1313 | |
1314 for (i = 0; VEC_iterate (tree, str->new_types, i, type); i++) | |
1315 { | |
1316 gimple new_stmt; | |
1317 | |
1318 new_stmt = create_general_new_stmt (acc, type); | |
1319 insert_after_stmt (stmt, new_stmt); | |
1320 } | |
1321 } | |
1322 | |
1323 /* This function creates a new general access of structure STR | |
1324 to replace the access ACC. */ | |
1325 | |
1326 static void | |
1327 create_new_general_access (struct access_site *acc, d_str str) | |
1328 { | |
1329 gimple stmt = acc->stmt; | |
1330 switch (gimple_code (stmt)) | |
1331 { | |
1332 case GIMPLE_COND: | |
1333 create_new_stmts_for_cond_expr (stmt); | |
1334 break; | |
1335 | |
1336 default: | |
1337 create_new_stmts_for_general_acc (acc, str); | |
1338 } | |
1339 } | |
1340 | |
1341 /* Auxiliary data for creation of accesses. */ | |
1342 struct create_acc_data | |
1343 { | |
1344 basic_block bb; | |
1345 d_str str; | |
1346 int field_index; | |
1347 }; | |
1348 | |
1349 /* This function creates a new general access, defined by SLOT. | |
1350 DATA is a pointer to create_acc_data structure. */ | |
1351 | |
1352 static int | |
1353 create_new_acc (void **slot, void *data) | |
1354 { | |
1355 struct access_site *acc = *(struct access_site **) slot; | |
1356 basic_block bb = ((struct create_acc_data *)data)->bb; | |
1357 d_str str = ((struct create_acc_data *)data)->str; | |
1358 | |
1359 if (gimple_bb (acc->stmt) == bb) | |
1360 create_new_general_access (acc, str); | |
1361 return 1; | |
1362 } | |
1363 | |
1364 /* This function creates a new field access, defined by SLOT. | |
1365 DATA is a pointer to create_acc_data structure. */ | |
1366 | |
1367 static int | |
1368 create_new_field_acc (void **slot, void *data) | |
1369 { | |
1370 struct field_access_site *f_acc = *(struct field_access_site **) slot; | |
1371 basic_block bb = ((struct create_acc_data *)data)->bb; | |
1372 d_str str = ((struct create_acc_data *)data)->str; | |
1373 int i = ((struct create_acc_data *)data)->field_index; | |
1374 | |
1375 if (gimple_bb (f_acc->stmt) == bb) | |
1376 create_new_field_access (f_acc, str->fields[i]); | |
1377 return 1; | |
1378 } | |
1379 | |
1380 /* This function creates new accesses for the structure | |
1381 type STR in basic block BB. */ | |
1382 | |
1383 static void | |
1384 create_new_accs_for_struct (d_str str, basic_block bb) | |
1385 { | |
1386 int i; | |
1387 struct create_acc_data dt; | |
1388 | |
1389 dt.str = str; | |
1390 dt.bb = bb; | |
1391 dt.field_index = -1; | |
1392 | |
1393 for (i = 0; i < str->num_fields; i++) | |
1394 { | |
1395 dt.field_index = i; | |
1396 | |
1397 if (str->fields[i].acc_sites) | |
1398 htab_traverse (str->fields[i].acc_sites, | |
1399 create_new_field_acc, &dt); | |
1400 } | |
1401 if (str->accs) | |
1402 htab_traverse (str->accs, create_new_acc, &dt); | |
1403 } | |
1404 | |
1405 /* This function inserts new variables from new_var, | |
1406 defined by SLOT, into varpool. */ | |
1407 | |
1408 static int | |
1409 update_varpool_with_new_var (void **slot, void *data ATTRIBUTE_UNUSED) | |
1410 { | |
1411 new_var n_var = *(new_var *) slot; | |
1412 tree var; | |
1413 unsigned i; | |
1414 | |
1415 for (i = 0; VEC_iterate (tree, n_var->new_vars, i, var); i++) | |
1416 insert_global_to_varpool (var); | |
1417 return 1; | |
1418 } | |
1419 | |
1420 /* This function prints a field access site, defined by SLOT. */ | |
1421 | |
1422 static int | |
1423 dump_field_acc (void **slot, void *data ATTRIBUTE_UNUSED) | |
1424 { | |
1425 struct field_access_site *f_acc = | |
1426 *(struct field_access_site **) slot; | |
1427 | |
1428 fprintf(dump_file, "\n"); | |
1429 if (f_acc->stmt) | |
1430 print_gimple_stmt (dump_file, f_acc->stmt, 0, 0); | |
1431 if (f_acc->ref_def_stmt) | |
1432 print_gimple_stmt (dump_file, f_acc->ref_def_stmt, 0, 0); | |
1433 if (f_acc->cast_stmt) | |
1434 print_gimple_stmt (dump_file, f_acc->cast_stmt, 0, 0); | |
1435 return 1; | |
1436 } | |
1437 | |
1438 /* Print field accesses from hashtable F_ACCS. */ | |
1439 | |
1440 static void | |
1441 dump_field_acc_sites (htab_t f_accs) | |
1442 { | |
1443 if (!dump_file) | |
1444 return; | |
1445 | |
1446 if (f_accs) | |
1447 htab_traverse (f_accs, dump_field_acc, NULL); | |
1448 } | |
1449 | |
1450 /* Hash value for fallocs_t. */ | |
1451 | |
1452 static hashval_t | |
1453 malloc_hash (const void *x) | |
1454 { | |
1455 return htab_hash_pointer (((const_fallocs_t)x)->func); | |
1456 } | |
1457 | |
1458 /* This function returns nonzero if function of func_alloc_sites' X | |
1459 is equal to Y. */ | |
1460 | |
1461 static int | |
1462 malloc_eq (const void *x, const void *y) | |
1463 { | |
1464 return ((const_fallocs_t)x)->func == (const_tree)y; | |
1465 } | |
1466 | |
1467 /* This function is a callback for traversal over a structure accesses. | |
1468 It frees an access represented by SLOT. */ | |
1469 | |
1470 static int | |
1471 free_accs (void **slot, void *data ATTRIBUTE_UNUSED) | |
1472 { | |
1473 struct access_site * acc = *(struct access_site **) slot; | |
1474 | |
1475 VEC_free (tree, heap, acc->vars); | |
1476 free (acc); | |
1477 return 1; | |
1478 } | |
1479 | |
1480 /* This is a callback function for traversal over field accesses. | |
1481 It frees a field access represented by SLOT. */ | |
1482 | |
1483 static int | |
1484 free_field_accs (void **slot, void *data ATTRIBUTE_UNUSED) | |
1485 { | |
1486 struct field_access_site *f_acc = *(struct field_access_site **) slot; | |
1487 | |
1488 free (f_acc); | |
1489 return 1; | |
1490 } | |
1491 | |
1492 /* This function inserts TYPE into vector of UNSUITABLE_TYPES, | |
1493 if it is not there yet. */ | |
1494 | |
1495 static void | |
1496 add_unsuitable_type (VEC (tree, heap) **unsuitable_types, tree type) | |
1497 { | |
1498 unsigned i; | |
1499 tree t; | |
1500 | |
1501 if (!type) | |
1502 return; | |
1503 | |
1504 type = TYPE_MAIN_VARIANT (type); | |
1505 | |
1506 for (i = 0; VEC_iterate (tree, *unsuitable_types, i, t); i++) | |
1507 if (is_equal_types (t, type)) | |
1508 break; | |
1509 | |
1510 if (i == VEC_length (tree, *unsuitable_types)) | |
1511 VEC_safe_push (tree, heap, *unsuitable_types, type); | |
1512 } | |
1513 | |
1514 /* Given a type TYPE, this function returns the name of the type. */ | |
1515 | |
1516 static const char * | |
1517 get_type_name (tree type) | |
1518 { | |
1519 if (! TYPE_NAME (type)) | |
1520 return NULL; | |
1521 | |
1522 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) | |
1523 return IDENTIFIER_POINTER (TYPE_NAME (type)); | |
1524 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL | |
1525 && DECL_NAME (TYPE_NAME (type))) | |
1526 return IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); | |
1527 else | |
1528 return NULL; | |
1529 } | |
1530 | |
1531 /* This function is a temporary hack to overcome the types problem. | |
1532 When several compilation units are compiled together | |
1533 with -combine, the TYPE_MAIN_VARIANT of the same type | |
1534 can appear differently in different compilation units. | |
1535 Therefore this function first compares type names. | |
1536 If there are no names, structure bodies are recursively | |
1537 compared. */ | |
1538 | |
1539 static bool | |
1540 is_equal_types (tree type1, tree type2) | |
1541 { | |
1542 const char * name1,* name2; | |
1543 | |
1544 if ((!type1 && type2) | |
1545 ||(!type2 && type1)) | |
1546 return false; | |
1547 | |
1548 if (!type1 && !type2) | |
1549 return true; | |
1550 | |
1551 if (TREE_CODE (type1) != TREE_CODE (type2)) | |
1552 return false; | |
1553 | |
1554 if (type1 == type2) | |
1555 return true; | |
1556 | |
1557 if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)) | |
1558 return true; | |
1559 | |
1560 name1 = get_type_name (type1); | |
1561 name2 = get_type_name (type2); | |
1562 | |
1563 if (name1 && name2 && !strcmp (name1, name2)) | |
1564 return true; | |
1565 | |
1566 if (name1 && name2 && strcmp (name1, name2)) | |
1567 return false; | |
1568 | |
1569 switch (TREE_CODE (type1)) | |
1570 { | |
1571 case POINTER_TYPE: | |
1572 case REFERENCE_TYPE: | |
1573 { | |
1574 return is_equal_types (TREE_TYPE (type1), TREE_TYPE (type2)); | |
1575 } | |
1576 break; | |
1577 | |
1578 case RECORD_TYPE: | |
1579 case UNION_TYPE: | |
1580 case QUAL_UNION_TYPE: | |
1581 case ENUMERAL_TYPE: | |
1582 { | |
1583 tree field1; | |
1584 /* Compare fields of structure. */ | |
1585 for (field1 = TYPE_FIELDS (type1); field1; | |
1586 field1 = TREE_CHAIN (field1)) | |
1587 { | |
1588 tree field2 = find_field_in_struct_1 (type2, field1); | |
1589 if (!field2) | |
1590 return false; | |
1591 } | |
1592 return true; | |
1593 } | |
1594 break; | |
1595 | |
1596 case INTEGER_TYPE: | |
1597 { | |
1598 if (TYPE_UNSIGNED (type1) == TYPE_UNSIGNED (type2) | |
1599 && TYPE_PRECISION (type1) == TYPE_PRECISION (type2)) | |
1600 return true; | |
1601 } | |
1602 break; | |
1603 | |
1604 case ARRAY_TYPE: | |
1605 { | |
1606 tree d1, d2; | |
1607 tree max1, min1, max2, min2; | |
1608 | |
1609 if (!is_equal_types (TREE_TYPE (type1), TREE_TYPE (type2))) | |
1610 return false; | |
1611 | |
1612 d1 = TYPE_DOMAIN (type1); | |
1613 d2 = TYPE_DOMAIN (type2); | |
1614 | |
1615 if (!d1 || !d2) | |
1616 return false; | |
1617 | |
1618 max1 = TYPE_MAX_VALUE (d1); | |
1619 max2 = TYPE_MAX_VALUE (d2); | |
1620 min1 = TYPE_MIN_VALUE (d1); | |
1621 min2 = TYPE_MIN_VALUE (d2); | |
1622 | |
1623 if (max1 && max2 && min1 && min2 | |
1624 && TREE_CODE (max1) == TREE_CODE (max2) | |
1625 && TREE_CODE (max1) == INTEGER_CST | |
1626 && TREE_CODE (min1) == TREE_CODE (min2) | |
1627 && TREE_CODE (min1) == INTEGER_CST | |
1628 && tree_int_cst_equal (max1, max2) | |
1629 && tree_int_cst_equal (min1, min2)) | |
1630 return true; | |
1631 } | |
1632 break; | |
1633 | |
1634 default: | |
1635 gcc_unreachable(); | |
1636 } | |
1637 | |
1638 return false; | |
1639 } | |
1640 | |
1641 /* This function free non-field accesses from hashtable ACCS. */ | |
1642 | |
1643 static void | |
1644 free_accesses (htab_t accs) | |
1645 { | |
1646 if (accs) | |
1647 htab_traverse (accs, free_accs, NULL); | |
1648 htab_delete (accs); | |
1649 } | |
1650 | |
1651 /* This function free field accesses hashtable F_ACCS. */ | |
1652 | |
1653 static void | |
1654 free_field_accesses (htab_t f_accs) | |
1655 { | |
1656 if (f_accs) | |
1657 htab_traverse (f_accs, free_field_accs, NULL); | |
1658 htab_delete (f_accs); | |
1659 } | |
1660 | |
1661 /* Update call graph with new edge generated by new MALLOC_STMT. | |
1662 The edge origin is CONTEXT function. */ | |
1663 | |
1664 static void | |
1665 update_cgraph_with_malloc_call (gimple malloc_stmt, tree context) | |
1666 { | |
1667 struct cgraph_node *src, *dest; | |
1668 tree malloc_fn_decl; | |
1669 | |
1670 if (!malloc_stmt) | |
1671 return; | |
1672 | |
1673 malloc_fn_decl = gimple_call_fndecl (malloc_stmt); | |
1674 | |
1675 src = cgraph_node (context); | |
1676 dest = cgraph_node (malloc_fn_decl); | |
1677 cgraph_create_edge (src, dest, malloc_stmt, | |
1678 0, 0, gimple_bb (malloc_stmt)->loop_depth); | |
1679 } | |
1680 | |
1681 /* This function generates set of statements required | |
1682 to allocate number NUM of structures of type NEW_TYPE. | |
1683 The statements are stored in NEW_STMTS. The statement that contain | |
1684 call to malloc is returned. MALLOC_STMT is an original call to malloc. */ | |
1685 | |
1686 static gimple | |
1687 create_new_malloc (gimple malloc_stmt, tree new_type, gimple_seq *new_stmts, | |
1688 tree num) | |
1689 { | |
1690 tree new_malloc_size; | |
1691 tree malloc_fn_decl; | |
1692 gimple new_stmt; | |
1693 tree malloc_res; | |
1694 gimple call_stmt, final_stmt; | |
1695 tree cast_res; | |
1696 | |
1697 gcc_assert (num && malloc_stmt && new_type); | |
1698 *new_stmts = gimple_seq_alloc (); | |
1699 | |
1700 /* Generate argument to malloc as multiplication of num | |
1701 and size of new_type. */ | |
1702 new_stmt = gen_size (num, new_type, &new_malloc_size); | |
1703 gimple_seq_add_stmt (new_stmts, new_stmt); | |
1704 | |
1705 /* Generate new call for malloc. */ | |
1706 malloc_res = create_tmp_var (ptr_type_node, NULL); | |
1707 add_referenced_var (malloc_res); | |
1708 | |
1709 malloc_fn_decl = gimple_call_fndecl (malloc_stmt); | |
1710 call_stmt = gimple_build_call (malloc_fn_decl, 1, new_malloc_size); | |
1711 gimple_call_set_lhs (call_stmt, malloc_res); | |
1712 finalize_stmt_and_append (new_stmts, call_stmt); | |
1713 | |
1714 /* Create new cast statement. */ | |
1715 final_stmt = get_final_alloc_stmt (malloc_stmt); | |
1716 gcc_assert (final_stmt); | |
1717 new_stmt = gen_cast_stmt (malloc_res, new_type, final_stmt, &cast_res); | |
1718 gimple_seq_add_stmt (new_stmts, new_stmt); | |
1719 | |
1720 return call_stmt; | |
1721 } | |
1722 | |
1723 /* This function returns a tree representing | |
1724 the number of instances of structure STR_DECL allocated | |
1725 by allocation STMT. If new statements are generated, | |
1726 they are filled into NEW_STMTS_P. */ | |
1727 | |
1728 static tree | |
1729 gen_num_of_structs_in_malloc (gimple stmt, tree str_decl, | |
1730 gimple_seq *new_stmts_p) | |
1731 { | |
1732 tree arg; | |
1733 tree struct_size; | |
1734 HOST_WIDE_INT struct_size_int; | |
1735 | |
1736 if (!stmt) | |
1737 return NULL_TREE; | |
1738 | |
1739 /* Get malloc argument. */ | |
1740 if (!is_gimple_call (stmt)) | |
1741 return NULL_TREE; | |
1742 | |
1743 arg = gimple_call_arg (stmt, 0); | |
1744 | |
1745 if (TREE_CODE (arg) != SSA_NAME | |
1746 && !TREE_CONSTANT (arg)) | |
1747 return NULL_TREE; | |
1748 | |
1749 struct_size = TYPE_SIZE_UNIT (str_decl); | |
1750 struct_size_int = TREE_INT_CST_LOW (struct_size); | |
1751 | |
1752 gcc_assert (struct_size); | |
1753 | |
1754 if (TREE_CODE (arg) == SSA_NAME) | |
1755 { | |
1756 tree num; | |
1757 gimple div_stmt; | |
1758 | |
1759 if (is_result_of_mult (arg, &num, struct_size)) | |
1760 return num; | |
1761 | |
1762 num = create_tmp_var (integer_type_node, NULL); | |
1763 | |
1764 if (num) | |
1765 add_referenced_var (num); | |
1766 | |
1767 if (exact_log2 (struct_size_int) == -1) | |
1768 div_stmt = gimple_build_assign_with_ops (TRUNC_DIV_EXPR, num, arg, | |
1769 struct_size); | |
1770 else | |
1771 { | |
1772 tree C = build_int_cst (integer_type_node, | |
1773 exact_log2 (struct_size_int)); | |
1774 | |
1775 div_stmt = gimple_build_assign_with_ops (RSHIFT_EXPR, num, arg, C); | |
1776 } | |
1777 gimple_seq_add_stmt (new_stmts_p, div_stmt); | |
1778 finalize_stmt (div_stmt); | |
1779 return num; | |
1780 } | |
1781 | |
1782 if (CONSTANT_CLASS_P (arg) | |
1783 && multiple_of_p (TREE_TYPE (struct_size), arg, struct_size)) | |
1784 return int_const_binop (TRUNC_DIV_EXPR, arg, struct_size, 0); | |
1785 | |
1786 return NULL_TREE; | |
1787 } | |
1788 | |
1789 /* This function is a callback for traversal on new_var's hashtable. | |
1790 SLOT is a pointer to new_var. This function prints to dump_file | |
1791 an original variable and all new variables from the new_var | |
1792 pointed by *SLOT. */ | |
1793 | |
1794 static int | |
1795 dump_new_var (void **slot, void *data ATTRIBUTE_UNUSED) | |
1796 { | |
1797 new_var n_var = *(new_var *) slot; | |
1798 tree var_type; | |
1799 tree var; | |
1800 unsigned i; | |
1801 | |
1802 var_type = get_type_of_var (n_var->orig_var); | |
1803 | |
1804 fprintf (dump_file, "\nOrig var: "); | |
1805 print_generic_expr (dump_file, n_var->orig_var, 0); | |
1806 fprintf (dump_file, " of type "); | |
1807 print_generic_expr (dump_file, var_type, 0); | |
1808 fprintf (dump_file, "\n"); | |
1809 | |
1810 for (i = 0; | |
1811 VEC_iterate (tree, n_var->new_vars, i, var); i++) | |
1812 { | |
1813 var_type = get_type_of_var (var); | |
1814 | |
1815 fprintf (dump_file, " "); | |
1816 print_generic_expr (dump_file, var, 0); | |
1817 fprintf (dump_file, " of type "); | |
1818 print_generic_expr (dump_file, var_type, 0); | |
1819 fprintf (dump_file, "\n"); | |
1820 } | |
1821 return 1; | |
1822 } | |
1823 | |
1824 /* This function copies attributes form ORIG_DECL to NEW_DECL. */ | |
1825 | |
1826 static inline void | |
1827 copy_decl_attributes (tree new_decl, tree orig_decl) | |
1828 { | |
1829 | |
1830 DECL_ARTIFICIAL (new_decl) = 1; | |
1831 DECL_EXTERNAL (new_decl) = DECL_EXTERNAL (orig_decl); | |
1832 TREE_STATIC (new_decl) = TREE_STATIC (orig_decl); | |
1833 TREE_PUBLIC (new_decl) = TREE_PUBLIC (orig_decl); | |
1834 TREE_USED (new_decl) = TREE_USED (orig_decl); | |
1835 DECL_CONTEXT (new_decl) = DECL_CONTEXT (orig_decl); | |
1836 TREE_THIS_VOLATILE (new_decl) = TREE_THIS_VOLATILE (orig_decl); | |
1837 TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (orig_decl); | |
1838 | |
1839 if (TREE_CODE (orig_decl) == VAR_DECL) | |
1840 { | |
1841 TREE_READONLY (new_decl) = TREE_READONLY (orig_decl); | |
1842 DECL_TLS_MODEL (new_decl) = DECL_TLS_MODEL (orig_decl); | |
1843 } | |
1844 } | |
1845 | |
1846 /* This function wraps NEW_STR_TYPE in pointers or arrays wrapper | |
1847 the same way as a structure type is wrapped in DECL. | |
1848 It returns the generated type. */ | |
1849 | |
1850 static inline tree | |
1851 gen_struct_type (tree decl, tree new_str_type) | |
1852 { | |
1853 tree type_orig = get_type_of_var (decl); | |
1854 tree new_type = new_str_type; | |
1855 VEC (type_wrapper_t, heap) *wrapper = VEC_alloc (type_wrapper_t, heap, 10); | |
1856 type_wrapper_t wr; | |
1857 type_wrapper_t *wr_p; | |
1858 | |
1859 while (POINTER_TYPE_P (type_orig) | |
1860 || TREE_CODE (type_orig) == ARRAY_TYPE) | |
1861 { | |
1862 if (POINTER_TYPE_P (type_orig)) | |
1863 { | |
1864 wr.wrap = 0; | |
1865 wr.domain = NULL_TREE; | |
1866 } | |
1867 else | |
1868 { | |
1869 gcc_assert (TREE_CODE (type_orig) == ARRAY_TYPE); | |
1870 wr.wrap = 1; | |
1871 wr.domain = TYPE_DOMAIN (type_orig); | |
1872 } | |
1873 VEC_safe_push (type_wrapper_t, heap, wrapper, &wr); | |
1874 type_orig = TREE_TYPE (type_orig); | |
1875 } | |
1876 | |
1877 while (VEC_length (type_wrapper_t, wrapper) != 0) | |
1878 { | |
1879 wr_p = VEC_last (type_wrapper_t, wrapper); | |
1880 | |
1881 if (wr_p->wrap) /* Array. */ | |
1882 new_type = build_array_type (new_type, wr_p->domain); | |
1883 else /* Pointer. */ | |
1884 new_type = build_pointer_type (new_type); | |
1885 | |
1886 VEC_pop (type_wrapper_t, wrapper); | |
1887 } | |
1888 | |
1889 VEC_free (type_wrapper_t, heap, wrapper); | |
1890 return new_type; | |
1891 } | |
1892 | |
1893 /* This function generates and returns new variable name based on | |
1894 ORIG_DECL name, combined with index I. | |
1895 The form of the new name is <orig_name>.<I> . */ | |
1896 | |
1897 static tree | |
1898 gen_var_name (tree orig_decl, unsigned HOST_WIDE_INT i) | |
1899 { | |
1900 const char *old_name; | |
1901 char *prefix; | |
1902 char *new_name; | |
1903 | |
1904 if (!DECL_NAME (orig_decl) | |
1905 || !IDENTIFIER_POINTER (DECL_NAME (orig_decl))) | |
1906 return NULL; | |
1907 | |
1908 /* If the original variable has a name, create an | |
1909 appropriate new name for the new variable. */ | |
1910 | |
1911 old_name = IDENTIFIER_POINTER (DECL_NAME (orig_decl)); | |
1912 prefix = XALLOCAVEC (char, strlen (old_name) + 1); | |
1913 strcpy (prefix, old_name); | |
1914 ASM_FORMAT_PRIVATE_NAME (new_name, prefix, i); | |
1915 return get_identifier (new_name); | |
1916 } | |
1917 | |
1918 /* This function adds NEW_NODE to hashtable of new_var's NEW_VARS_HTAB. */ | |
1919 | |
1920 static void | |
1921 add_to_new_vars_htab (new_var new_node, htab_t new_vars_htab) | |
1922 { | |
1923 void **slot; | |
1924 | |
1925 slot = htab_find_slot_with_hash (new_vars_htab, new_node->orig_var, | |
1926 htab_hash_pointer (new_node->orig_var), | |
1927 INSERT); | |
1928 *slot = new_node; | |
1929 } | |
1930 | |
1931 /* This function creates and returns new_var_data node | |
1932 with empty new_vars and orig_var equal to VAR. */ | |
1933 | |
1934 static new_var | |
1935 create_new_var_node (tree var, d_str str) | |
1936 { | |
1937 new_var node; | |
1938 | |
1939 node = (new_var) xmalloc (sizeof (struct new_var_data)); | |
1940 node->orig_var = var; | |
1941 node->new_vars = VEC_alloc (tree, heap, VEC_length (tree, str->new_types)); | |
1942 return node; | |
1943 } | |
1944 | |
1945 /* Check whether the type of VAR is potential candidate for peeling. | |
1946 Returns true if yes, false otherwise. If yes, TYPE_P will contain | |
1947 candidate type. If VAR is initialized, the type of VAR will be added | |
1948 to UNSUITABLE_TYPES. */ | |
1949 | |
1950 static bool | |
1951 is_candidate (tree var, tree *type_p, VEC (tree, heap) **unsuitable_types) | |
1952 { | |
1953 tree type; | |
1954 bool initialized = false; | |
1955 | |
1956 *type_p = NULL; | |
1957 | |
1958 if (!var) | |
1959 return false; | |
1960 | |
1961 /* There is no support of initialized vars. */ | |
1962 if (TREE_CODE (var) == VAR_DECL | |
1963 && DECL_INITIAL (var) != NULL_TREE) | |
1964 initialized = true; | |
1965 | |
1966 type = get_type_of_var (var); | |
1967 | |
1968 if (type) | |
1969 { | |
1970 type = TYPE_MAIN_VARIANT (strip_type (type)); | |
1971 if (TREE_CODE (type) != RECORD_TYPE) | |
1972 return false; | |
1973 else | |
1974 { | |
1975 if (initialized && unsuitable_types && *unsuitable_types) | |
1976 { | |
1977 if (dump_file) | |
1978 { | |
1979 fprintf (dump_file, "The type "); | |
1980 print_generic_expr (dump_file, type, 0); | |
1981 fprintf (dump_file, " is initialized...Excluded."); | |
1982 } | |
1983 add_unsuitable_type (unsuitable_types, type); | |
1984 } | |
1985 *type_p = type; | |
1986 return true; | |
1987 } | |
1988 } | |
1989 else | |
1990 return false; | |
1991 } | |
1992 | |
1993 /* Hash value for field_access_site. */ | |
1994 | |
1995 static hashval_t | |
1996 field_acc_hash (const void *x) | |
1997 { | |
1998 return htab_hash_pointer (((const struct field_access_site *)x)->stmt); | |
1999 } | |
2000 | |
2001 /* This function returns nonzero if stmt of field_access_site X | |
2002 is equal to Y. */ | |
2003 | |
2004 static int | |
2005 field_acc_eq (const void *x, const void *y) | |
2006 { | |
2007 return ((const struct field_access_site *)x)->stmt == (const_gimple)y; | |
2008 } | |
2009 | |
2010 /* This function prints an access site, defined by SLOT. */ | |
2011 | |
2012 static int | |
2013 dump_acc (void **slot, void *data ATTRIBUTE_UNUSED) | |
2014 { | |
2015 struct access_site *acc = *(struct access_site **) slot; | |
2016 tree var; | |
2017 unsigned i; | |
2018 | |
2019 fprintf(dump_file, "\n"); | |
2020 if (acc->stmt) | |
2021 print_gimple_stmt (dump_file, acc->stmt, 0, 0); | |
2022 fprintf(dump_file, " : "); | |
2023 | |
2024 for (i = 0; VEC_iterate (tree, acc->vars, i, var); i++) | |
2025 { | |
2026 print_generic_expr (dump_file, var, 0); | |
2027 fprintf(dump_file, ", "); | |
2028 } | |
2029 return 1; | |
2030 } | |
2031 | |
2032 /* This function frees memory allocated for structure clusters, | |
2033 starting from CLUSTER. */ | |
2034 | |
2035 static void | |
2036 free_struct_cluster (struct field_cluster* cluster) | |
2037 { | |
2038 if (cluster) | |
2039 { | |
2040 if (cluster->fields_in_cluster) | |
2041 sbitmap_free (cluster->fields_in_cluster); | |
2042 if (cluster->sibling) | |
2043 free_struct_cluster (cluster->sibling); | |
2044 free (cluster); | |
2045 } | |
2046 } | |
2047 | |
2048 /* Free all allocated memory under the structure node pointed by D_NODE. */ | |
2049 | |
2050 static void | |
2051 free_data_struct (d_str d_node) | |
2052 { | |
2053 int i; | |
2054 | |
2055 if (!d_node) | |
2056 return; | |
2057 | |
2058 if (dump_file) | |
2059 { | |
2060 fprintf (dump_file, "\nRemoving data structure \""); | |
2061 print_generic_expr (dump_file, d_node->decl, 0); | |
2062 fprintf (dump_file, "\" from data_struct_list."); | |
2063 } | |
2064 | |
2065 /* Free all space under d_node. */ | |
2066 if (d_node->fields) | |
2067 { | |
2068 for (i = 0; i < d_node->num_fields; i++) | |
2069 free_field_accesses (d_node->fields[i].acc_sites); | |
2070 free (d_node->fields); | |
2071 } | |
2072 | |
2073 if (d_node->accs) | |
2074 free_accesses (d_node->accs); | |
2075 | |
2076 if (d_node->struct_clustering) | |
2077 free_struct_cluster (d_node->struct_clustering); | |
2078 | |
2079 if (d_node->new_types) | |
2080 VEC_free (tree, heap, d_node->new_types); | |
2081 } | |
2082 | |
2083 /* This function creates new general and field accesses in BB. */ | |
2084 | |
2085 static void | |
2086 create_new_accesses_in_bb (basic_block bb) | |
2087 { | |
2088 d_str str; | |
2089 unsigned i; | |
2090 | |
2091 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
2092 create_new_accs_for_struct (str, bb); | |
2093 } | |
2094 | |
2095 /* This function adds allocation sites for peeled structures. | |
2096 M_DATA is vector of allocation sites of function CONTEXT. */ | |
2097 | |
2098 static void | |
2099 create_new_alloc_sites (fallocs_t m_data, tree context) | |
2100 { | |
2101 alloc_site_t *call; | |
2102 unsigned j; | |
2103 | |
2104 for (j = 0; VEC_iterate (alloc_site_t, m_data->allocs, j, call); j++) | |
2105 { | |
2106 gimple stmt = call->stmt; | |
2107 d_str str = call->str; | |
2108 tree num; | |
2109 gimple_seq new_stmts = NULL; | |
2110 gimple last_stmt = get_final_alloc_stmt (stmt); | |
2111 unsigned i; | |
2112 tree type; | |
2113 | |
2114 num = gen_num_of_structs_in_malloc (stmt, str->decl, &new_stmts); | |
2115 if (new_stmts) | |
2116 { | |
2117 gimple last_stmt_tmp = gimple_seq_last_stmt (new_stmts); | |
2118 insert_seq_after_stmt (last_stmt, new_stmts); | |
2119 last_stmt = last_stmt_tmp; | |
2120 } | |
2121 | |
2122 /* Generate an allocation sites for each new structure type. */ | |
2123 for (i = 0; VEC_iterate (tree, str->new_types, i, type); i++) | |
2124 { | |
2125 gimple new_malloc_stmt = NULL; | |
2126 gimple last_stmt_tmp = NULL; | |
2127 | |
2128 new_stmts = NULL; | |
2129 new_malloc_stmt = create_new_malloc (stmt, type, &new_stmts, num); | |
2130 last_stmt_tmp = gimple_seq_last_stmt (new_stmts); | |
2131 insert_seq_after_stmt (last_stmt, new_stmts); | |
2132 update_cgraph_with_malloc_call (new_malloc_stmt, context); | |
2133 last_stmt = last_stmt_tmp; | |
2134 } | |
2135 } | |
2136 } | |
2137 | |
2138 /* This function prints new variables from hashtable | |
2139 NEW_VARS_HTAB to dump_file. */ | |
2140 | |
2141 static void | |
2142 dump_new_vars (htab_t new_vars_htab) | |
2143 { | |
2144 if (!dump_file) | |
2145 return; | |
2146 | |
2147 if (new_vars_htab) | |
2148 htab_traverse (new_vars_htab, dump_new_var, NULL); | |
2149 } | |
2150 | |
2151 /* Given an original variable ORIG_DECL of structure type STR, | |
2152 this function generates new variables of the types defined | |
2153 by STR->new_type. Generated types are saved in new_var node NODE. | |
2154 ORIG_DECL should has VAR_DECL tree_code. */ | |
2155 | |
2156 static void | |
2157 create_new_var_1 (tree orig_decl, d_str str, new_var node) | |
2158 { | |
2159 unsigned i; | |
2160 tree type; | |
2161 | |
2162 for (i = 0; | |
2163 VEC_iterate (tree, str->new_types, i, type); i++) | |
2164 { | |
2165 tree new_decl = NULL; | |
2166 tree new_name; | |
2167 | |
2168 new_name = gen_var_name (orig_decl, i); | |
2169 type = gen_struct_type (orig_decl, type); | |
2170 | |
2171 if (is_global_var (orig_decl)) | |
2172 new_decl = build_decl (VAR_DECL, new_name, type); | |
2173 else | |
2174 { | |
2175 const char *name = new_name ? IDENTIFIER_POINTER (new_name) : NULL; | |
2176 new_decl = create_tmp_var (type, name); | |
2177 } | |
2178 | |
2179 copy_decl_attributes (new_decl, orig_decl); | |
2180 VEC_safe_push (tree, heap, node->new_vars, new_decl); | |
2181 } | |
2182 } | |
2183 | |
2184 /* This function creates new variables to | |
2185 substitute the original variable VAR_DECL and adds | |
2186 them to the new_var's hashtable NEW_VARS_HTAB. */ | |
2187 | |
2188 static void | |
2189 create_new_var (tree var_decl, htab_t new_vars_htab) | |
2190 { | |
2191 new_var node; | |
2192 d_str str; | |
2193 tree type; | |
2194 unsigned i; | |
2195 | |
2196 if (!var_decl || is_in_new_vars_htab (var_decl, new_vars_htab)) | |
2197 return; | |
2198 | |
2199 if (!is_candidate (var_decl, &type, NULL)) | |
2200 return; | |
2201 | |
2202 i = find_structure (type); | |
2203 if (i == VEC_length (structure, structures)) | |
2204 return; | |
2205 | |
2206 str = VEC_index (structure, structures, i); | |
2207 node = create_new_var_node (var_decl, str); | |
2208 create_new_var_1 (var_decl, str, node); | |
2209 add_to_new_vars_htab (node, new_vars_htab); | |
2210 } | |
2211 | |
2212 /* Hash value for new_var. */ | |
2213 | |
2214 static hashval_t | |
2215 new_var_hash (const void *x) | |
2216 { | |
2217 return htab_hash_pointer (((const_new_var)x)->orig_var); | |
2218 } | |
2219 | |
2220 /* This function returns nonzero if orig_var of new_var X is equal to Y. */ | |
2221 | |
2222 static int | |
2223 new_var_eq (const void *x, const void *y) | |
2224 { | |
2225 return ((const_new_var)x)->orig_var == (const_tree)y; | |
2226 } | |
2227 | |
2228 /* This function check whether a structure type represented by STR | |
2229 escapes due to ipa-type-escape analysis. If yes, this type is added | |
2230 to UNSUITABLE_TYPES vector. */ | |
2231 | |
2232 static void | |
2233 check_type_escape (d_str str, VEC (tree, heap) **unsuitable_types) | |
2234 { | |
2235 tree type = str->decl; | |
2236 | |
2237 if (!ipa_type_escape_type_contained_p (type)) | |
2238 { | |
2239 if (dump_file) | |
2240 { | |
2241 fprintf (dump_file, "\nEscaping type is "); | |
2242 print_generic_expr (dump_file, type, 0); | |
2243 } | |
2244 add_unsuitable_type (unsuitable_types, type); | |
2245 } | |
2246 } | |
2247 | |
2248 /* Hash value for access_site. */ | |
2249 | |
2250 static hashval_t | |
2251 acc_hash (const void *x) | |
2252 { | |
2253 return htab_hash_pointer (((const struct access_site *)x)->stmt); | |
2254 } | |
2255 | |
2256 /* Return nonzero if stmt of access_site X is equal to Y. */ | |
2257 | |
2258 static int | |
2259 acc_eq (const void *x, const void *y) | |
2260 { | |
2261 return ((const struct access_site *)x)->stmt == (const_gimple)y; | |
2262 } | |
2263 | |
2264 /* Given a structure declaration STRUCT_DECL, and number of fields | |
2265 in the structure NUM_FIELDS, this function creates and returns | |
2266 corresponding field_entry's. */ | |
2267 | |
2268 static struct field_entry * | |
2269 get_fields (tree struct_decl, int num_fields) | |
2270 { | |
2271 struct field_entry *list; | |
2272 tree t = TYPE_FIELDS (struct_decl); | |
2273 int idx = 0; | |
2274 | |
2275 list = | |
2276 (struct field_entry *) xmalloc (num_fields * sizeof (struct field_entry)); | |
2277 | |
2278 for (idx = 0 ; t; t = TREE_CHAIN (t), idx++) | |
2279 if (TREE_CODE (t) == FIELD_DECL) | |
2280 { | |
2281 list[idx].index = idx; | |
2282 list[idx].decl = t; | |
2283 list[idx].acc_sites = | |
2284 htab_create (32, field_acc_hash, field_acc_eq, NULL); | |
2285 list[idx].count = 0; | |
2286 list[idx].field_mapping = NULL_TREE; | |
2287 } | |
2288 | |
2289 return list; | |
2290 } | |
2291 | |
2292 /* Print non-field accesses from hashtable ACCS of structure. */ | |
2293 | |
2294 static void | |
2295 dump_access_sites (htab_t accs) | |
2296 { | |
2297 if (!dump_file) | |
2298 return; | |
2299 | |
2300 if (accs) | |
2301 htab_traverse (accs, dump_acc, NULL); | |
2302 } | |
2303 | |
2304 /* This function is a callback for alloc_sites hashtable | |
2305 traversal. SLOT is a pointer to fallocs_t. This function | |
2306 removes all allocations of the structure defined by DATA. */ | |
2307 | |
2308 static int | |
2309 remove_str_allocs_in_func (void **slot, void *data) | |
2310 { | |
2311 fallocs_t fallocs = *(fallocs_t *) slot; | |
2312 unsigned i = 0; | |
2313 alloc_site_t *call; | |
2314 | |
2315 while (VEC_iterate (alloc_site_t, fallocs->allocs, i, call)) | |
2316 { | |
2317 if (call->str == (d_str) data) | |
2318 VEC_ordered_remove (alloc_site_t, fallocs->allocs, i); | |
2319 else | |
2320 i++; | |
2321 } | |
2322 | |
2323 return 1; | |
2324 } | |
2325 | |
2326 /* This function remove all entries corresponding to the STR structure | |
2327 from alloc_sites hashtable. */ | |
2328 | |
2329 static void | |
2330 remove_str_allocs (d_str str) | |
2331 { | |
2332 if (!str) | |
2333 return; | |
2334 | |
2335 if (alloc_sites) | |
2336 htab_traverse (alloc_sites, remove_str_allocs_in_func, str); | |
2337 } | |
2338 | |
2339 /* This function removes the structure with index I from structures vector. */ | |
2340 | |
2341 static void | |
2342 remove_structure (unsigned i) | |
2343 { | |
2344 d_str str; | |
2345 | |
2346 if (i >= VEC_length (structure, structures)) | |
2347 return; | |
2348 | |
2349 str = VEC_index (structure, structures, i); | |
2350 | |
2351 /* Before removing the structure str, we have to remove its | |
2352 allocations from alloc_sites hashtable. */ | |
2353 remove_str_allocs (str); | |
2354 free_data_struct (str); | |
2355 VEC_ordered_remove (structure, structures, i); | |
2356 } | |
2357 | |
2358 /* Currently we support only EQ_EXPR or NE_EXPR conditions. | |
2359 COND_STMT is a condition statement to check. */ | |
2360 | |
2361 static bool | |
2362 is_safe_cond_expr (gimple cond_stmt) | |
2363 { | |
2364 tree arg0, arg1; | |
2365 unsigned str0, str1; | |
2366 bool s0, s1; | |
2367 unsigned length = VEC_length (structure, structures); | |
2368 | |
2369 if (gimple_cond_code (cond_stmt) != EQ_EXPR | |
2370 && gimple_cond_code (cond_stmt) != NE_EXPR) | |
2371 return false; | |
2372 | |
2373 arg0 = gimple_cond_lhs (cond_stmt); | |
2374 arg1 = gimple_cond_rhs (cond_stmt); | |
2375 | |
2376 str0 = find_structure (strip_type (get_type_of_var (arg0))); | |
2377 str1 = find_structure (strip_type (get_type_of_var (arg1))); | |
2378 | |
2379 s0 = (str0 != length) ? true : false; | |
2380 s1 = (str1 != length) ? true : false; | |
2381 | |
2382 if (!s0 && !s1) | |
2383 return false; | |
2384 | |
2385 /* For now we allow only comparison with 0 or NULL. */ | |
2386 if (!integer_zerop (arg0) && !integer_zerop (arg1)) | |
2387 return false; | |
2388 | |
2389 return true; | |
2390 } | |
2391 | |
2392 /* This function excludes statements, that are | |
2393 part of allocation sites or field accesses, from the | |
2394 hashtable of general accesses. SLOT represents general | |
2395 access that will be checked. DATA is a pointer to | |
2396 exclude_data structure. */ | |
2397 | |
2398 static int | |
2399 exclude_from_accs (void **slot, void *data) | |
2400 { | |
2401 struct access_site *acc = *(struct access_site **) slot; | |
2402 tree fn_decl = ((struct exclude_data *)data)->fn_decl; | |
2403 d_str str = ((struct exclude_data *)data)->str; | |
2404 | |
2405 if (is_part_of_malloc (acc->stmt, fn_decl) | |
2406 || is_part_of_field_access (acc->stmt, str)) | |
2407 { | |
2408 VEC_free (tree, heap, acc->vars); | |
2409 free (acc); | |
2410 htab_clear_slot (str->accs, slot); | |
2411 } | |
2412 return 1; | |
2413 } | |
2414 | |
2415 /* Callback function for walk_tree called from collect_accesses_in_bb | |
2416 function. DATA is the statement which is analyzed. */ | |
2417 | |
2418 static tree | |
2419 get_stmt_accesses (tree *tp, int *walk_subtrees, void *data) | |
2420 { | |
2421 struct walk_stmt_info *wi = (struct walk_stmt_info *) data; | |
2422 gimple stmt = (gimple) wi->info; | |
2423 tree t = *tp; | |
2424 | |
2425 if (!t) | |
2426 return NULL; | |
2427 | |
2428 switch (TREE_CODE (t)) | |
2429 { | |
2430 case BIT_FIELD_REF: | |
2431 { | |
2432 tree var = TREE_OPERAND(t, 0); | |
2433 tree type = TYPE_MAIN_VARIANT (strip_type (get_type_of_var (var))); | |
2434 unsigned i = find_structure (type); | |
2435 | |
2436 if (i != VEC_length (structure, structures)) | |
2437 { | |
2438 if (dump_file) | |
2439 { | |
2440 fprintf (dump_file, "\nThe type "); | |
2441 print_generic_expr (dump_file, type, 0); | |
2442 fprintf (dump_file, " has bitfield."); | |
2443 } | |
2444 remove_structure (i); | |
2445 } | |
2446 } | |
2447 break; | |
2448 | |
2449 case COMPONENT_REF: | |
2450 { | |
2451 tree ref = TREE_OPERAND (t, 0); | |
2452 tree field_decl = TREE_OPERAND (t, 1); | |
2453 | |
2454 | |
2455 if ((TREE_CODE (ref) == INDIRECT_REF | |
2456 || TREE_CODE (ref) == ARRAY_REF | |
2457 || TREE_CODE (ref) == VAR_DECL) | |
2458 && TREE_CODE (field_decl) == FIELD_DECL) | |
2459 { | |
2460 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref)); | |
2461 unsigned i = find_structure (type); | |
2462 | |
2463 if (i != VEC_length (structure, structures)) | |
2464 { | |
2465 d_str str = VEC_index (structure, structures, i); | |
2466 struct field_entry * field = | |
2467 find_field_in_struct (str, field_decl); | |
2468 | |
2469 if (field) | |
2470 { | |
2471 struct field_access_site *acc = make_field_acc_node (); | |
2472 | |
2473 gcc_assert (acc); | |
2474 | |
2475 acc->stmt = stmt; | |
2476 acc->comp_ref = t; | |
2477 acc->ref = ref; | |
2478 acc->field_decl = field_decl; | |
2479 | |
2480 /* Check whether the access is of the form | |
2481 we can deal with. */ | |
2482 if (!decompose_access (str->decl, acc)) | |
2483 { | |
2484 if (dump_file) | |
2485 { | |
2486 fprintf (dump_file, "\nThe type "); | |
2487 print_generic_expr (dump_file, type, 0); | |
2488 fprintf (dump_file, | |
2489 " has complicate access in statement "); | |
2490 print_gimple_stmt (dump_file, stmt, 0, 0); | |
2491 } | |
2492 | |
2493 remove_structure (i); | |
2494 free (acc); | |
2495 } | |
2496 else | |
2497 { | |
2498 /* Increase count of field. */ | |
2499 basic_block bb = gimple_bb (stmt); | |
2500 field->count += bb->count; | |
2501 | |
2502 /* Add stmt to the acc_sites of field. */ | |
2503 add_field_acc_to_acc_sites (acc, field->acc_sites); | |
2504 } | |
2505 *walk_subtrees = 0; | |
2506 } | |
2507 } | |
2508 } | |
2509 } | |
2510 break; | |
2511 | |
2512 case COND_EXPR: | |
2513 { | |
2514 tree cond = COND_EXPR_COND (t); | |
2515 int i; | |
2516 for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (cond)); i++) | |
2517 { | |
2518 tree t = TREE_OPERAND (cond, i); | |
2519 | |
2520 *walk_subtrees = 1; | |
2521 walk_tree (&t, get_stmt_accesses, data, NULL); | |
2522 } | |
2523 *walk_subtrees = 0; | |
2524 } | |
2525 break; | |
2526 | |
2527 case VAR_DECL: | |
2528 case SSA_NAME: | |
2529 { | |
2530 unsigned i; | |
2531 | |
2532 if (TREE_CODE (t) == SSA_NAME) | |
2533 t = SSA_NAME_VAR (t); | |
2534 | |
2535 i = find_structure (strip_type (get_type_of_var (t))); | |
2536 if (i != VEC_length (structure, structures)) | |
2537 { | |
2538 d_str str; | |
2539 | |
2540 str = VEC_index (structure, structures, i); | |
2541 add_access_to_acc_sites (stmt, t, str->accs); | |
2542 } | |
2543 *walk_subtrees = 0; | |
2544 } | |
2545 break; | |
2546 | |
2547 default: | |
2548 return NULL; | |
2549 } | |
2550 | |
2551 return NULL; | |
2552 } | |
2553 | |
2554 /* Free structures hashtable. */ | |
2555 | |
2556 static void | |
2557 free_structures (void) | |
2558 { | |
2559 d_str str; | |
2560 unsigned i; | |
2561 | |
2562 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
2563 free_data_struct (str); | |
2564 | |
2565 VEC_free (structure, heap, structures); | |
2566 structures = NULL; | |
2567 } | |
2568 | |
2569 /* This function is a callback for traversal over new_var's hashtable. | |
2570 SLOT is a pointer to new_var. This function frees memory allocated | |
2571 for new_var and pointed by *SLOT. */ | |
2572 | |
2573 static int | |
2574 free_new_var (void **slot, void *data ATTRIBUTE_UNUSED) | |
2575 { | |
2576 new_var n_var = *(new_var *) slot; | |
2577 | |
2578 /* Free vector of new_vars. */ | |
2579 VEC_free (tree, heap, n_var->new_vars); | |
2580 free (n_var); | |
2581 return 1; | |
2582 } | |
2583 | |
2584 /* Free new_vars hashtable NEW_VARS_HTAB. */ | |
2585 | |
2586 static void | |
2587 free_new_vars_htab (htab_t new_vars_htab) | |
2588 { | |
2589 if (new_vars_htab) | |
2590 htab_traverse (new_vars_htab, free_new_var, NULL); | |
2591 htab_delete (new_vars_htab); | |
2592 new_vars_htab = NULL; | |
2593 } | |
2594 | |
2595 /* This function creates new general and field accesses that appear in cfun. */ | |
2596 | |
2597 static void | |
2598 create_new_accesses_for_func (void) | |
2599 { | |
2600 basic_block bb; | |
2601 | |
2602 FOR_EACH_BB_FN (bb, cfun) | |
2603 create_new_accesses_in_bb (bb); | |
2604 } | |
2605 | |
2606 /* Create new allocation sites for the function represented by NODE. */ | |
2607 | |
2608 static void | |
2609 create_new_alloc_sites_for_func (struct cgraph_node *node) | |
2610 { | |
2611 fallocs_t fallocs = get_fallocs (node->decl); | |
2612 | |
2613 if (fallocs) | |
2614 create_new_alloc_sites (fallocs, node->decl); | |
2615 } | |
2616 | |
2617 /* For each local variable of structure type from the vector of structures | |
2618 this function generates new variable(s) to replace it. */ | |
2619 | |
2620 static void | |
2621 create_new_local_vars (void) | |
2622 { | |
2623 tree var; | |
2624 referenced_var_iterator rvi; | |
2625 | |
2626 new_local_vars = htab_create (num_referenced_vars, | |
2627 new_var_hash, new_var_eq, NULL); | |
2628 | |
2629 FOR_EACH_REFERENCED_VAR (var, rvi) | |
2630 { | |
2631 if (!is_global_var (var)) | |
2632 create_new_var (var, new_local_vars); | |
2633 } | |
2634 | |
2635 if (new_local_vars) | |
2636 htab_traverse (new_local_vars, finalize_new_vars_creation, NULL); | |
2637 dump_new_vars (new_local_vars); | |
2638 } | |
2639 | |
2640 /* This function prints the SHIFT number of spaces to the DUMP_FILE. */ | |
2641 | |
2642 static inline void | |
2643 print_shift (unsigned HOST_WIDE_INT shift) | |
2644 { | |
2645 unsigned HOST_WIDE_INT sh = shift; | |
2646 | |
2647 while (sh--) | |
2648 fprintf (dump_file, " "); | |
2649 } | |
2650 | |
2651 /* This function updates field_mapping of FIELDS in CLUSTER with NEW_TYPE. */ | |
2652 | |
2653 static inline void | |
2654 update_fields_mapping (struct field_cluster *cluster, tree new_type, | |
2655 struct field_entry * fields, int num_fields) | |
2656 { | |
2657 int i; | |
2658 | |
2659 for (i = 0; i < num_fields; i++) | |
2660 if (TEST_BIT (cluster->fields_in_cluster, i)) | |
2661 fields[i].field_mapping = new_type; | |
2662 } | |
2663 | |
2664 /* This functions builds structure with FIELDS, | |
2665 NAME and attributes similar to ORIG_STRUCT. | |
2666 It returns the newly created structure. */ | |
2667 | |
2668 static tree | |
2669 build_basic_struct (tree fields, tree name, tree orig_struct) | |
2670 { | |
2671 tree attributes = NULL_TREE; | |
2672 tree ref = 0; | |
2673 tree x; | |
2674 | |
2675 if (TYPE_ATTRIBUTES (orig_struct)) | |
2676 attributes = unshare_expr (TYPE_ATTRIBUTES (orig_struct)); | |
2677 ref = make_node (RECORD_TYPE); | |
2678 TYPE_SIZE (ref) = 0; | |
2679 decl_attributes (&ref, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); | |
2680 TYPE_PACKED (ref) = TYPE_PACKED (orig_struct); | |
2681 for (x = fields; x; x = TREE_CHAIN (x)) | |
2682 { | |
2683 DECL_CONTEXT (x) = ref; | |
2684 DECL_PACKED (x) |= TYPE_PACKED (ref); | |
2685 } | |
2686 TYPE_FIELDS (ref) = fields; | |
2687 layout_type (ref); | |
2688 TYPE_NAME (ref) = name; | |
2689 | |
2690 return ref; | |
2691 } | |
2692 | |
2693 /* This function copies FIELDS from CLUSTER into TREE_CHAIN as part | |
2694 of preparation for new structure building. NUM_FIELDS is a total | |
2695 number of fields in the structure. The function returns newly | |
2696 generated fields. */ | |
2697 | |
2698 static tree | |
2699 create_fields (struct field_cluster * cluster, | |
2700 struct field_entry * fields, int num_fields) | |
2701 { | |
2702 int i; | |
2703 tree new_types = NULL_TREE; | |
2704 tree last = NULL_TREE; | |
2705 | |
2706 for (i = 0; i < num_fields; i++) | |
2707 if (TEST_BIT (cluster->fields_in_cluster, i)) | |
2708 { | |
2709 tree new_decl = unshare_expr (fields[i].decl); | |
2710 | |
2711 if (!new_types) | |
2712 new_types = new_decl; | |
2713 else | |
2714 TREE_CHAIN (last) = new_decl; | |
2715 last = new_decl; | |
2716 } | |
2717 | |
2718 TREE_CHAIN (last) = NULL_TREE; | |
2719 return new_types; | |
2720 | |
2721 } | |
2722 | |
2723 /* This function creates a cluster name. The name is based on | |
2724 the original structure name, if it is present. It has a form: | |
2725 | |
2726 <original_struct_name>_sub.<CLUST_NUM> | |
2727 | |
2728 The original structure name is taken from the type of DECL. | |
2729 If an original structure name is not present, it's generated to be: | |
2730 | |
2731 struct.<STR_NUM> | |
2732 | |
2733 The function returns identifier of the new cluster name. */ | |
2734 | |
2735 static inline tree | |
2736 gen_cluster_name (tree decl, int clust_num, int str_num) | |
2737 { | |
2738 const char * orig_name = get_type_name (decl); | |
2739 char * tmp_name = NULL; | |
2740 char * prefix; | |
2741 char * new_name; | |
2742 size_t len; | |
2743 | |
2744 if (!orig_name) | |
2745 ASM_FORMAT_PRIVATE_NAME(tmp_name, "struct", str_num); | |
2746 | |
2747 len = strlen (tmp_name ? tmp_name : orig_name) + strlen ("_sub"); | |
2748 prefix = XALLOCAVEC (char, len + 1); | |
2749 memcpy (prefix, tmp_name ? tmp_name : orig_name, | |
2750 strlen (tmp_name ? tmp_name : orig_name)); | |
2751 strcpy (prefix + strlen (tmp_name ? tmp_name : orig_name), "_sub"); | |
2752 | |
2753 ASM_FORMAT_PRIVATE_NAME (new_name, prefix, clust_num); | |
2754 return get_identifier (new_name); | |
2755 } | |
2756 | |
2757 /* This function checks whether the structure STR has bitfields. | |
2758 If yes, this structure type is added to UNSUITABLE_TYPES vector. */ | |
2759 | |
2760 static void | |
2761 check_bitfields (d_str str, VEC (tree, heap) **unsuitable_types) | |
2762 { | |
2763 tree type = str->decl; | |
2764 int i; | |
2765 | |
2766 for (i = 0; i < str->num_fields; i++) | |
2767 if (DECL_BIT_FIELD (str->fields[i].decl)) | |
2768 { | |
2769 add_unsuitable_type (unsuitable_types, type); | |
2770 if (dump_file) | |
2771 { | |
2772 fprintf (dump_file, "\nType "); | |
2773 print_generic_expr (dump_file, type, 0); | |
2774 fprintf (dump_file, "\nescapes due to bitfield "); | |
2775 print_generic_expr (dump_file, str->fields[i].decl, 0); | |
2776 } | |
2777 break; | |
2778 } | |
2779 } | |
2780 | |
2781 /* This function adds to UNSUITABLE_TYPES those types that escape | |
2782 due to results of ipa-type-escape analysis. See ipa-type-escape.[c,h]. */ | |
2783 | |
2784 static void | |
2785 exclude_escaping_types_1 (VEC (tree, heap) **unsuitable_types) | |
2786 { | |
2787 d_str str; | |
2788 unsigned i; | |
2789 | |
2790 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
2791 check_type_escape (str, unsuitable_types); | |
2792 } | |
2793 | |
2794 /* If a structure type is a return type of any function, | |
2795 we cannot transform it. Such type is added to UNSUITABLE_TYPES vector. */ | |
2796 | |
2797 static void | |
2798 exclude_returned_types (VEC (tree, heap) **unsuitable_types) | |
2799 { | |
2800 struct cgraph_node *c_node; | |
2801 | |
2802 for (c_node = cgraph_nodes; c_node; c_node = c_node->next) | |
2803 { | |
2804 tree ret_t = TREE_TYPE (TREE_TYPE (c_node->decl)); | |
2805 | |
2806 if (ret_t) | |
2807 { | |
2808 ret_t = strip_type (ret_t); | |
2809 if (TREE_CODE (ret_t) == RECORD_TYPE) | |
2810 { | |
2811 add_unsuitable_type (unsuitable_types, TYPE_MAIN_VARIANT (ret_t)); | |
2812 if (dump_file) | |
2813 { | |
2814 fprintf (dump_file, "\nThe type \""); | |
2815 print_generic_expr (dump_file, ret_t, 0); | |
2816 fprintf (dump_file, | |
2817 "\" is return type of function...Excluded."); | |
2818 } | |
2819 } | |
2820 } | |
2821 } | |
2822 } | |
2823 | |
2824 /* This function looks for parameters of local functions | |
2825 which are of structure types, or derived from them (arrays | |
2826 of structures, pointers to structures, or their combinations). | |
2827 We are not handling peeling of such structures right now. | |
2828 The found structures types are added to UNSUITABLE_TYPES vector. */ | |
2829 | |
2830 static void | |
2831 exclude_types_passed_to_local_func (VEC (tree, heap) **unsuitable_types) | |
2832 { | |
2833 struct cgraph_node *c_node; | |
2834 | |
2835 for (c_node = cgraph_nodes; c_node; c_node = c_node->next) | |
2836 if (cgraph_function_body_availability (c_node) == AVAIL_LOCAL) | |
2837 { | |
2838 tree fn = c_node->decl; | |
2839 tree arg; | |
2840 | |
2841 for (arg = DECL_ARGUMENTS (fn); arg; arg = TREE_CHAIN (arg)) | |
2842 { | |
2843 tree type = TREE_TYPE (arg); | |
2844 | |
2845 type = strip_type (type); | |
2846 if (TREE_CODE (type) == RECORD_TYPE) | |
2847 { | |
2848 add_unsuitable_type (unsuitable_types, | |
2849 TYPE_MAIN_VARIANT (type)); | |
2850 if (dump_file) | |
2851 { | |
2852 fprintf (dump_file, "\nPointer to type \""); | |
2853 print_generic_expr (dump_file, type, 0); | |
2854 fprintf (dump_file, | |
2855 "\" is passed to local function...Excluded."); | |
2856 } | |
2857 } | |
2858 } | |
2859 } | |
2860 } | |
2861 | |
2862 /* This function analyzes structure form of structures | |
2863 potential for transformation. If we are not capable to transform | |
2864 structure of some form, we remove it from the structures hashtable. | |
2865 Right now we cannot handle nested structs, when nesting is | |
2866 through any level of pointers or arrays. | |
2867 | |
2868 TBD: release these constrains in future. | |
2869 | |
2870 Note, that in this function we suppose that all structures | |
2871 in the program are members of the structures hashtable right now, | |
2872 without excluding escaping types. */ | |
2873 | |
2874 static void | |
2875 check_struct_form (d_str str, VEC (tree, heap) **unsuitable_types) | |
2876 { | |
2877 int i; | |
2878 | |
2879 for (i = 0; i < str->num_fields; i++) | |
2880 { | |
2881 tree f_type = strip_type(TREE_TYPE (str->fields[i].decl)); | |
2882 | |
2883 if (TREE_CODE (f_type) == RECORD_TYPE) | |
2884 { | |
2885 add_unsuitable_type (unsuitable_types, TYPE_MAIN_VARIANT (f_type)); | |
2886 add_unsuitable_type (unsuitable_types, str->decl); | |
2887 if (dump_file) | |
2888 { | |
2889 fprintf (dump_file, "\nType "); | |
2890 print_generic_expr (dump_file, f_type, 0); | |
2891 fprintf (dump_file, " is a field in the structure "); | |
2892 print_generic_expr (dump_file, str->decl, 0); | |
2893 fprintf (dump_file, ". Escaping..."); | |
2894 } | |
2895 } | |
2896 } | |
2897 } | |
2898 | |
2899 /* This function adds a structure TYPE to the vector of structures, | |
2900 if it's not already there. */ | |
2901 | |
2902 static void | |
2903 add_structure (tree type) | |
2904 { | |
2905 struct data_structure node; | |
2906 unsigned i; | |
2907 int num_fields; | |
2908 | |
2909 type = TYPE_MAIN_VARIANT (type); | |
2910 | |
2911 i = find_structure (type); | |
2912 | |
2913 if (i != VEC_length (structure, structures)) | |
2914 return; | |
2915 | |
2916 num_fields = fields_length (type); | |
2917 node.decl = type; | |
2918 node.num_fields = num_fields; | |
2919 node.fields = get_fields (type, num_fields); | |
2920 node.struct_clustering = NULL; | |
2921 node.accs = htab_create (32, acc_hash, acc_eq, NULL); | |
2922 node.new_types = VEC_alloc (tree, heap, num_fields); | |
2923 node.count = 0; | |
2924 | |
2925 VEC_safe_push (structure, heap, structures, &node); | |
2926 | |
2927 if (dump_file) | |
2928 { | |
2929 fprintf (dump_file, "\nAdding data structure \""); | |
2930 print_generic_expr (dump_file, type, 0); | |
2931 fprintf (dump_file, "\" to data_struct_list."); | |
2932 } | |
2933 } | |
2934 | |
2935 /* This function adds an allocation site to alloc_sites hashtable. | |
2936 The allocation site appears in STMT of function FN_DECL and | |
2937 allocates the structure represented by STR. */ | |
2938 | |
2939 static void | |
2940 add_alloc_site (tree fn_decl, gimple stmt, d_str str) | |
2941 { | |
2942 fallocs_t fallocs = NULL; | |
2943 alloc_site_t m_call; | |
2944 | |
2945 m_call.stmt = stmt; | |
2946 m_call.str = str; | |
2947 | |
2948 fallocs = | |
2949 (fallocs_t) htab_find_with_hash (alloc_sites, | |
2950 fn_decl, htab_hash_pointer (fn_decl)); | |
2951 | |
2952 if (!fallocs) | |
2953 { | |
2954 void **slot; | |
2955 | |
2956 fallocs = (fallocs_t) | |
2957 xmalloc (sizeof (struct func_alloc_sites)); | |
2958 fallocs->func = fn_decl; | |
2959 fallocs->allocs = VEC_alloc (alloc_site_t, heap, 1); | |
2960 slot = htab_find_slot_with_hash (alloc_sites, fn_decl, | |
2961 htab_hash_pointer (fn_decl), INSERT); | |
2962 *slot = fallocs; | |
2963 } | |
2964 VEC_safe_push (alloc_site_t, heap, | |
2965 fallocs->allocs, &m_call); | |
2966 | |
2967 if (dump_file) | |
2968 { | |
2969 fprintf (dump_file, "\nAdding stmt "); | |
2970 print_gimple_stmt (dump_file, stmt, 0, 0); | |
2971 fprintf (dump_file, " to list of mallocs."); | |
2972 } | |
2973 } | |
2974 | |
2975 /* This function returns true if the result of STMT, that contains a call | |
2976 to an allocation function, is cast to one of the structure types. | |
2977 STMT should be of the form: T.2 = <alloc_func> (T.1); | |
2978 If true, I_P contains an index of an allocated structure. | |
2979 Otherwise I_P contains the length of the vector of structures. */ | |
2980 | |
2981 static bool | |
2982 is_alloc_of_struct (gimple stmt, unsigned *i_p) | |
2983 { | |
2984 tree lhs; | |
2985 tree type; | |
2986 gimple final_stmt; | |
2987 | |
2988 final_stmt = get_final_alloc_stmt (stmt); | |
2989 | |
2990 if (!final_stmt) | |
2991 return false; | |
2992 | |
2993 /* final_stmt should be of the form: | |
2994 T.3 = (struct_type *) T.2; */ | |
2995 | |
2996 if (gimple_code (final_stmt) != GIMPLE_ASSIGN) | |
2997 return false; | |
2998 | |
2999 lhs = gimple_assign_lhs (final_stmt); | |
3000 | |
3001 type = get_type_of_var (lhs); | |
3002 | |
3003 if (!type) | |
3004 return false; | |
3005 | |
3006 if (!POINTER_TYPE_P (type) | |
3007 || TREE_CODE (strip_type (type)) != RECORD_TYPE) | |
3008 return false; | |
3009 | |
3010 *i_p = find_structure (strip_type (type)); | |
3011 | |
3012 if (*i_p == VEC_length (structure, structures)) | |
3013 return false; | |
3014 | |
3015 return true; | |
3016 } | |
3017 | |
3018 /* This function prints non-field and field accesses | |
3019 of the structure STR. */ | |
3020 | |
3021 static void | |
3022 dump_accs (d_str str) | |
3023 { | |
3024 int i; | |
3025 | |
3026 fprintf (dump_file, "\nAccess sites of struct "); | |
3027 print_generic_expr (dump_file, str->decl, 0); | |
3028 | |
3029 for (i = 0; i < str->num_fields; i++) | |
3030 { | |
3031 fprintf (dump_file, "\nAccess site of field "); | |
3032 print_generic_expr (dump_file, str->fields[i].decl, 0); | |
3033 dump_field_acc_sites (str->fields[i].acc_sites); | |
3034 fprintf (dump_file, ":\n"); | |
3035 } | |
3036 fprintf (dump_file, "\nGeneral access sites\n"); | |
3037 dump_access_sites (str->accs); | |
3038 } | |
3039 | |
3040 /* This function checks whether an access statement, pointed by SLOT, | |
3041 is a condition we are capable to transform. It returns false if not, | |
3042 setting bool *DATA to false. */ | |
3043 | |
3044 static int | |
3045 safe_cond_expr_check (void **slot, void *data) | |
3046 { | |
3047 struct access_site *acc = *(struct access_site **) slot; | |
3048 | |
3049 if (gimple_code (acc->stmt) == GIMPLE_COND | |
3050 && !is_safe_cond_expr (acc->stmt)) | |
3051 { | |
3052 if (dump_file) | |
3053 { | |
3054 fprintf (dump_file, "\nUnsafe conditional statement "); | |
3055 print_gimple_stmt (dump_file, acc->stmt, 0, 0); | |
3056 } | |
3057 *(bool *) data = false; | |
3058 return 0; | |
3059 } | |
3060 return 1; | |
3061 } | |
3062 | |
3063 /* This function excludes statements that are part of allocation sites and | |
3064 field accesses from the hashtable of general accesses of the structure | |
3065 type STR. Only accesses that belong to the function represented by | |
3066 NODE are treated. */ | |
3067 | |
3068 static void | |
3069 exclude_alloc_and_field_accs_1 (d_str str, struct cgraph_node *node) | |
3070 { | |
3071 struct exclude_data dt; | |
3072 dt.str = str; | |
3073 dt.fn_decl = node->decl; | |
3074 | |
3075 if (dt.str->accs) | |
3076 htab_traverse (dt.str->accs, exclude_from_accs, &dt); | |
3077 } | |
3078 | |
3079 /* Collect accesses to the structure types that appear in basic block BB. */ | |
3080 | |
3081 static void | |
3082 collect_accesses_in_bb (basic_block bb) | |
3083 { | |
3084 gimple_stmt_iterator bsi; | |
3085 struct walk_stmt_info wi; | |
3086 | |
3087 memset (&wi, 0, sizeof (wi)); | |
3088 | |
3089 for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) | |
3090 { | |
3091 gimple stmt = gsi_stmt (bsi); | |
3092 | |
3093 /* In asm stmt we cannot always track the arguments, | |
3094 so we just give up. */ | |
3095 if (gimple_code (stmt) == GIMPLE_ASM) | |
3096 { | |
3097 free_structures (); | |
3098 break; | |
3099 } | |
3100 | |
3101 wi.info = (void *) stmt; | |
3102 walk_gimple_op (stmt, get_stmt_accesses, &wi); | |
3103 } | |
3104 } | |
3105 | |
3106 /* This function generates cluster substructure that contains FIELDS. | |
3107 The cluster added to the set of clusters of the structure STR. */ | |
3108 | |
3109 static void | |
3110 gen_cluster (sbitmap fields, d_str str) | |
3111 { | |
3112 struct field_cluster *crr_cluster = NULL; | |
3113 | |
3114 crr_cluster = | |
3115 (struct field_cluster *) xcalloc (1, sizeof (struct field_cluster)); | |
3116 crr_cluster->sibling = str->struct_clustering; | |
3117 str->struct_clustering = crr_cluster; | |
3118 crr_cluster->fields_in_cluster = fields; | |
3119 } | |
3120 | |
3121 /* This function peels a field with the index I from the structure DS. */ | |
3122 | |
3123 static void | |
3124 peel_field (int i, d_str ds) | |
3125 { | |
3126 struct field_cluster *crr_cluster = NULL; | |
3127 | |
3128 crr_cluster = | |
3129 (struct field_cluster *) xcalloc (1, sizeof (struct field_cluster)); | |
3130 crr_cluster->sibling = ds->struct_clustering; | |
3131 ds->struct_clustering = crr_cluster; | |
3132 crr_cluster->fields_in_cluster = | |
3133 sbitmap_alloc ((unsigned int) ds->num_fields); | |
3134 sbitmap_zero (crr_cluster->fields_in_cluster); | |
3135 SET_BIT (crr_cluster->fields_in_cluster, i); | |
3136 } | |
3137 | |
3138 /* This function calculates maximum field count in | |
3139 the structure STR. */ | |
3140 | |
3141 static gcov_type | |
3142 get_max_field_count (d_str str) | |
3143 { | |
3144 gcov_type max = 0; | |
3145 int i; | |
3146 | |
3147 for (i = 0; i < str->num_fields; i++) | |
3148 if (str->fields[i].count > max) | |
3149 max = str->fields[i].count; | |
3150 | |
3151 return max; | |
3152 } | |
3153 | |
3154 /* Do struct-reorg transformation for individual function | |
3155 represented by NODE. All structure types relevant | |
3156 for this function are transformed. */ | |
3157 | |
3158 static void | |
3159 do_reorg_for_func (struct cgraph_node *node) | |
3160 { | |
3161 create_new_local_vars (); | |
3162 create_new_alloc_sites_for_func (node); | |
3163 create_new_accesses_for_func (); | |
3164 update_ssa (TODO_update_ssa); | |
3165 cleanup_tree_cfg (); | |
3166 | |
3167 /* Free auxiliary data representing local variables. */ | |
3168 free_new_vars_htab (new_local_vars); | |
3169 } | |
3170 | |
3171 /* Print structure TYPE, its name, if it exists, and body. | |
3172 INDENT defines the level of indentation (similar | |
3173 to the option -i of indent command). SHIFT parameter | |
3174 defines a number of spaces by which a structure will | |
3175 be shifted right. */ | |
3176 | |
3177 static void | |
3178 dump_struct_type (tree type, unsigned HOST_WIDE_INT indent, | |
3179 unsigned HOST_WIDE_INT shift) | |
3180 { | |
3181 const char *struct_name; | |
3182 tree field; | |
3183 | |
3184 if (!type || !dump_file) | |
3185 return; | |
3186 | |
3187 if (TREE_CODE (type) != RECORD_TYPE) | |
3188 { | |
3189 print_generic_expr (dump_file, type, 0); | |
3190 return; | |
3191 } | |
3192 | |
3193 print_shift (shift); | |
3194 struct_name = get_type_name (type); | |
3195 fprintf (dump_file, "struct "); | |
3196 if (struct_name) | |
3197 fprintf (dump_file, "%s\n",struct_name); | |
3198 print_shift (shift); | |
3199 fprintf (dump_file, "{\n"); | |
3200 | |
3201 for (field = TYPE_FIELDS (type); field; | |
3202 field = TREE_CHAIN (field)) | |
3203 { | |
3204 unsigned HOST_WIDE_INT s = indent; | |
3205 tree f_type = TREE_TYPE (field); | |
3206 | |
3207 print_shift (shift); | |
3208 while (s--) | |
3209 fprintf (dump_file, " "); | |
3210 dump_struct_type (f_type, indent, shift + indent); | |
3211 fprintf(dump_file, " "); | |
3212 print_generic_expr (dump_file, field, 0); | |
3213 fprintf(dump_file, ";\n"); | |
3214 } | |
3215 print_shift (shift); | |
3216 fprintf (dump_file, "}\n"); | |
3217 } | |
3218 | |
3219 /* This function creates new structure types to replace original type, | |
3220 indicated by STR->decl. The names of the new structure types are | |
3221 derived from the original structure type. If the original structure | |
3222 type has no name, we assume that its name is 'struct.<STR_NUM>'. */ | |
3223 | |
3224 static void | |
3225 create_new_type (d_str str, int *str_num) | |
3226 { | |
3227 int cluster_num = 0; | |
3228 | |
3229 struct field_cluster *cluster = str->struct_clustering; | |
3230 while (cluster) | |
3231 { | |
3232 tree name = gen_cluster_name (str->decl, cluster_num, | |
3233 *str_num); | |
3234 tree fields; | |
3235 tree new_type; | |
3236 cluster_num++; | |
3237 | |
3238 fields = create_fields (cluster, str->fields, | |
3239 str->num_fields); | |
3240 new_type = build_basic_struct (fields, name, str->decl); | |
3241 | |
3242 update_fields_mapping (cluster, new_type, | |
3243 str->fields, str->num_fields); | |
3244 | |
3245 VEC_safe_push (tree, heap, str->new_types, new_type); | |
3246 cluster = cluster->sibling; | |
3247 } | |
3248 (*str_num)++; | |
3249 } | |
3250 | |
3251 /* This function is a callback for alloc_sites hashtable | |
3252 traversal. SLOT is a pointer to fallocs_t. | |
3253 This function frees memory pointed by *SLOT. */ | |
3254 | |
3255 static int | |
3256 free_falloc_sites (void **slot, void *data ATTRIBUTE_UNUSED) | |
3257 { | |
3258 fallocs_t fallocs = *(fallocs_t *) slot; | |
3259 | |
3260 VEC_free (alloc_site_t, heap, fallocs->allocs); | |
3261 free (fallocs); | |
3262 return 1; | |
3263 } | |
3264 | |
3265 /* Remove structures collected in UNSUITABLE_TYPES | |
3266 from structures vector. */ | |
3267 | |
3268 static void | |
3269 remove_unsuitable_types (VEC (tree, heap) *unsuitable_types) | |
3270 { | |
3271 d_str str; | |
3272 tree type; | |
3273 unsigned i, j; | |
3274 | |
3275 for (j = 0; VEC_iterate (tree, unsuitable_types, j, type); j++) | |
3276 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
3277 if (is_equal_types (str->decl, type)) | |
3278 { | |
3279 remove_structure (i); | |
3280 break; | |
3281 } | |
3282 } | |
3283 | |
3284 /* Exclude structure types with bitfields. | |
3285 We would not want to interfere with other optimizations | |
3286 that can be done in this case. The structure types with | |
3287 bitfields are added to UNSUITABLE_TYPES vector. */ | |
3288 | |
3289 static void | |
3290 exclude_types_with_bit_fields (VEC (tree, heap) **unsuitable_types) | |
3291 { | |
3292 d_str str; | |
3293 unsigned i; | |
3294 | |
3295 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
3296 check_bitfields (str, unsuitable_types); | |
3297 } | |
3298 | |
3299 /* This function checks three types of escape. A structure type escapes: | |
3300 | |
3301 1. if it's a type of parameter of a local function. | |
3302 2. if it's a type of function return value. | |
3303 3. if it escapes as a result of ipa-type-escape analysis. | |
3304 | |
3305 The escaping structure types are added to UNSUITABLE_TYPES vector. */ | |
3306 | |
3307 static void | |
3308 exclude_escaping_types (VEC (tree, heap) **unsuitable_types) | |
3309 { | |
3310 exclude_types_passed_to_local_func (unsuitable_types); | |
3311 exclude_returned_types (unsuitable_types); | |
3312 exclude_escaping_types_1 (unsuitable_types); | |
3313 } | |
3314 | |
3315 /* This function analyzes whether the form of | |
3316 structure is such that we are capable to transform it. | |
3317 Nested structures are checked here. Unsuitable structure | |
3318 types are added to UNSUITABLE_TYPE vector. */ | |
3319 | |
3320 static void | |
3321 analyze_struct_form (VEC (tree, heap) **unsuitable_types) | |
3322 { | |
3323 d_str str; | |
3324 unsigned i; | |
3325 | |
3326 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
3327 check_struct_form (str, unsuitable_types); | |
3328 } | |
3329 | |
3330 /* This function looks for structure types instantiated in the program. | |
3331 The candidate types are added to the structures vector. | |
3332 Unsuitable types are collected into UNSUITABLE_TYPES vector. */ | |
3333 | |
3334 static void | |
3335 build_data_structure (VEC (tree, heap) **unsuitable_types) | |
3336 { | |
3337 tree var, type; | |
3338 tree var_list; | |
3339 struct varpool_node *current_varpool; | |
3340 struct cgraph_node *c_node; | |
3341 | |
3342 /* Check global variables. */ | |
3343 FOR_EACH_STATIC_VARIABLE (current_varpool) | |
3344 { | |
3345 var = current_varpool->decl; | |
3346 if (is_candidate (var, &type, unsuitable_types)) | |
3347 add_structure (type); | |
3348 } | |
3349 | |
3350 /* Now add structures that are types of function parameters and | |
3351 local variables. */ | |
3352 for (c_node = cgraph_nodes; c_node; c_node = c_node->next) | |
3353 { | |
3354 enum availability avail = | |
3355 cgraph_function_body_availability (c_node); | |
3356 | |
3357 /* We need AVAIL_AVAILABLE for main function. */ | |
3358 if (avail == AVAIL_LOCAL || avail == AVAIL_AVAILABLE) | |
3359 { | |
3360 struct function *fn = DECL_STRUCT_FUNCTION (c_node->decl); | |
3361 | |
3362 for (var = DECL_ARGUMENTS (c_node->decl); var; | |
3363 var = TREE_CHAIN (var)) | |
3364 if (is_candidate (var, &type, unsuitable_types)) | |
3365 add_structure (type); | |
3366 | |
3367 /* Check function local variables. */ | |
3368 for (var_list = fn->local_decls; var_list; | |
3369 var_list = TREE_CHAIN (var_list)) | |
3370 { | |
3371 var = TREE_VALUE (var_list); | |
3372 | |
3373 if (is_candidate (var, &type, unsuitable_types)) | |
3374 add_structure (type); | |
3375 } | |
3376 } | |
3377 } | |
3378 } | |
3379 | |
3380 /* This function returns true if the program contains | |
3381 a call to user defined allocation function, or other | |
3382 functions that can interfere with struct-reorg optimizations. */ | |
3383 | |
3384 static bool | |
3385 program_redefines_malloc_p (void) | |
3386 { | |
3387 struct cgraph_node *c_node; | |
3388 struct cgraph_node *c_node2; | |
3389 struct cgraph_edge *c_edge; | |
3390 tree fndecl; | |
3391 tree fndecl2; | |
3392 | |
3393 for (c_node = cgraph_nodes; c_node; c_node = c_node->next) | |
3394 { | |
3395 fndecl = c_node->decl; | |
3396 | |
3397 for (c_edge = c_node->callees; c_edge; c_edge = c_edge->next_callee) | |
3398 { | |
3399 c_node2 = c_edge->callee; | |
3400 fndecl2 = c_node2->decl; | |
3401 if (is_gimple_call (c_edge->call_stmt)) | |
3402 { | |
3403 const char * fname = get_name (fndecl2); | |
3404 | |
3405 if ((gimple_call_flags (c_edge->call_stmt) & ECF_MALLOC) | |
3406 && (DECL_FUNCTION_CODE (fndecl2) != BUILT_IN_MALLOC) | |
3407 && (DECL_FUNCTION_CODE (fndecl2) != BUILT_IN_CALLOC) | |
3408 && (DECL_FUNCTION_CODE (fndecl2) != BUILT_IN_ALLOCA)) | |
3409 return true; | |
3410 | |
3411 /* Check that there is no __builtin_object_size, | |
3412 __builtin_offsetof, or realloc's in the program. */ | |
3413 if (DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_OBJECT_SIZE | |
3414 || !strcmp (fname, "__builtin_offsetof") | |
3415 || !strcmp (fname, "realloc")) | |
3416 return true; | |
3417 } | |
3418 } | |
3419 } | |
3420 | |
3421 return false; | |
3422 } | |
3423 | |
3424 /* In this function we assume that an allocation statement | |
3425 | |
3426 var = (type_cast) malloc (size); | |
3427 | |
3428 is converted into the following set of statements: | |
3429 | |
3430 T.1 = size; | |
3431 T.2 = malloc (T.1); | |
3432 T.3 = (type_cast) T.2; | |
3433 var = T.3; | |
3434 | |
3435 In this function we collect into alloc_sites the allocation | |
3436 sites of variables of structure types that are present | |
3437 in structures vector. */ | |
3438 | |
3439 static void | |
3440 collect_alloc_sites (void) | |
3441 { | |
3442 struct cgraph_node *node; | |
3443 struct cgraph_edge *cs; | |
3444 | |
3445 for (node = cgraph_nodes; node; node = node->next) | |
3446 if (node->analyzed && node->decl) | |
3447 { | |
3448 for (cs = node->callees; cs; cs = cs->next_callee) | |
3449 { | |
3450 gimple stmt = cs->call_stmt; | |
3451 | |
3452 if (stmt) | |
3453 { | |
3454 tree decl; | |
3455 | |
3456 if (is_gimple_call (stmt) | |
3457 && (decl = gimple_call_fndecl (stmt)) | |
3458 && gimple_call_lhs (stmt)) | |
3459 { | |
3460 unsigned i; | |
3461 | |
3462 if (is_alloc_of_struct (stmt, &i)) | |
3463 { | |
3464 /* We support only malloc now. */ | |
3465 if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MALLOC) | |
3466 { | |
3467 d_str str; | |
3468 | |
3469 str = VEC_index (structure, structures, i); | |
3470 add_alloc_site (node->decl, stmt, str); | |
3471 } | |
3472 else | |
3473 { | |
3474 if (dump_file) | |
3475 { | |
3476 fprintf (dump_file, | |
3477 "\nUnsupported allocation function "); | |
3478 print_gimple_stmt (dump_file, stmt, 0, 0); | |
3479 } | |
3480 remove_structure (i); | |
3481 } | |
3482 } | |
3483 } | |
3484 } | |
3485 } | |
3486 } | |
3487 } | |
3488 | |
3489 /* Print collected accesses. */ | |
3490 | |
3491 static void | |
3492 dump_accesses (void) | |
3493 { | |
3494 d_str str; | |
3495 unsigned i; | |
3496 | |
3497 if (!dump_file) | |
3498 return; | |
3499 | |
3500 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
3501 dump_accs (str); | |
3502 } | |
3503 | |
3504 /* This function checks whether the accesses of structures in condition | |
3505 expressions are of the kind we are capable to transform. | |
3506 If not, such structures are removed from the vector of structures. */ | |
3507 | |
3508 static void | |
3509 check_cond_exprs (void) | |
3510 { | |
3511 d_str str; | |
3512 unsigned i; | |
3513 | |
3514 i = 0; | |
3515 while (VEC_iterate (structure, structures, i, str)) | |
3516 { | |
3517 bool safe_p = true; | |
3518 | |
3519 if (str->accs) | |
3520 htab_traverse (str->accs, safe_cond_expr_check, &safe_p); | |
3521 if (!safe_p) | |
3522 remove_structure (i); | |
3523 else | |
3524 i++; | |
3525 } | |
3526 } | |
3527 | |
3528 /* We exclude from non-field accesses of the structure | |
3529 all statements that will be treated as part of the structure | |
3530 allocation sites or field accesses. */ | |
3531 | |
3532 static void | |
3533 exclude_alloc_and_field_accs (struct cgraph_node *node) | |
3534 { | |
3535 d_str str; | |
3536 unsigned i; | |
3537 | |
3538 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
3539 exclude_alloc_and_field_accs_1 (str, node); | |
3540 } | |
3541 | |
3542 /* This function collects accesses of the fields of the structures | |
3543 that appear at function FN. */ | |
3544 | |
3545 static void | |
3546 collect_accesses_in_func (struct function *fn) | |
3547 { | |
3548 basic_block bb; | |
3549 | |
3550 if (! fn) | |
3551 return; | |
3552 | |
3553 /* Collect accesses for each basic blocks separately. */ | |
3554 FOR_EACH_BB_FN (bb, fn) | |
3555 collect_accesses_in_bb (bb); | |
3556 } | |
3557 | |
3558 /* This function summarizes counts of the fields into the structure count. */ | |
3559 | |
3560 static void | |
3561 sum_counts (d_str str, gcov_type *hottest) | |
3562 { | |
3563 int i; | |
3564 | |
3565 str->count = 0; | |
3566 for (i = 0; i < str->num_fields; i++) | |
3567 { | |
3568 if (dump_file) | |
3569 { | |
3570 fprintf (dump_file, "\nCounter of field \""); | |
3571 print_generic_expr (dump_file, str->fields[i].decl, 0); | |
3572 fprintf (dump_file, "\" is " HOST_WIDEST_INT_PRINT_DEC, | |
3573 str->fields[i].count); | |
3574 } | |
3575 str->count += str->fields[i].count; | |
3576 } | |
3577 | |
3578 if (dump_file) | |
3579 { | |
3580 fprintf (dump_file, "\nCounter of struct \""); | |
3581 print_generic_expr (dump_file, str->decl, 0); | |
3582 fprintf (dump_file, "\" is " HOST_WIDEST_INT_PRINT_DEC, str->count); | |
3583 } | |
3584 | |
3585 if (str->count > *hottest) | |
3586 *hottest = str->count; | |
3587 } | |
3588 | |
3589 /* This function peels the field into separate structure if it's | |
3590 sufficiently hot, i.e. if its count provides at least 90% of | |
3591 the maximum field count in the structure. */ | |
3592 | |
3593 static void | |
3594 peel_hot_fields (d_str str) | |
3595 { | |
3596 gcov_type max_field_count; | |
3597 sbitmap fields_left = sbitmap_alloc (str->num_fields); | |
3598 int i; | |
3599 | |
3600 sbitmap_ones (fields_left); | |
3601 max_field_count = | |
3602 (gcov_type) (get_max_field_count (str)/100)*90; | |
3603 | |
3604 str->struct_clustering = NULL; | |
3605 | |
3606 for (i = 0; i < str->num_fields; i++) | |
3607 { | |
3608 if (str->count >= max_field_count) | |
3609 { | |
3610 RESET_BIT (fields_left, i); | |
3611 peel_field (i, str); | |
3612 } | |
3613 } | |
3614 | |
3615 i = sbitmap_first_set_bit (fields_left); | |
3616 if (i != -1) | |
3617 gen_cluster (fields_left, str); | |
3618 else | |
3619 sbitmap_free (fields_left); | |
3620 } | |
3621 | |
3622 /* This function is a helper for do_reorg. It goes over | |
3623 functions in call graph and performs actual transformation | |
3624 on them. */ | |
3625 | |
3626 static void | |
3627 do_reorg_1 (void) | |
3628 { | |
3629 struct cgraph_node *node; | |
3630 | |
3631 /* Initialize the default bitmap obstack. */ | |
3632 bitmap_obstack_initialize (NULL); | |
3633 | |
3634 for (node = cgraph_nodes; node; node = node->next) | |
3635 if (node->analyzed && node->decl && !node->next_clone) | |
3636 { | |
3637 push_cfun (DECL_STRUCT_FUNCTION (node->decl)); | |
3638 current_function_decl = node->decl; | |
3639 if (dump_file) | |
3640 fprintf (dump_file, "\nFunction to do reorg is %s: \n", | |
3641 (const char *) IDENTIFIER_POINTER (DECL_NAME (node->decl))); | |
3642 do_reorg_for_func (node); | |
3643 free_dominance_info (CDI_DOMINATORS); | |
3644 free_dominance_info (CDI_POST_DOMINATORS); | |
3645 current_function_decl = NULL; | |
3646 pop_cfun (); | |
3647 } | |
3648 | |
3649 set_cfun (NULL); | |
3650 bitmap_obstack_release (NULL); | |
3651 } | |
3652 | |
3653 /* This function creates new global struct variables. | |
3654 For each original variable, the set of new variables | |
3655 is created with the new structure types corresponding | |
3656 to the structure type of original variable. | |
3657 Only VAR_DECL variables are treated by this function. */ | |
3658 | |
3659 static void | |
3660 create_new_global_vars (void) | |
3661 { | |
3662 struct varpool_node *current_varpool; | |
3663 unsigned HOST_WIDE_INT i; | |
3664 unsigned HOST_WIDE_INT varpool_size = 0; | |
3665 | |
3666 for (i = 0; i < 2; i++) | |
3667 { | |
3668 if (i) | |
3669 new_global_vars = htab_create (varpool_size, | |
3670 new_var_hash, new_var_eq, NULL); | |
3671 FOR_EACH_STATIC_VARIABLE(current_varpool) | |
3672 { | |
3673 tree var_decl = current_varpool->decl; | |
3674 | |
3675 if (!var_decl || TREE_CODE (var_decl) != VAR_DECL) | |
3676 continue; | |
3677 if (!i) | |
3678 varpool_size++; | |
3679 else | |
3680 create_new_var (var_decl, new_global_vars); | |
3681 } | |
3682 } | |
3683 | |
3684 if (new_global_vars) | |
3685 htab_traverse (new_global_vars, update_varpool_with_new_var, NULL); | |
3686 } | |
3687 | |
3688 /* Dump all new types generated by this optimization. */ | |
3689 | |
3690 static void | |
3691 dump_new_types (void) | |
3692 { | |
3693 d_str str; | |
3694 tree type; | |
3695 unsigned i, j; | |
3696 | |
3697 if (!dump_file) | |
3698 return; | |
3699 | |
3700 fprintf (dump_file, "\nThe following are the new types generated by" | |
3701 " this optimization:\n"); | |
3702 | |
3703 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
3704 { | |
3705 if (dump_file) | |
3706 { | |
3707 fprintf (dump_file, "\nFor type "); | |
3708 dump_struct_type (str->decl, 2, 0); | |
3709 fprintf (dump_file, "\nthe number of new types is %d\n", | |
3710 VEC_length (tree, str->new_types)); | |
3711 } | |
3712 for (j = 0; VEC_iterate (tree, str->new_types, j, type); j++) | |
3713 dump_struct_type (type, 2, 0); | |
3714 } | |
3715 } | |
3716 | |
3717 /* This function creates new types to replace old structure types. */ | |
3718 | |
3719 static void | |
3720 create_new_types (void) | |
3721 { | |
3722 d_str str; | |
3723 unsigned i; | |
3724 int str_num = 0; | |
3725 | |
3726 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
3727 create_new_type (str, &str_num); | |
3728 } | |
3729 | |
3730 /* Free allocation sites hashtable. */ | |
3731 | |
3732 static void | |
3733 free_alloc_sites (void) | |
3734 { | |
3735 if (alloc_sites) | |
3736 htab_traverse (alloc_sites, free_falloc_sites, NULL); | |
3737 htab_delete (alloc_sites); | |
3738 alloc_sites = NULL; | |
3739 } | |
3740 | |
3741 /* This function collects structures potential | |
3742 for peeling transformation, and inserts | |
3743 them into structures hashtable. */ | |
3744 | |
3745 static void | |
3746 collect_structures (void) | |
3747 { | |
3748 VEC (tree, heap) *unsuitable_types = VEC_alloc (tree, heap, 32); | |
3749 | |
3750 structures = VEC_alloc (structure, heap, 32); | |
3751 | |
3752 /* If program contains user defined mallocs, we give up. */ | |
3753 if (program_redefines_malloc_p ()) | |
3754 return; | |
3755 | |
3756 /* Build data structures hashtable of all data structures | |
3757 in the program. */ | |
3758 build_data_structure (&unsuitable_types); | |
3759 | |
3760 /* This function analyzes whether the form of | |
3761 structure is such that we are capable to transform it. | |
3762 Nested structures are checked here. */ | |
3763 analyze_struct_form (&unsuitable_types); | |
3764 | |
3765 /* This function excludes those structure types | |
3766 that escape compilation unit. */ | |
3767 exclude_escaping_types (&unsuitable_types); | |
3768 | |
3769 /* We do not want to change data layout of the structures with bitfields. */ | |
3770 exclude_types_with_bit_fields (&unsuitable_types); | |
3771 | |
3772 remove_unsuitable_types (unsuitable_types); | |
3773 VEC_free (tree, heap, unsuitable_types); | |
3774 } | |
3775 | |
3776 /* Collect structure allocation sites. In case of arrays | |
3777 we have nothing to do. */ | |
3778 | |
3779 static void | |
3780 collect_allocation_sites (void) | |
3781 { | |
3782 alloc_sites = htab_create (32, malloc_hash, malloc_eq, NULL); | |
3783 collect_alloc_sites (); | |
3784 } | |
3785 | |
3786 /* This function collects data accesses for the | |
3787 structures to be transformed. For each structure | |
3788 field it updates the count field in field_entry. */ | |
3789 | |
3790 static void | |
3791 collect_data_accesses (void) | |
3792 { | |
3793 struct cgraph_node *c_node; | |
3794 | |
3795 for (c_node = cgraph_nodes; c_node; c_node = c_node->next) | |
3796 { | |
3797 enum availability avail = cgraph_function_body_availability (c_node); | |
3798 | |
3799 if (avail == AVAIL_LOCAL || avail == AVAIL_AVAILABLE) | |
3800 { | |
3801 struct function *func = DECL_STRUCT_FUNCTION (c_node->decl); | |
3802 | |
3803 if (!c_node->next_clone) | |
3804 collect_accesses_in_func (func); | |
3805 exclude_alloc_and_field_accs (c_node); | |
3806 } | |
3807 } | |
3808 | |
3809 check_cond_exprs (); | |
3810 /* Print collected accesses. */ | |
3811 dump_accesses (); | |
3812 } | |
3813 | |
3814 /* We do not bother to transform cold structures. | |
3815 Coldness of the structure is defined relatively | |
3816 to the highest structure count among the structures | |
3817 to be transformed. It's triggered by the compiler parameter | |
3818 | |
3819 --param struct-reorg-cold-struct-ratio=<value> | |
3820 | |
3821 where <value> ranges from 0 to 100. Structures with count ratios | |
3822 that are less than this parameter are considered to be cold. */ | |
3823 | |
3824 static void | |
3825 exclude_cold_structs (void) | |
3826 { | |
3827 gcov_type hottest = 0; | |
3828 unsigned i; | |
3829 d_str str; | |
3830 | |
3831 /* We summarize counts of fields of a structure into the structure count. */ | |
3832 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
3833 sum_counts (str, &hottest); | |
3834 | |
3835 /* Remove cold structures from structures vector. */ | |
3836 i = 0; | |
3837 while (VEC_iterate (structure, structures, i, str)) | |
3838 if (str->count * 100 < (hottest * STRUCT_REORG_COLD_STRUCT_RATIO)) | |
3839 { | |
3840 if (dump_file) | |
3841 { | |
3842 fprintf (dump_file, "\nThe structure "); | |
3843 print_generic_expr (dump_file, str->decl, 0); | |
3844 fprintf (dump_file, " is cold."); | |
3845 } | |
3846 remove_structure (i); | |
3847 } | |
3848 else | |
3849 i++; | |
3850 } | |
3851 | |
3852 /* This function decomposes original structure into substructures, | |
3853 i.e.clusters. */ | |
3854 | |
3855 static void | |
3856 peel_structs (void) | |
3857 { | |
3858 d_str str; | |
3859 unsigned i; | |
3860 | |
3861 for (i = 0; VEC_iterate (structure, structures, i, str); i++) | |
3862 peel_hot_fields (str); | |
3863 } | |
3864 | |
3865 /* Stage 3. */ | |
3866 /* Do the actual transformation for each structure | |
3867 from the structures hashtable. */ | |
3868 | |
3869 static void | |
3870 do_reorg (void) | |
3871 { | |
3872 /* Check that there is a work to do. */ | |
3873 if (!VEC_length (structure, structures)) | |
3874 { | |
3875 if (dump_file) | |
3876 fprintf (dump_file, "\nNo structures to transform. Exiting..."); | |
3877 return; | |
3878 } | |
3879 else | |
3880 { | |
3881 if (dump_file) | |
3882 { | |
3883 fprintf (dump_file, "\nNumber of structures to transform is %d", | |
3884 VEC_length (structure, structures)); | |
3885 } | |
3886 } | |
3887 | |
3888 /* Generate new types. */ | |
3889 create_new_types (); | |
3890 dump_new_types (); | |
3891 | |
3892 /* Create new global variables. */ | |
3893 create_new_global_vars (); | |
3894 dump_new_vars (new_global_vars); | |
3895 | |
3896 /* Decompose structures for each function separately. */ | |
3897 do_reorg_1 (); | |
3898 | |
3899 /* Free auxiliary data collected for global variables. */ | |
3900 free_new_vars_htab (new_global_vars); | |
3901 } | |
3902 | |
3903 /* Free all auxiliary data used by this optimization. */ | |
3904 | |
3905 static void | |
3906 free_data_structs (void) | |
3907 { | |
3908 free_structures (); | |
3909 free_alloc_sites (); | |
3910 } | |
3911 | |
3912 /* Perform structure decomposition (peeling). */ | |
3913 | |
3914 static void | |
3915 reorg_structs (void) | |
3916 { | |
3917 | |
3918 /* Stage1. */ | |
3919 /* Collect structure types. */ | |
3920 collect_structures (); | |
3921 | |
3922 /* Collect structure allocation sites. */ | |
3923 collect_allocation_sites (); | |
3924 | |
3925 /* Collect structure accesses. */ | |
3926 collect_data_accesses (); | |
3927 | |
3928 /* We transform only hot structures. */ | |
3929 exclude_cold_structs (); | |
3930 | |
3931 /* Stage2. */ | |
3932 /* Decompose structures into substructures, i.e. clusters. */ | |
3933 peel_structs (); | |
3934 | |
3935 /* Stage3. */ | |
3936 /* Do the actual transformation for each structure | |
3937 from the structures hashtable. */ | |
3938 do_reorg (); | |
3939 | |
3940 /* Free all auxiliary data used by this optimization. */ | |
3941 free_data_structs (); | |
3942 } | |
3943 | |
3944 /* Struct-reorg optimization entry point function. */ | |
3945 | |
3946 static unsigned int | |
3947 reorg_structs_drive (void) | |
3948 { | |
3949 reorg_structs (); | |
3950 return 0; | |
3951 } | |
3952 | |
3953 /* Struct-reorg optimization gate function. */ | |
3954 | |
3955 static bool | |
3956 struct_reorg_gate (void) | |
3957 { | |
3958 return flag_ipa_struct_reorg | |
3959 && flag_whole_program | |
3960 && (optimize > 0); | |
3961 } | |
3962 | |
3963 struct simple_ipa_opt_pass pass_ipa_struct_reorg = | |
3964 { | |
3965 { | |
3966 SIMPLE_IPA_PASS, | |
3967 "ipa_struct_reorg", /* name */ | |
3968 struct_reorg_gate, /* gate */ | |
3969 reorg_structs_drive, /* execute */ | |
3970 NULL, /* sub */ | |
3971 NULL, /* next */ | |
3972 0, /* static_pass_number */ | |
3973 TV_INTEGRATION, /* tv_id */ | |
3974 0, /* properties_required */ | |
3975 0, /* properties_provided */ | |
3976 0, /* properties_destroyed */ | |
3977 TODO_verify_ssa, /* todo_flags_start */ | |
3978 TODO_dump_func | TODO_verify_ssa /* todo_flags_finish */ | |
3979 } | |
3980 }; |