[PATCH] Per-function flag setting

Zdenek Dvorak rakdver@atrey.karlin.mff.cuni.cz
Tue Jun 3 09:00:00 GMT 2003


Hello,

this patch enables you to change optimization flags on per-function
basis, by attaching
__attribute__ ((options ("whatever", "flags", "you", "want")))
to it. It is quite simple and does no sanity checking at all, but I
think it might be quite useful for debugging (locating which function
is misscompiled).

Zdenek

	* c-common.c (handle_options_attribute): New static function.
	(c_common_attribute_table): Add options attribute.
	* toplev.c (save_flag_values, restore_flag_values,
	process_local_options): New static functions.
	(rest_of_compilation): Set per-function flags from options attribute.
	(parse_options_and_default_flags): Split parts into ...
	(set_optimization_level_defaults, decode_flags): ... new functions.

Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.417
diff -c -3 -p -r1.417 c-common.c
*** c-common.c	19 May 2003 19:19:42 -0000	1.417
--- c-common.c	2 Jun 2003 15:17:48 -0000
*************** static tree handle_vector_size_attribute
*** 790,795 ****
--- 790,797 ----
  						  bool *));
  static tree handle_nonnull_attribute	PARAMS ((tree *, tree, tree, int,
  						 bool *));
+ static tree handle_options_attribute	PARAMS ((tree *, tree, tree, int,
+ 						 bool *));
  static tree handle_nothrow_attribute	PARAMS ((tree *, tree, tree, int,
  						 bool *));
  static tree vector_size_helper PARAMS ((tree, tree));
*************** const struct attribute_spec c_common_att
*** 865,870 ****
--- 867,874 ----
  			      handle_tls_model_attribute },
    { "nonnull",                0, -1, false, true, true,
  			      handle_nonnull_attribute },
+   { "options",                1, -1, true,  false, false,
+ 			      handle_options_attribute },
    { "nothrow",                0, 0, true,  false, false,
  			      handle_nothrow_attribute },
    { "may_alias",	      0, 0, false, true, false, NULL },
*************** handle_nonnull_attribute (node, name, ar
*** 5964,5969 ****
--- 5968,6007 ----
  	      return NULL_TREE;
  	    }
  	}
+     }
+ 
+   return NULL_TREE;
+ }
+ 
+ /* Handle the "options" attribute.  */
+ static tree
+ handle_options_attribute (node, name, args, flags, no_add_attrs)
+      tree *node;
+      tree name ATTRIBUTE_UNUSED;
+      tree args;
+      int flags ATTRIBUTE_UNUSED;
+      bool *no_add_attrs ATTRIBUTE_UNUSED;
+ {
+   tree decl = *node;
+ 
+   if (TREE_CODE (decl) != FUNCTION_DECL)
+     {
+       error_with_decl (decl,
+ 		       "options attribute can only be specified for functions");
+       *no_add_attrs = true;
+       return NULL_TREE;
+     }
+     
+   while (args)
+     {
+       if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+ 	{
+ 	  error_with_decl (decl,
+ 			   "argument to options attribute must be a string");
+ 	  *no_add_attrs = true;
+ 	  return NULL_TREE;
+ 	}
+       args = TREE_CHAIN (args);
      }
  
    return NULL_TREE;
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.762
diff -c -3 -p -r1.762 toplev.c
*** toplev.c	2 Jun 2003 05:05:33 -0000	1.762
--- toplev.c	2 Jun 2003 15:17:48 -0000
*************** extern void reg_alloc (void);
*** 105,110 ****
--- 105,115 ----
  static void general_init (char *);
  static void parse_options_and_default_flags (int, char **);
  static void do_compile (void);
+ static int *save_flag_values (void);
+ static void restore_flag_values (int *);
+ static void process_local_options (tree);
+ static void set_optimization_level_defaults (int, char **);
+ static void decode_flags (int, char **);
  static void process_options (void);
  static void backend_init (void);
  static int lang_dependent_init (const char *);
*************** rest_of_compilation (tree decl)
*** 3465,3472 ****
--- 3470,3487 ----
  {
    rtx insns;
    int rebuild_label_notes_after_reload;
+   int *global_flags;
+   tree local_flags;
  
    timevar_push (TV_REST_OF_COMPILATION);
+   local_flags = lookup_attribute ("options", DECL_ATTRIBUTES (decl));
+   if (local_flags)
+     {
+       global_flags = save_flag_values ();
+       process_local_options (local_flags);
+     }
+   else
+     global_flags = NULL;
  
    /* Now that we're out of the frontend, we shouldn't have any more
       CONCATs anywhere.  */
*************** rest_of_compilation (tree decl)
*** 4002,4007 ****
--- 4017,4027 ----
  
    ggc_collect ();
  
+   if (global_flags)
+     {
+       restore_flag_values (global_flags);
+       free (global_flags);
+     }
    timevar_pop (TV_REST_OF_COMPILATION);
  }
  
*************** general_init (char *argv0)
*** 5118,5152 ****
    init_ttree ();
  }
  
! /* Parse command line options and set default flag values, called
!    after language-independent option-independent initialization.  Do
!    minimal options processing.  Outputting diagnostics is OK, but GC
!    and identifier hashtables etc. are not initialized yet.
! 
!    Return nonzero to suppress compiler back end initialization.  */
  static void
