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.