Attachment 'unidapt_patch_20070718.diff'
Download 1 Index: gcc/tree-tailcall.c
2 ===================================================================
3 --- gcc/tree-tailcall.c (revision 9015)
4 +++ gcc/tree-tailcall.c (working copy)
5 @@ -1008,6 +1008,13 @@
6 static bool
7 gate_tail_calls (void)
8 {
9 + /* FGG temporal hack for UNIDAPT */
10 + return 0;
11 +
12 + /* FGG ??? should be this */
13 + return flag_optimize_sibling_calls != 0 && !flag_api_clone_functions;
14 +
15 + /* original */
16 return flag_optimize_sibling_calls != 0 && dbg_cnt (tail_call);
17 }
18
19 Index: gcc/tree.h
20 ===================================================================
21 --- gcc/tree.h (revision 9015)
22 +++ gcc/tree.h (working copy)
23 @@ -5000,4 +5000,7 @@
24 for ((arg) = first_call_expr_arg ((call), &(iter)); (arg); \
25 (arg) = next_call_expr_arg (&(iter)))
26
27 +extern int is_adapt_functions_needed (void);
28 +extern void init_adaptation (void);
29 +
30 #endif /* GCC_TREE_H */
31 Index: gcc/tree-pass.h
32 ===================================================================
33 --- gcc/tree-pass.h (revision 9015)
34 +++ gcc/tree-pass.h (working copy)
35 @@ -442,6 +442,11 @@
36 extern struct tree_opt_pass pass_apply_inline;
37 extern struct tree_opt_pass pass_all_early_optimizations;
38
39 +extern struct tree_opt_pass pass_adaptation;
40 +extern struct tree_opt_pass pass_set_specific_options;
41 +extern struct tree_opt_pass pass_restore_options;
42 +
43 +
44 /* The root of the compilation pass tree, once constructed. */
45 extern struct tree_opt_pass *all_passes, *all_ipa_passes, *all_lowering_passes;
46
47 Index: gcc/ipa-cp.c
48 ===================================================================
49 --- gcc/ipa-cp.c (revision 9015)
50 +++ gcc/ipa-cp.c (working copy)
51 @@ -1042,8 +1042,13 @@
52 VEC_quick_push (cgraph_edge_p, redirect_callers, cs);
53 /* Redirecting all the callers of the node to the
54 new versioned node. */
55 - node1 =
56 - cgraph_function_versioning (node, redirect_callers, replace_trees);
57 +
58 + if (!tree_versionable_function_p (node->decl))
59 + node1 = NULL;
60 + else
61 + node1 = cgraph_function_versioning (node, redirect_callers,
62 + replace_trees);
63 +
64 VEC_free (cgraph_edge_p, heap, redirect_callers);
65 VARRAY_CLEAR (replace_trees);
66 if (node1 == NULL)
67 Index: gcc/toplev.c
68 ===================================================================
69 --- gcc/toplev.c (revision 9015)
70 +++ gcc/toplev.c (working copy)
71 @@ -2169,7 +2169,15 @@
72
73 /* Parse the options and do minimal processing; basically just
74 enough to default flags appropriately. */
75 - decode_options (argc, argv);
76 + if (is_adapt_functions_needed ())
77 + {
78 + fprintf (stderr, "Options will be backuped\n");
79 + init_adaptation ();
80 + decode_options (argc, argv);
81 + save_options ();
82 + }
83 + else
84 + decode_options (argc, argv);
85
86 init_local_tick ();
87
88 Index: gcc/cgraphunit.c
89 ===================================================================
90 --- gcc/cgraphunit.c (revision 9015)
91 +++ gcc/cgraphunit.c (working copy)
92 @@ -1548,9 +1548,6 @@
93 struct cgraph_node *new_version_node = NULL;
94 tree new_decl;
95
96 - if (!tree_versionable_function_p (old_decl))
97 - return NULL;
98 -
99 /* Make a new FUNCTION_DECL tree node for the
100 new version. */
101 new_decl = copy_node (old_decl);
102 Index: gcc/tree-nrv.c
103 ===================================================================
104 --- gcc/tree-nrv.c (revision 9015)
105 +++ gcc/tree-nrv.c (working copy)
106 @@ -124,18 +124,9 @@
107 tree stmt = bsi_stmt (bsi);
108 tree ret_expr;
109
110 - if (TREE_CODE (stmt) == RETURN_EXPR)
111 + if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
112 + && GIMPLE_STMT_OPERAND (stmt, 0) == result)
113 {
114 - /* In a function with an aggregate return value, the
115 - gimplifier has changed all non-empty RETURN_EXPRs to
116 - return the RESULT_DECL. */
117 - ret_expr = TREE_OPERAND (stmt, 0);
118 - if (ret_expr)
119 - gcc_assert (ret_expr == result);
120 - }
121 - else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
122 - && GIMPLE_STMT_OPERAND (stmt, 0) == result)
123 - {
124 ret_expr = GIMPLE_STMT_OPERAND (stmt, 1);
125
126 /* Now verify that this return statement uses the same value
127 Index: gcc/ipa-inline.c
128 ===================================================================
129 --- gcc/ipa-inline.c (revision 9015)
130 +++ gcc/ipa-inline.c (working copy)
131 @@ -1414,7 +1414,7 @@
132 static bool
133 cgraph_gate_inlining (void)
134 {
135 - return flag_inline_trees;
136 + return flag_inline_trees && !(flag_api_clone_functions || flag_api_virtual_cloning);
137 }
138
139 struct tree_opt_pass pass_ipa_inline =
140 @@ -1467,7 +1467,7 @@
141 static bool
142 cgraph_gate_early_inlining (void)
143 {
144 - return flag_inline_trees && flag_early_inlining;
145 + return flag_inline_trees && flag_early_inlining && !flag_api_clone_functions;
146 }
147
148 struct tree_opt_pass pass_early_inline =
149 @@ -1493,7 +1493,8 @@
150 {
151 return (flag_inline_trees && flag_early_inlining
152 && (flag_branch_probabilities || flag_test_coverage
153 - || profile_arc_flag));
154 + || profile_arc_flag)
155 + && !flag_api_clone_functions);
156 }
157
158 /* IPA pass wrapper for early inlining pass. We need to run early inlining
159 Index: gcc/opts.c
160 ===================================================================
161 --- gcc/opts.c (revision 9015)
162 +++ gcc/opts.c (working copy)
163 @@ -1892,6 +1892,164 @@
164 return true;
165 }
166
167 +
168 +/* Defines if option should or not be backuped.
169 + * TODO: List of options shod be analised. */
170 +bool is_option_to_backup (struct cl_option option)
171 +{
172 + if(option.flags & CL_COMMON && !(option.flags & CL_TARGET) && option.flag_var)
173 + return true;
174 + else
175 + return false;
176 +}
177 +
178 +/* Copy string without memory leakage. */
179 +static inline void copy_string_var (const char **from, const char **to)
180 +{
181 + char *str = NULL;
182 +
183 + if(*to != NULL)
184 + free ((char *) *to);
185 +
186 + if(*from != NULL)
187 + {
188 + str = xmalloc(sizeof(char) * (strlen(*from) + 1));
189 + strcpy(str, *from);
190 + }
191 +
192 + *to = str;
193 +}
194 +
195 +
196 +static inline void copy_int_var (int *from, int *to)
197 +{
198 + if(from != NULL && to != NULL)
199 + {
200 + *to = *from;
201 + }
202 +}
203 +
204 +void save_options (void)
205 +{
206 + unsigned int i;
207 + for (i = 0; i < cl_options_count; i++)
208 + {
209 + if(is_option_to_backup(cl_options[i]))
210 + {
211 + switch(cl_options[i].var_type)
212 + {
213 + case CLVC_STRING:
214 + copy_string_var((const char **) cl_options[i].flag_var,
215 + (const char **) cl_options[i].saved_flag_var);
216 + break;
217 + default:
218 + copy_int_var((int *) cl_options[i].flag_var, (int *) cl_options[i].saved_flag_var);
219 + break;
220 + }
221 + }
222 + }
223 +}
224 +void save_new_options (void)
225 +{
226 + unsigned int i;
227 + for (i = 0; i < cl_options_count; i++)
228 + {
229 + if(is_option_to_backup(cl_options[i]))
230 + {
231 + switch(cl_options[i].var_type)
232 + {
233 + case CLVC_STRING:
234 + copy_string_var((const char **) cl_options[i].flag_var,
235 + (const char **) cl_options[i].new_flag_var);
236 + break;
237 + default:
238 + copy_int_var((int *) cl_options[i].flag_var, (int *) cl_options[i].new_flag_var);
239 + break;
240 + }
241 + }
242 + }
243 +}
244 +
245 +void restore_options (void)
246 +{
247 + unsigned int i, count = 0;
248 + for (i = 0; i < cl_options_count; i++)
249 + {
250 + if(is_option_to_backup(cl_options[i]))
251 + {
252 + count++;
253 + switch(cl_options[i].var_type)
254 + {
255 + case CLVC_STRING:
256 + copy_string_var((const char **) cl_options[i].saved_flag_var,
257 + (const char **) cl_options[i].flag_var);
258 + break;
259 + default:
260 + copy_int_var((int *) cl_options[i].saved_flag_var, (int *) cl_options[i].flag_var);
261 + break;
262 + }
263 + }
264 + }
265 +}
266 +void set_new_options (void)
267 +{
268 + unsigned int i, count = 0;
269 +
270 + for (i = 0; i < cl_options_count; i++)
271 + {
272 + if(is_option_to_backup(cl_options[i]))
273 + {
274 + count++;
275 + switch(cl_options[i].var_type)
276 + {
277 + case CLVC_STRING:
278 + copy_string_var((const char **) cl_options[i].new_flag_var,
279 + (const char **) cl_options[i].flag_var);
280 + break;
281 + default:
282 + copy_int_var((int *) cl_options[i].new_flag_var, (int *) cl_options[i].flag_var);
283 + break;
284 + }
285 + }
286 + }
287 +}
288 +
289 +void dump_options_copy(void)
290 +{
291 + FILE *file;
292 + unsigned int i;
293 + file = fopen("/tmp/options.csv", "w");
294 +
295 + for (i = 0; i < cl_options_count; i++)
296 + {
297 + if(is_option_to_backup(cl_options[i]))
298 + {
299 + fprintf(file, "%s;", cl_options[i].opt_text);
300 + switch(cl_options[i].var_type)
301 + {
302 + case CLVC_STRING:
303 + if(*(const char **) cl_options[i].flag_var != NULL)
304 + fprintf(file, "%s; %s; %s",
305 + *(const char **) cl_options[i].flag_var,
306 + *(const char **) cl_options[i].saved_flag_var,
307 + *(const char **) cl_options[i].new_flag_var
308 + );
309 + break;
310 + default:
311 + if((int *) cl_options[i].flag_var != NULL)
312 + fprintf(file, "%d; %d; %d",
313 + *((int *) cl_options[i].flag_var),
314 + *((int *) cl_options[i].saved_flag_var),
315 + *((int *) cl_options[i].new_flag_var)
316 + );
317 + break;
318 + }
319 + fprintf(file, "\n");
320 + }
321 + }
322 + fclose(file);
323 +}
324 +
325 /* Enable a warning option as an error. This is used by -Werror= and
326 also by legacy Werror-implicit-function-declaration. */
327
328 Index: gcc/opts.h
329 ===================================================================
330 --- gcc/opts.h (revision 9015)
331 +++ gcc/opts.h (working copy)
332 @@ -49,6 +49,8 @@
333 int neg_index;
334 unsigned int flags;
335 void *flag_var;
336 + void *saved_flag_var;
337 + void *new_flag_var;
338 enum cl_var_type var_type;
339 int var_value;
340 };
341 @@ -106,4 +108,12 @@
342
343 extern void enable_warning_as_error (const char *arg, int value,
344 unsigned int lang_mask);
345 +
346 +extern bool is_option_to_backup (struct cl_option option);
347 +extern void dump_options_copy (void);
348 +extern void save_options (void);
349 +extern void save_new_options (void);
350 +extern void restore_options (void);
351 +extern void set_new_options (void);
352 +
353 #endif
354 Index: gcc/optc-gen.awk
355 ===================================================================
356 --- gcc/optc-gen.awk (revision 9015)
357 +++ gcc/optc-gen.awk (working copy)
358 @@ -73,6 +73,14 @@
359 continue;
360
361 if (flag_set_p("VarExists", flags[i])) {
362 + if (flag_set_p("Common", flags[i]) && !flag_set_p("Target", flags[i]))
363 + {
364 + print "/* Added for function adaptation " opts[i] "."
365 + print " " help[i] " */"
366 + print var_type(flags[i]) name "_saved;"
367 + print var_type(flags[i]) name "_new;"
368 + }
369 +
370 # Need it for the gcc driver.
371 if (name in var_seen)
372 continue;
373 @@ -93,6 +101,11 @@
374 print "/* Set by -" opts[i] "."
375 print " " help[i] " */"
376 print var_type(flags[i]) name init ";"
377 + if (flag_set_p("Common", flags[i]) && !flag_set_p("Target", flags[i]))
378 + {
379 + print var_type(flags[i]) name "_saved;"
380 + print var_type(flags[i]) name "_new;"
381 + }
382 if (gcc_driver == 1)
383 print "#endif /* GCC_DRIVER */"
384 print ""
385 @@ -202,8 +215,20 @@
386 condition, cl_flags, cl_flags)
387 else
388 printf(" %s,\n", cl_flags)
389 - printf(" %s, %s }%s\n", var_ref(opts[i], flags[i]),
390 +
391 + if (var_ref(opts[i], flags[i]) != 0 && flag_set_p("Common", flags[i]) && !flag_set_p("Target", flags[i]))
392 + {
393 + printf(" %s, %s_saved, %s_new, %s }%s\n",
394 + var_ref(opts[i], flags[i]),
395 + var_ref(opts[i], flags[i]),
396 + var_ref(opts[i], flags[i]),
397 var_set(flags[i]), comma)
398 + }
399 + else
400 + printf(" %s, 0, 0, %s }%s\n",
401 + var_ref(opts[i], flags[i]),
402 + var_set(flags[i]), comma)
403 +
404 }
405
406 print "};"
407 Index: gcc/common.opt
408 ===================================================================
409 --- gcc/common.opt (revision 9015)
410 +++ gcc/common.opt (working copy)
411 @@ -285,6 +285,14 @@
412 falign-loops=
413 Common RejectNegative Joined UInteger
414
415 +fapi-clone-functions
416 +Common Report Var(flag_api_clone_functions)
417 +Activate API clone functions
418 +
419 +fapi-virtual-cloning
420 +Common Report Var(flag_api_virtual_cloning)
421 +Activate virtual cloning
422 +
423 ; This flag is only tested if alias checking is enabled.
424 ; 0 if pointer arguments may alias each other. True in C.
425 ; 1 if pointer arguments may not alias each other but may alias
426 Index: gcc/fapi-tools.c
427 ===================================================================
428 --- gcc/fapi-tools.c (revision 0)
429 +++ gcc/fapi-tools.c (revision 0)
430 @@ -0,0 +1,1122 @@
431 +/* Loop optimizations over tree-ssa.
432 + Copyright (C) 2006 by Cupertino Miranda
433 + INRIA Futurs, France
434 +
435 +This file is part of GCC.
436 +
437 +GCC is free software; you can redistribute it and/or modify it
438 +under the terms of the GNU General Public License as published by the
439 +Free Software Foundation; either version 2, or (at your option) any
440 +later version.
441 +
442 +GCC is distributed in the hope that it will be useful, but WITHOUT
443 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
444 +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
445 +for more details.
446 +
447 +You should have received a copy of the GNU General Public License
448 +along with GCC; see the file COPYING. If not, write to the Free
449 +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
450 +02110-1301, USA. */
451 +
452 +#include "config.h"
453 +#include "system.h"
454 +#include "coretypes.h"
455 +#include "tm.h"
456 +#include "tree.h"
457 +#include "rtl.h"
458 +#include "tm_p.h"
459 +#include "hard-reg-set.h"
460 +#include "basic-block.h"
461 +#include "output.h"
462 +#include "diagnostic.h"
463 +#include "tree-flow.h"
464 +#include "tree-dump.h"
465 +#include "tree-pass.h"
466 +#include "timevar.h"
467 +#include "cfgloop.h"
468 +#include "flags.h"
469 +#include "tree-inline.h"
470 +#include "cgraph.h"
471 +#include "ipa-prop.h"
472 +#include "opts.h"
473 +#include "tree-iterator.h"
474 +
475 +
476 +static void
477 +dump_bb_flags (FILE * file, basic_block bb)
478 +{
479 +#define DUMP_BB_FLAG(FLAG) \
480 + if(bb->flags & FLAG) \
481 + fprintf(file, "%s\\n", #FLAG);
482 +
483 + DUMP_BB_FLAG (BB_NEW);
484 + DUMP_BB_FLAG (BB_REACHABLE);
485 + DUMP_BB_FLAG (BB_IRREDUCIBLE_LOOP);
486 + DUMP_BB_FLAG (BB_SUPERBLOCK);
487 + DUMP_BB_FLAG (BB_DISABLE_SCHEDULE);
488 + DUMP_BB_FLAG (BB_HOT_PARTITION);
489 + DUMP_BB_FLAG (BB_COLD_PARTITION);
490 + DUMP_BB_FLAG (BB_DUPLICATED);
491 + DUMP_BB_FLAG (BB_RTL);
492 + DUMP_BB_FLAG (BB_FORWARDER_BLOCK);
493 + DUMP_BB_FLAG (BB_NONTHREADABLE_BLOCK);
494 +
495 +#undef DUMP_BB_FLAG
496 +}
497 +static void
498 +dump_edge_flags (FILE * file, edge e)
499 +{
500 +#define DUMP_EDGE_FLAG(FLAG) \
501 + if(e->flags & FLAG) \
502 + fprintf(file, "%s\\n", #FLAG);
503 +
504 + DUMP_EDGE_FLAG (EDGE_FALLTHRU); /* 'Straight line' flow */
505 + DUMP_EDGE_FLAG (EDGE_ABNORMAL); /* Strange flow, like computed
506 + label, or eh */
507 + DUMP_EDGE_FLAG (EDGE_ABNORMAL_CALL); /* Call with abnormal exit
508 + like an exception, or sibcall */
509 + DUMP_EDGE_FLAG (EDGE_EH); /* Exception throw */
510 + DUMP_EDGE_FLAG (EDGE_FAKE); /* Not a real edge (profile.c) */
511 + DUMP_EDGE_FLAG (EDGE_DFS_BACK); /* A backwards edge */
512 + DUMP_EDGE_FLAG (EDGE_CAN_FALLTHRU); /* Candidate for straight line
513 + flow. */
514 + DUMP_EDGE_FLAG (EDGE_IRREDUCIBLE_LOOP); /* Part of irreducible loop. */
515 + DUMP_EDGE_FLAG (EDGE_SIBCALL); /* Edge from sibcall to exit. */
516 + DUMP_EDGE_FLAG (EDGE_LOOP_EXIT); /* Exit of a loop. */
517 + DUMP_EDGE_FLAG (EDGE_TRUE_VALUE); /* Edge taken when controlling
518 + predicate is nonzero. */
519 + DUMP_EDGE_FLAG (EDGE_FALSE_VALUE); /* Edge taken when controlling
520 + predicate is zero. */
521 + DUMP_EDGE_FLAG (EDGE_EXECUTABLE); /* Edge is executable. Only
522 + valid during SSA-CCP. */
523 + DUMP_EDGE_FLAG (EDGE_CROSSING); /* Edge crosses between hot
524 + and cold sections, when we
525 + do partitioning. */
526 +
527 +#undef DUMP_BB_FLAG
528 +}
529 +
530 +void
531 +draw_cfg (struct function *func)
532 +{
533 + FILE *file = fopen ("/tmp/foo.dot", "w");
534 + dump_cfg_to_dot (file, func);
535 + fclose (file);
536 +
537 + system ("dotty /tmp/foo.dot");
538 +}
539 +
540 +
541 +void
542 +dump_cfg_to_dot (FILE *file, struct function *func)
543 +{
544 + basic_block bb;
545 + edge_iterator ei;
546 + edge e;
547 +
548 + fprintf (file, "digraph cfg {\n");
549 + FOR_EACH_BB_FN (bb, func)
550 + {
551 + block_stmt_iterator bsi;
552 + fprintf (file, "\"BB%d\" [ label = \"index = %d\\n", bb->index,
553 + bb->index);
554 + dump_bb_flags (file, bb);
555 +
556 + for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
557 + {
558 + tree stmt = bsi_stmt (bsi);
559 + print_generic_expr (file, stmt, 0);
560 + fprintf (file, "\\n");
561 + }
562 +
563 + fprintf (file, "\" ]\n");
564 + }
565 + FOR_EACH_BB_FN (bb, func)
566 + {
567 + FOR_EACH_EDGE (e, ei, bb->succs)
568 + {
569 + fprintf (file, "\"BB%d\" -> \"BB%d\" [ label = \"", (int) bb->index,
570 + (int) e->dest->index);
571 + dump_edge_flags (file, e);
572 + fprintf (file, "\"] \n");
573 + }
574 + }
575 + fprintf (file, "}\n");
576 +}
577 +
578 +static void
579 +dump_flags_to_csv (void)
580 +{
581 + FILE *file;
582 + unsigned int j;
583 + char filename[100];
584 +
585 + sprintf (filename, "/tmp/%s.csv",
586 + IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
587 +
588 + file = fopen (filename, "w");
589 + for (j = 0; j < cl_options_count; j++)
590 + {
591 +/*
592 + if ((cl_options[j].var_type == CLVC_BOOLEAN) &&
593 + (cl_options[j].flags & CL_COMMON) &&
594 + !(cl_options[j].flags & CL_TARGET)
595 + )
596 +*/
597 + if (is_option_to_backup (cl_options[j]))
598 + {
599 + if (cl_options[j].flag_var != NULL)
600 + fprintf (file, "%s; %d\n", cl_options[j].opt_text,
601 + *((int *) cl_options[j].flag_var));
602 + }
603 + }
604 + fclose (file);
605 +}
606 +
607 +char *id_function[500];
608 +int id_count;
609 +
610 +#if 0
611 +static void
612 +dump_ids (FILE * file)
613 +{
614 + int i;
615 + fprintf (file, " - id_count = %d --------------- \n", id_count);
616 +
617 + for (i = 0; i < id_count; i++)
618 + {
619 + if (id_function[i] != NULL)
620 + fprintf (file, " %d\t%s\n", i, id_function[i]);
621 + else
622 + fprintf (file, " %d\t%s\n", i, "NULL");
623 +
624 + }
625 +
626 + fprintf (file, " ----------------------------- \n");
627 +}
628 +#endif
629 +
630 +static void
631 +id_system_load (void)
632 +{
633 + FILE *file;
634 +
635 + /* Reading current ids */
636 + if ((file = fopen ("adaptation.ids", "r")) != NULL)
637 + {
638 + memset (id_function, 0, 500 * sizeof (char *));
639 +
640 + id_count = 0;
641 + while (!feof (file))
642 + {
643 + /* TODO Cupertino : Clean memory leak */
644 + char func_name[250];
645 + int id;
646 + int count;
647 +
648 + count = fscanf (file, "%d %s", &id, func_name);
649 +
650 + if (count == 2)
651 + {
652 + if (id >= id_count)
653 + id_count = id + 1;
654 +
655 + id_function[id] =
656 + (char *) xmalloc (sizeof (char) * (strlen (func_name) + 1));
657 + strcpy (id_function[id], func_name);
658 + }
659 + }
660 +
661 + fclose (file);
662 + }
663 + else
664 + {
665 + memset (id_function, 0, 500 * sizeof (char *));
666 + }
667 +}
668 +static void
669 +id_system_save (void)
670 +{
671 + FILE *file;
672 +
673 + /* Writing current ids */
674 + if ((file = fopen ("adaptation.ids", "w")) != NULL)
675 + {
676 + int i;
677 + for (i = 0; i < id_count; i++)
678 + {
679 + if (id_function[i] != NULL)
680 + {
681 + fprintf (file, "%d %s\n", i, id_function[i]);
682 + }
683 + }
684 +
685 + fclose (file);
686 + }
687 + else
688 + gcc_assert (0);
689 +}
690 +
691 +static int
692 +get_id (const char *func_name)
693 +{
694 + int i;
695 + int ret;
696 + int first_empty = -1;
697 + char *new_func_name;
698 + char *is_to_number;
699 +
700 + if ((is_to_number = getenv ("CO_ADAPT_NUMBERING")) != NULL)
701 + {
702 + if (strcmp ("1", is_to_number))
703 + return 1;
704 + }
705 + else
706 + return 1;
707 +
708 + id_system_load ();
709 +
710 + for (i = 0; i < id_count; i++)
711 + {
712 + if (id_function[i] != NULL)
713 + {
714 + if (!strcmp (func_name, id_function[i]))
715 + {
716 + return i + 1;
717 + break;
718 + }
719 + }
720 + else if (first_empty == -1)
721 + first_empty = i;
722 + }
723 +
724 +
725 + new_func_name = (char *) xmalloc (sizeof (char) * (strlen (func_name) + 1));
726 + strcpy (new_func_name, func_name);
727 +
728 + if (first_empty == -1)
729 + {
730 + id_function[id_count] = new_func_name;
731 + ret = id_count;
732 + id_count++;
733 + }
734 + else
735 + {
736 + id_function[first_empty] = new_func_name;
737 + ret = first_empty;
738 + }
739 +
740 + id_system_save ();
741 +
742 + return ret + 1;
743 +}
744 +static int
745 +get_id_count (void)
746 +{
747 + id_system_load ();
748 + return id_count;
749 +}
750 +
751 +static char **
752 +parse_call_format (char *format, unsigned int *argc)
753 +{
754 + char func_name[51];
755 + char arguments[251];
756 + char **argv;
757 + char *start;
758 + unsigned int i, size;
759 +
760 +
761 + int count = sscanf (format, "%50[^(](%250[^)]", func_name, arguments);
762 +
763 + size = count == 2 ? strlen (arguments) : 0;
764 +
765 + *argc = 1;
766 +
767 + if (size > 0)
768 + *argc = 2;
769 +
770 + for (i = 0; i < size; i++)
771 + {
772 + if (arguments[i] == ',')
773 + {
774 + arguments[i] = '\0';
775 + *argc = *argc + 1;
776 + }
777 + if (arguments[i] == ' ')
778 + {
779 + arguments[i] = '\0';
780 + }
781 + }
782 +
783 + argv = (char **) xmalloc (sizeof (char *) * (*argc + 1));
784 + start = arguments;
785 + for (i = 1; i < (*argc); i++)
786 + {
787 + if (strlen (start) == 0)
788 + {
789 + start += 1;
790 + i--;
791 + }
792 + else
793 + {
794 + argv[i] = (char *) xmalloc (sizeof (char) * (strlen (start) + 1));
795 + argv[i] = strcpy (argv[i], start);
796 + start += (strlen (argv[i]) + 1);
797 + }
798 + }
799 +
800 + argv[0] = (char *) xmalloc (sizeof (char) * (strlen (func_name) + 1));
801 + strcpy (argv[0], func_name);
802 + return argv;
803 +}
804 +
805 +
806 +extern tree mf_mark (tree);
807 +
808 +static tree
809 +build_cst_string (const char *string)
810 +{
811 + size_t len = strlen (string);
812 + tree result = mf_mark (build_string (len + 1, string));
813 +
814 + TREE_TYPE (result) = build_array_type
815 + (char_type_node, build_index_type (build_int_cst (NULL_TREE, len)));
816 + TREE_CONSTANT (result) = 1;
817 + TREE_INVARIANT (result) = 1;
818 + TREE_READONLY (result) = 1;
819 + TREE_STATIC (result) = 1;
820 +
821 + result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result);
822 +
823 + return mf_mark (result);
824 +}
825 +
826 +static void
827 +build_function_and_call (char *format, int id, struct cgraph_node *func,
828 + tree *func_decl, tree *func_call, bool is_clone,
829 + tree decision_var)
830 +{
831 + unsigned int argc, i;
832 + char **argv;
833 + tree args_type, args_call, func_type;
834 + struct cgraph_node *func_node;
835 +
836 + args_type = void_list_node;
837 + args_call = NULL_TREE;
838 +
839 + argv = parse_call_format (format, &argc);
840 +
841 + for (i = argc - 1; i > 0; i--)
842 + {
843 + switch (argv[i][0])
844 + {
845 + case '<':
846 + if (!strcmp (argv[i], "<id>"))
847 + {
848 + tree node;
849 + args_type = tree_cons (NULL_TREE, intSI_type_node, args_type);
850 + node = build_int_cst (intSI_type_node, id);
851 + args_call = tree_cons (NULL_TREE, node, args_call);
852 + }
853 + else if (!strcmp (argv[i], "<id_count>"))
854 + {
855 + tree node;
856 + int tmp_num = get_id_count ();
857 + args_type = tree_cons (NULL_TREE, intSI_type_node, args_type);
858 + node = build_int_cst (intSI_type_node, tmp_num);
859 + args_call = tree_cons (NULL_TREE, node, args_call);
860 + }
861 + else if (!strcmp (argv[i], "<file>"))
862 + {
863 + tree node;
864 + const char *file_name;
865 + args_type =
866 + tree_cons (NULL_TREE, const_ptr_type_node, args_type);
867 + file_name = DECL_SOURCE_FILE (func->decl);
868 + node = build_cst_string (file_name);
869 + args_call = tree_cons (NULL_TREE, node, args_call);
870 + }
871 + else if (!strcmp (argv[i], "<function>"))
872 + {
873 + tree node;
874 + const char *func_name;
875 + args_type =
876 + tree_cons (NULL_TREE, const_ptr_type_node, args_type);
877 + func_name = IDENTIFIER_POINTER (DECL_NAME (func->decl));
878 + node = build_cst_string (func_name);
879 + args_call = tree_cons (NULL_TREE, node, args_call);
880 + }
881 + else if (!strcmp (argv[i], "<line_no>"))
882 + {
883 + tree node;
884 + args_type =
885 + tree_cons (NULL_TREE, const_ptr_type_node, args_type);
886 + node =
887 + build_int_cst (intSI_type_node,
888 + DECL_SOURCE_LINE (func->decl));
889 + args_call = tree_cons (NULL_TREE, node, args_call);
890 + }
891 + else if (!strcmp (argv[i], "<is_clone>"))
892 + {
893 + tree node;
894 + args_type = tree_cons (NULL_TREE, intSI_type_node, args_type);
895 + node = is_clone ? integer_one_node : integer_zero_node;
896 + args_call = tree_cons (NULL_TREE, node, args_call);
897 + }
898 + else if (!strcmp (argv[i], "<decision>"))
899 + {
900 + tree node;
901 + args_type =
902 + tree_cons (NULL_TREE,
903 + TYPE_POINTER_TO (TREE_TYPE (decision_var)),
904 + args_type);
905 + node =
906 + build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (decision_var)),
907 + decision_var);
908 + recompute_tree_invariant_for_addr_expr (node);
909 + args_call = tree_cons (NULL_TREE, node, args_call);
910 + }
911 + else
912 + {
913 + gcc_assert (0);
914 + }
915 + break;
916 + case '"':
917 + {
918 + /* TODO Cupertino: Strings with spaces are truncated in the space */
919 + tree node;
920 + char *tmp_string =
921 + (char *) xmalloc (sizeof (char) * (strlen (argv[i]) - 1));
922 + strcpy (tmp_string, argv[i] + 1);
923 + tmp_string[strlen (argv[i]) - 2] = '\0';
924 +
925 + args_type = tree_cons (NULL_TREE, const_ptr_type_node, args_type);
926 + node = build_cst_string (tmp_string);
927 + args_call = tree_cons (NULL_TREE, node, args_call);
928 + }
929 + break;
930 + default:
931 + if (argv[i][0] >= '0' && argv[i][0] <= '9')
932 + {
933 + int tmp_num;
934 + tree node;
935 + sscanf (argv[i], "%d", &tmp_num);
936 + args_type = tree_cons (NULL_TREE, intSI_type_node, args_type);
937 + node = build_int_cst (intSI_type_node, tmp_num);
938 + args_call = tree_cons (NULL_TREE, node, args_call);
939 + }
940 + else
941 + gcc_assert (0);
942 + break;
943 + }
944 + }
945 + func_type = build_function_type (void_type_node, args_type);
946 + *func_decl = build_fn_decl (argv[0], func_type);
947 +
948 + func_node = cgraph_node (*func_decl);
949 + cgraph_mark_needed_node (func_node);
950 +
951 + *func_call = build_function_call_expr (*func_decl, args_call);
952 +}
953 +
954 +static tree
955 +get_arguments (tree tree_list)
956 +{
957 + tree args = NULL_TREE;
958 +
959 + while (tree_list)
960 + {
961 + args = tree_cons (NULL_TREE, tree_list, args);
962 + tree_list = TREE_CHAIN (tree_list);
963 + }
964 +
965 + return nreverse (args);
966 +}
967 +
968 +static inline bool
969 +is_it_main (struct cgraph_node *cg_func)
970 +{
971 + if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (cg_func->decl)), "MAIN__"))
972 + return true;
973 + if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (cg_func->decl)), "main"))
974 + return true;
975 +
976 + return false;
977 +}
978 +
979 +static bool
980 +is_it_clonable (struct cgraph_node *cg_func)
981 +{
982 + tree decl = cg_func->decl;
983 +
984 + /* TODO Cupertino : Are this enough */
985 + if (cg_func->global.inlined_to)
986 + return false;
987 +
988 + if (is_it_main (cg_func))
989 + return false;
990 +
991 + if (cgraph_function_body_availability (cg_func) == AVAIL_NOT_AVAILABLE)
992 + return false;
993 +
994 + if (flags_from_decl_or_type (decl) & ECF_NORETURN)
995 + return false;
996 +
997 + /* ??? Mismatch between the returned type and the result declaration. */
998 + if (TREE_TYPE (TREE_TYPE (decl)) != TREE_TYPE (DECL_RESULT (decl)))
999 + return false;
1000 +
1001 + return true;
1002 +}
1003 +
1004 +static void
1005 +add_timer_init (struct cgraph_node *cg_func)
1006 +{
1007 + tree decl = cg_func->decl;
1008 + tree ftype = build_function_type (void_type_node, void_list_node);
1009 + tree func_decl = build_fn_decl ("fapi_init", ftype);
1010 + tree call_expr = build_function_call_expr (func_decl, NULL_TREE);
1011 + struct function *func = DECL_STRUCT_FUNCTION (decl);
1012 + basic_block bb = ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->next_bb;
1013 + block_stmt_iterator bsi = bsi_start (bb);
1014 +
1015 + bsi_insert_before (&bsi, call_expr, BSI_SAME_STMT);
1016 + cgraph_create_edge (cg_func, cgraph_node (func_decl), call_expr,
1017 + bb->count, CGRAPH_FREQ_MAX, bb->loop_depth);
1018 +}
1019 +
1020 +static void
1021 +add_timer_fini (struct cgraph_node *cg_func)
1022 +{
1023 + edge e;
1024 + edge_iterator ei;
1025 + tree decl = cg_func->decl;
1026 + tree ftype = build_function_type (void_type_node, void_list_node);
1027 + tree func_decl = build_fn_decl ("fapi_fini", ftype);
1028 + tree call_expr = build_function_call_expr (func_decl, NULL_TREE);
1029 + struct function *func = DECL_STRUCT_FUNCTION (decl);
1030 +
1031 + FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FUNCTION (func)->preds)
1032 + {
1033 + block_stmt_iterator bsi = bsi_last (e->src);
1034 +
1035 + if (TREE_CODE (bsi_stmt (bsi)) == RETURN_EXPR)
1036 + bsi_insert_before (&bsi, call_expr, BSI_SAME_STMT);
1037 + else
1038 + bsi_insert_after (&bsi, call_expr, BSI_SAME_STMT);
1039 +
1040 + cgraph_create_edge (cg_func, cgraph_node (func_decl), call_expr,
1041 + e->src->count, CGRAPH_FREQ_MAX,
1042 + e->src->loop_depth);
1043 + }
1044 +}
1045 +
1046 +static void
1047 +add_timer_to_func (struct cgraph_node *cg_func, int id, bool is_clone)
1048 +{
1049 + tree func_decl, func_expr;
1050 + basic_block bb;
1051 + block_stmt_iterator bsi;
1052 + char *format;
1053 + tree decl = cg_func->decl;
1054 + struct function *func = DECL_STRUCT_FUNCTION (decl);
1055 +
1056 + format = getenv ("GCC_ADAPT_START");
1057 + if (format != NULL)
1058 + {
1059 + build_function_and_call (format, id, cg_func, &func_decl, &func_expr,
1060 + is_clone, NULL_TREE);
1061 +
1062 + bb = ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->next_bb;
1063 + bsi = bsi_start (bb);
1064 + bsi_insert_before (&bsi, func_expr, BSI_SAME_STMT);
1065 +
1066 + cgraph_create_edge (cg_func, cgraph_node (func_decl), func_expr,
1067 + bb->count, CGRAPH_FREQ_MAX, bb->loop_depth);
1068 + }
1069 +
1070 + format = getenv ("GCC_ADAPT_STOP");
1071 + if (format != NULL)
1072 + {
1073 + edge e;
1074 + edge_iterator ei;
1075 +
1076 + build_function_and_call (format, id, cg_func, &func_decl, &func_expr,
1077 + is_clone, NULL_TREE);
1078 +
1079 + FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FUNCTION (func)->preds)
1080 + {
1081 + bsi = bsi_last (e->src);
1082 + if (TREE_CODE (bsi_stmt (bsi)) == RETURN_EXPR)
1083 + bsi_insert_before (&bsi, func_expr, BSI_SAME_STMT);
1084 + else
1085 + bsi_insert_after (&bsi, func_expr, BSI_SAME_STMT);
1086 +
1087 + cgraph_create_edge (cg_func, cgraph_node (func_decl), func_expr,
1088 + e->src->count, CGRAPH_FREQ_MAX,
1089 + e->src->loop_depth);
1090 + }
1091 + }
1092 +}
1093 +
1094 +static void
1095 +add_call_to_clone (struct cgraph_node *orig, struct cgraph_node *clone)
1096 +{
1097 + tree decl;
1098 + tree
1099 + body_label, body_label_expr,
1100 + call_label, call_label_expr,
1101 + select, select_expr, cond_expr;
1102 + basic_block entry, call_block, body_block;
1103 + edge call_edge, body_edge, e;
1104 + edge_iterator ei;
1105 + block_stmt_iterator bsi;
1106 + struct function *func;
1107 + struct cgraph_edge *cge;
1108 +
1109 + decl = orig->decl;
1110 + func = DECL_STRUCT_FUNCTION (decl);
1111 +
1112 + if (DECL_SAVED_TREE (decl) != NULL)
1113 + {
1114 + bool removed;
1115 + basic_block first_bb = ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->next_bb;
1116 +
1117 + struct cgraph_node *select_node;
1118 + tree ftype = build_function_type (unsigned_type_node, void_list_node);
1119 + tree select_func = build_fn_decl ("fapi_select", ftype);
1120 + tree select_call = build_function_call_expr (select_func, NULL_TREE);
1121 + tree args = get_arguments (DECL_ARGUMENTS (decl));
1122 + tree clone_stmt = build_function_call_expr (clone->decl, args);
1123 + tree return_stmt;
1124 +
1125 + if (0)
1126 + {
1127 + tree last;
1128 + basic_block return_bb;
1129 + edge_iterator iter = ei_start (EXIT_BLOCK_PTR_FOR_FUNCTION (func)->preds);
1130 + edge exit;
1131 +
1132 + ei_cond (iter, &exit);
1133 + return_bb = exit->src;
1134 + last = last_stmt (return_bb);
1135 +
1136 + gcc_assert (TREE_CODE (last) == RETURN_EXPR);
1137 +
1138 + /*
1139 + return_stmt = copy_node (last);
1140 + modify = TREE_OPERAND (return_stmt, 0);
1141 + result = GIMPLE_STMT_OPERAND (modify, 0);
1142 + type = TREE_TYPE (result);
1143 + */
1144 + }
1145 +
1146 +
1147 + if (TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
1148 + {
1149 + tree return_var = create_tmp_var (TREE_TYPE (DECL_RESULT (decl)), "ret");
1150 +
1151 + DECL_CONTEXT (return_var) = decl;
1152 + clone_stmt = build_gimple_modify_stmt (return_var, clone_stmt);
1153 + return_stmt = build_gimple_modify_stmt (DECL_RESULT (decl), return_var);
1154 + return_stmt = build1 (RETURN_EXPR, void_type_node, return_stmt);
1155 + }
1156 + else
1157 + return_stmt = build1 (RETURN_EXPR, void_type_node, NULL_TREE);
1158 +
1159 + body_label = create_artificial_label ();
1160 + DECL_CONTEXT (body_label) = decl;
1161 + body_label_expr = build1 (LABEL_EXPR, void_type_node, body_label);
1162 +
1163 + call_label = create_artificial_label ();
1164 + DECL_CONTEXT (call_label) = decl;
1165 + call_label_expr = build1 (LABEL_EXPR, void_type_node, call_label);
1166 +
1167 +
1168 +
1169 + select = create_tmp_var (unsigned_type_node, "select");
1170 + select_expr = build_gimple_modify_stmt (select, select_call);
1171 +
1172 + DECL_EXTERNAL (select_func) = 1;
1173 + TREE_PUBLIC (select_func) = 1;
1174 +
1175 + select_node = cgraph_node (select_func);
1176 + cgraph_mark_needed_node (select_node);
1177 + select_node->local.externally_visible = 1;
1178 + select_node->local.local = 0;
1179 +
1180 + cgraph_create_edge (orig, select_node, select_expr, first_bb->count,
1181 + CGRAPH_FREQ_MAX, first_bb->loop_depth);
1182 + cgraph_mark_needed_node (select_node);
1183 +
1184 +
1185 +
1186 + select = build2 (EQ_EXPR, boolean_type_node, select, integer_zero_node);
1187 +
1188 + cond_expr = build3 (COND_EXPR, void_type_node, select, NULL_TREE,
1189 + NULL_TREE);
1190 +
1191 + bsi = bsi_start (first_bb);
1192 + bsi_insert_before (&bsi, select_expr, BSI_SAME_STMT);
1193 + bsi_insert_before (&bsi, cond_expr, BSI_SAME_STMT);
1194 +
1195 + bsi_insert_before (&bsi, call_label_expr, BSI_SAME_STMT);
1196 +
1197 + bsi_insert_before (&bsi, clone_stmt, BSI_SAME_STMT);
1198 + SET_EXPR_LOCUS (clone_stmt, EXPR_LOCUS (first_stmt (first_bb)));
1199 + TREE_BLOCK (clone_stmt) = TREE_BLOCK (first_stmt (first_bb));
1200 +
1201 + bsi_insert_before (&bsi, return_stmt, BSI_SAME_STMT);
1202 + bsi_insert_before (&bsi, body_label_expr, BSI_SAME_STMT);
1203 +
1204 + /* CFG corrections. */
1205 +
1206 + bsi = bsi_start (first_bb);
1207 + entry = bb_for_stmt (bsi_stmt (bsi));
1208 +
1209 + call_edge = split_block (entry, cond_expr);
1210 + call_block = call_edge->dest;
1211 +
1212 + body_edge = split_block (call_block, return_stmt);
1213 + body_block = body_edge->dest;
1214 +
1215 + /* Redirect incomming edges from entry to body_block */
1216 + removed = true;
1217 + while (removed)
1218 + {
1219 + removed = false;
1220 + FOR_EACH_EDGE (e, ei, entry->preds)
1221 + {
1222 + if (e->src != ENTRY_BLOCK_PTR_FOR_FUNCTION (func))
1223 + {
1224 + make_edge (e->src, body_block, e->flags);
1225 + remove_edge (e);
1226 + removed = true;
1227 + break;
1228 + }
1229 + }
1230 + }
1231 +
1232 + entry->flags |= BB_REACHABLE;
1233 + call_block->flags |= BB_REACHABLE;
1234 + body_block->flags |= BB_REACHABLE;
1235 +
1236 + remove_edge (body_edge);
1237 + body_edge =
1238 + make_edge (entry, body_block, EDGE_FALSE_VALUE | EDGE_EXECUTABLE);
1239 + call_edge->flags |= EDGE_TRUE_VALUE | EDGE_EXECUTABLE;
1240 + make_edge (call_block, EXIT_BLOCK_PTR, 0);
1241 +
1242 + body_edge->flags &= ~EDGE_FALLTHRU;
1243 + call_edge->flags &= ~EDGE_FALLTHRU;
1244 +
1245 + entry->flags |= BB_DISABLE_SCHEDULE;
1246 + call_block->flags |= BB_DISABLE_SCHEDULE;
1247 + body_block->flags |= BB_DISABLE_SCHEDULE;
1248 +
1249 + update_stmt (clone_stmt);
1250 + update_stmt (return_stmt);
1251 + update_stmt (body_label_expr);
1252 + update_stmt (call_label_expr);
1253 + update_stmt (cond_expr);
1254 + update_stmt (select_expr);
1255 +
1256 + /* CGRAPH corrections. */
1257 + cge = cgraph_create_edge (orig, cgraph_node (clone->decl), clone_stmt,
1258 + first_bb->count, CGRAPH_FREQ_MAX, first_bb->loop_depth);
1259 + cge->inline_failed = "Clonned function";
1260 + cgraph_mark_needed_node (cgraph_node (clone->decl));
1261 + }
1262 +}
1263 +
1264 +
1265 +static unsigned int
1266 +exec_adaptation (void)
1267 +{
1268 + struct cgraph_node *node;
1269 + struct function *saved_cfun, *func;
1270 +
1271 + /* Finding all the ids necessary to have a reliable id_count */
1272 + for (node = cgraph_nodes; node; node = node->next)
1273 + {
1274 + const char *func_name = IDENTIFIER_POINTER (DECL_NAME (node->decl));
1275 + int func_name_size = strlen (func_name);
1276 +
1277 + if (is_it_clonable (node)
1278 + && !(func_name_size > 6
1279 + && !strcmp (func_name + (func_name_size - 6), "_clone")))
1280 + {
1281 + printf ("name is %s\n", func_name);
1282 + get_id (func_name);
1283 + }
1284 + }
1285 +
1286 + saved_cfun = cfun;
1287 +
1288 + /* Perform cloning and adaptation to functions */
1289 + for (node = cgraph_nodes; node; node = node->next)
1290 + {
1291 + func = DECL_STRUCT_FUNCTION (node->decl);
1292 + cfun = func;
1293 +
1294 + if (is_it_clonable (node))
1295 + {
1296 + struct cgraph_node *clone_node = NULL;
1297 + int id;
1298 + const char *node_name = IDENTIFIER_POINTER (DECL_NAME (node->decl));
1299 +
1300 + if (!strcmp (node_name + (strlen (node_name) - 6), "_clone"))
1301 + {
1302 + printf ("%s is a virtual clone function\n", node_name);
1303 + continue;
1304 + }
1305 +
1306 + id = get_id (node_name);
1307 +
1308 + cfun = DECL_STRUCT_FUNCTION (node->decl);
1309 +
1310 + add_timer_to_func (node, id, false);
1311 +
1312 + printf ("Cloning function %s\n", node_name);
1313 +
1314 + clone_node = cgraph_function_versioning (node, NULL, NULL);
1315 +
1316 + /* The cloned function should not be inlined. */
1317 + clone_node->local.inlinable = false;
1318 +
1319 + if (1)
1320 + {
1321 + char *output_name = NULL;
1322 +
1323 + /* Generate a new name for the new version. */
1324 + output_name =
1325 + (char *) alloca (strlen (IDENTIFIER_POINTER (DECL_NAME (node->decl))) + 64);
1326 + sprintf (output_name, "%s_clone",
1327 + IDENTIFIER_POINTER (DECL_NAME (node->decl)));
1328 +
1329 + DECL_NAME (clone_node->decl) = get_identifier (output_name);
1330 +
1331 + /* Create a new SYMBOL_REF rtx for the new name. */
1332 + if (DECL_RTL (node->decl) != NULL)
1333 + {
1334 + SET_DECL_RTL (clone_node->decl, copy_rtx (DECL_RTL (node->decl)));
1335 + XEXP (DECL_RTL (clone_node->decl), 0) =
1336 + gen_rtx_SYMBOL_REF (GET_MODE (XEXP (DECL_RTL (node->decl), 0)),
1337 + IDENTIFIER_POINTER (DECL_NAME (clone_node->decl)));
1338 + }
1339 + }
1340 +
1341 + add_timer_to_func (clone_node, id, true);
1342 + add_call_to_clone (node, clone_node);
1343 + }
1344 + else if (is_it_main (node))
1345 + {
1346 + add_timer_init (node);
1347 + add_timer_fini (node);
1348 + }
1349 + }
1350 +
1351 + cfun = saved_cfun;
1352 + return 0;
1353 +}
1354 +
1355 +static bool
1356 +gate_adaptation (void)
1357 +{
1358 + return (flag_api_clone_functions || flag_api_virtual_cloning);
1359 +}
1360 +
1361 +struct tree_opt_pass pass_adaptation = {
1362 + "clone_functions", /* name */
1363 + gate_adaptation, /* gate */
1364 + exec_adaptation, /* execute */
1365 + NULL, /* sub */
1366 + NULL, /* next */
1367 + 0, /* static_pass_number */
1368 + 0, /* tv_id */
1369 + 0, /* properties_required */
1370 + 0, /* properties_provided */
1371 + 0, /* properties_destroyed */
1372 + 0, /* todo_flags_start */
1373 + TODO_dump_cgraph | TODO_verify_flow, /* todo_flags_finish */
1374 + 0 /* letter */
1375 +};
1376 +
1377 +int
1378 +is_adapt_functions_needed (void)
1379 +{
1380 + char *opts;
1381 +
1382 + opts = getenv ("GCC_ADAPT_OPT");
1383 + return (opts != NULL);
1384 +}
1385 +
1386 +/* Function for parsing adaptation arguments and desirable functions. */
1387 +static char **
1388 +parse_arguments (char *text, unsigned int *argc)
1389 +{
1390 + unsigned int i, size;
1391 + char **argv;
1392 + char *start;
1393 +
1394 + *argc = 0;
1395 + if (text[0] != 0)
1396 + *argc = 2;
1397 +
1398 + size = strlen (text);
1399 + for (i = 0; i < size; i++)
1400 + {
1401 + if (text[i] == ' ')
1402 + {
1403 + text[i] = '\0';
1404 + (*argc)++;
1405 + }
1406 + }
1407 +
1408 + argv = (char **) xmalloc (sizeof (char *) * (*argc));
1409 +
1410 + start = text;
1411 + for (i = 1; i < (*argc); i++)
1412 + {
1413 + argv[i] = start;
1414 + start += (strlen (start) + 1);
1415 + }
1416 +
1417 + return argv;
1418 +}
1419 +
1420 +/* Adaptation initializitation.
1421 + * It reads adaptation arguments from the environment variable and
1422 + * save them separately. */
1423 +void
1424 +init_adaptation (void)
1425 +{
1426 + char *ptr;
1427 +
1428 + save_options ();
1429 + ptr = getenv ("GCC_ADAPT_OPT");
1430 +
1431 + if (ptr)
1432 + {
1433 + unsigned int argc;
1434 + char **argv = parse_arguments (ptr, &argc);
1435 +
1436 + decode_options (argc, (const char **) argv);
1437 + }
1438 + save_new_options ();
1439 + restore_options ();
1440 +
1441 +/* dump_options_copy(); */
1442 +}
1443 +
1444 +/* Verify if adaptation is enabled for function */
1445 +
1446 +static int
1447 +is_function_adaptable (char *name)
1448 +{
1449 + char *ptr;
1450 + unsigned int i;
1451 + static char **funcs = NULL;
1452 + static unsigned int funcs_count = 0;
1453 +
1454 + const char *func_name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
1455 +
1456 + if(strlen(func_name) > 6 && !strcmp ("_clone", func_name + (strlen(func_name) - 6)))
1457 + {
1458 + return true;
1459 + }
1460 +
1461 + fprintf(stderr, "Cheking func %s\n", IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
1462 +
1463 + if (funcs == NULL && (ptr = getenv ("GCC_ADAPT_FUNCS")) != NULL)
1464 + {
1465 + fprintf(stderr, "Parsing funcs\n");
1466 + funcs = parse_arguments (ptr, &funcs_count);
1467 + }
1468 +
1469 + if (funcs != NULL)
1470 + for (i = 1; i < funcs_count; i++)
1471 + if (!strcmp (funcs[i], name))
1472 + {
1473 + fprintf(stderr, "PASSED\n");
1474 + return true;
1475 + }
1476 +
1477 + return false;
1478 +}
1479 +
1480 +/* Pass responsible for setting function adaptation flags. */
1481 +
1482 +static bool
1483 +gate_set_specific_options (void)
1484 +{
1485 + dump_flags_to_csv ();
1486 + return is_adapt_functions_needed ()
1487 + && is_function_adaptable ((char *)
1488 + IDENTIFIER_POINTER (DECL_NAME
1489 + (current_function_decl)));
1490 +}
1491 +
1492 +static unsigned int
1493 +exec_set_specific_options (void)
1494 +{
1495 + fprintf(stderr, "Setting flags to func %s\n", IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
1496 + save_options ();
1497 + set_new_options ();
1498 + dump_flags_to_csv ();
1499 +
1500 + return 0;
1501 +}
1502 +
1503 +struct tree_opt_pass pass_set_specific_options = {
1504 + "set_specific_options", /* name */
1505 + gate_set_specific_options, /* gate */
1506 + exec_set_specific_options, /* execute */
1507 + NULL, /* sub */
1508 + NULL, /* next */
1509 + 0, /* static_pass_number */
1510 + 0, /* tv_id */
1511 + 0, /* properties_required */
1512 + 0, /* properties_provided */
1513 + 0, /* properties_destroyed */
1514 + 0, /* todo_flags_start */
1515 + 0, /* */
1516 + 0 /* letter */
1517 +};
1518 +
1519 +/* Pass responsible for restoring original compilation flags. */
1520 +
1521 +static bool
1522 +gate_restore_options (void)
1523 +{
1524 + return is_adapt_functions_needed ()
1525 + && is_function_adaptable ((char *)
1526 + IDENTIFIER_POINTER (DECL_NAME
1527 + (current_function_decl)));
1528 +}
1529 +
1530 +static unsigned int
1531 +exec_restore_options (void)
1532 +{
1533 + restore_options ();
1534 +
1535 + return 0;
1536 +}
1537 +
1538 +struct tree_opt_pass pass_restore_options = {
1539 + "restore_options", /* name */
1540 + gate_restore_options, /* gate */
1541 + exec_restore_options, /* execute */
1542 + NULL, /* sub */
1543 + NULL, /* next */
1544 + 0, /* static_pass_number */
1545 + 0, /* tv_id */
1546 + 0, /* properties_required */
1547 + 0, /* properties_provided */
1548 + 0, /* properties_destroyed */
1549 + 0, /* todo_flags_start */
1550 + 0, /* */
1551 + 0 /* letter */
1552 +};
1553 Index: gcc/tree-flow.h
1554 ===================================================================
1555 --- gcc/tree-flow.h (revision 9015)
1556 +++ gcc/tree-flow.h (working copy)
1557 @@ -1181,5 +1181,7 @@
1558 void swap_tree_operands (tree, tree *, tree *);
1559
1560 int least_common_multiple (int, int);
1561 +void dump_cfg_to_dot (FILE *, struct function *);
1562 +void draw_cfg (struct function *);
1563
1564 #endif /* _TREE_FLOW_H */
1565 Index: gcc/Makefile.in
1566 ===================================================================
1567 --- gcc/Makefile.in (revision 9015)
1568 +++ gcc/Makefile.in (working copy)
1569 @@ -1028,6 +1028,7 @@
1570 explow.o \
1571 expmed.o \
1572 expr.o \
1573 + fapi-tools.o \
1574 final.o \
1575 fold-const.o \
1576 function.o \
1577 @@ -2251,6 +2252,8 @@
1578 tree-object-size.o: tree-object-size.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
1579 $(TM_H) $(TREE_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) tree-pass.h \
1580 tree-ssa-propagate.h
1581 +fapi-tools.o : $(CONFIG_H) $(SYSTEM_H) coretypes.h tree-pass.h \
1582 + $(FLAGS_H) $(CGRAPH_H) $(TREE_H) $(TARGET_H) ipa-prop.h opts.h
1583 tree-gimple.o : tree-gimple.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(EXPR_H) \
1584 $(RTL_H) $(TREE_GIMPLE_H) $(TM_H) coretypes.h bitmap.h $(GGC_H) \
1585 output.h $(TREE_FLOW_H)
1586 Index: gcc/passes.c
1587 ===================================================================
1588 --- gcc/passes.c (revision 9015)
1589 +++ gcc/passes.c (working copy)
1590 @@ -503,6 +503,7 @@
1591 NEXT_PASS (pass_inline_parameters);
1592 NEXT_PASS (pass_rebuild_cgraph_edges);
1593 }
1594 + NEXT_PASS (pass_adaptation);
1595 NEXT_PASS (pass_early_local_passes);
1596 {
1597 struct tree_opt_pass **p = &pass_early_local_passes.sub;
1598 @@ -547,6 +548,7 @@
1599 /* These passes are run after IPA passes on every function that is being
1600 output to the assembler file. */
1601 p = &all_passes;
1602 + NEXT_PASS (pass_set_specific_options);
1603 NEXT_PASS (pass_apply_inline);
1604 NEXT_PASS (pass_all_optimizations);
1605 {
1606 @@ -790,6 +792,7 @@
1607 }
1608 }
1609 NEXT_PASS (pass_clean_state);
1610 + NEXT_PASS (pass_restore_options);
1611 *p = NULL;
1612
1613 #undef NEXT_PASS
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.