! parse_options_and_default_flags (int argc, char **argv)
  {
    int i;
  
-   /* Save in case md file wants to emit args as a comment.  */
-   save_argc = argc;
-   save_argv = argv;
- 
-   /* Initialize register usage now so switches may override.  */
-   init_reg_sets ();
- 
-   /* Register the language-independent parameters.  */
-   add_params (lang_independent_params, LAST_PARAM);
- 
-   /* This must be done after add_params but before argument processing.  */
-   init_ggc_heuristics();
- 
-   /* Perform language-specific options initialization.  */
-   (*lang_hooks.init_options) ();
- 
-   /* Scan to see what optimization level has been specified.  That will
-      determine the default value of many flags.  */
    for (i = 1; i < argc; i++)
      {
        if (!strcmp (argv[i], "-O"))
--- 5138,5150 ----
    init_ttree ();
  }
  
! /* Scan command line options for optimization level and set default values
!    of flags accordingly.  */
  static void
! set_optimization_level_defaults (int argc, char **argv)
  {
    int i;
  
    for (i = 1; i < argc; i++)
      {
        if (!strcmp (argv[i], "-O"))
*************** parse_options_and_default_flags (int arg
*** 5272,5279 ****
    /* Allow default optimizations to be specified on a per-machine basis.  */
    OPTIMIZATION_OPTIONS (optimize, optimize_size);
  #endif
  
-   /* Perform normal command line switch decoding.  */
    for (i = 1; i < argc;)
      {
        int lang_processed;
--- 5270,5283 ----
    /* Allow default optimizations to be specified on a per-machine basis.  */
    OPTIMIZATION_OPTIONS (optimize, optimize_size);
  #endif
+ }
+ 
+ /* Scan command line options and set the values of flags accordingly.  */
+ static void
+ decode_flags (int argc, char **argv)
+ {
+   int i;
  
    for (i = 1; i < argc;)
      {
        int lang_processed;
*************** parse_options_and_default_flags (int arg
*** 5366,5371 ****
--- 5370,5408 ----
      flag_really_no_inline = flag_no_inline;
  }
  
+ /* Parse command line options and set default flag values, called
+    after language-independent option-independent initialization.  Do
+    minimal options processing.  Outputting diagnostics is OK, but GC
+    and identifier hashtables etc. are not initialized yet.
+ 
+    Return nonzero to suppress compiler back end initialization.  */
+ static void
+ parse_options_and_default_flags (int argc, char **argv)
+ {
+   /* Save in case md file wants to emit args as a comment.  */
+   save_argc = argc;
+   save_argv = argv;
+ 
+   /* Initialize register usage now so switches may override.  */
+   init_reg_sets ();
+ 
+   /* Register the language-independent parameters.  */
+   add_params (lang_independent_params, LAST_PARAM);
+ 
+   /* This must be done after add_params but before argument processing.  */
+   init_ggc_heuristics();
+ 
+   /* Perform language-specific options initialization.  */
+   (*lang_hooks.init_options) ();
+ 
+   /* Scan to see what optimization level has been specified and set
+      the default value of flags.  */
+   set_optimization_level_defaults (argc, argv);
+ 
+   /* Perform normal command line switch decoding.  */
+   decode_flags (argc, argv);
+ }
+ 
  /* Process the options that have been parsed.  */
  static void
  process_options (void)
*************** process_options (void)
*** 5575,5580 ****
--- 5612,5677 ----
      /* The presence of IEEE signaling NaNs, implies all math can trap.  */
      if (flag_signaling_nans)
        flag_trapping_math = 1;
+ }
+ 
+ /* Save the values of flags.  */
+ static int *
+ save_flag_values ()
+ {
+   int *storage = xmalloc (sizeof (int) * (LAST_PARAM
+ 					  + ARRAY_SIZE (f_options)
+ 					  + ARRAY_SIZE (W_options)));
+   unsigned i, b;
+ 
+   for (i = 0, b = 0; i < LAST_PARAM; i++, b++)
+     storage[b] = compiler_params[i].value;
+ 
+   for (i = 0; i < ARRAY_SIZE (f_options); i++, b++)
+     storage[b] = *f_options[i].variable;
+ 
+   for (i = 0; i < ARRAY_SIZE (W_options); i++, b++)
+     storage[b] = *W_options[i].variable;
+ 
+   return storage;
+ }
+ 
+ /* Restore the values of flags.  */
+ static void
+ restore_flag_values (storage)
+      int *storage;
+ {
+   unsigned i, b;
+ 
+   for (i = 0, b = 0; i < LAST_PARAM; i++, b++)
+     compiler_params[i].value = storage[b];
+ 
+   for (i = 0; i < ARRAY_SIZE (f_options); i++, b++)
+     *f_options[i].variable = storage[b];
+ 
+   for (i = 0; i < ARRAY_SIZE (W_options); i++, b++)
+     *W_options[i].variable = storage[b];
+ }
+ 
+ /* Process OPTIONS passed through "options" attribute.  */
+ static void
+ process_local_options (options)
+      tree options;
+ {
+   char **argv;
+   int argc, i;
+ 
+   options = TREE_VALUE (options);
+   argc = list_length (options) + 1;
+   argv = xmalloc (sizeof (char *) * argc);
+ 
+   argv[0] = NULL;
+   for (i = 1; i < argc; i++)
+     {
+       argv[i] = (char *) TREE_STRING_POINTER (TREE_VALUE (options));
+       options = TREE_CHAIN (options);
+     }
+   decode_flags (argc, argv);
+   free (argv);
  }
  
  /* Initialize the compiler back end.  */



More information about the Gcc-patches mailing list