This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH][ARM] Fix PR target/69245 Rewrite arm_set_current_function




On 01/26/2016 04:58 PM, Kyrill Tkachov wrote:
Hi Christian,

On 26/01/16 15:29, Christian Bruel wrote:

On 01/25/2016 05:37 PM, Kyrill Tkachov wrote:


So this is ok for trunk with the testcase changed as discussed above and using -O2
optimisation level and with a couple comment fixes below.

Hi Kyrill,

I realized afterwards that my implementation had a flaw with the handling of #pragma GCC reset. What happened is that when both old and new TREE_TARGET_OPTION are NULL, we didn't save_restore the globals flags, to save compute time. The
problem is that with #pragma GCC reset, we also fall into this situation, and exit without calling target_reeinit :-(

Handling this situation doesn't complicate the code much, because I factorized the calls to target_reeinit + restore_target_globals into a new function (save_restore_target_globals). This function is called from the pragma context when
resetting the state arm_reset_previous_fndecl to the default, and from arm_set_current_function when setting to a new target. This is only done when there is a change of the target flags, so no extra computing cost.

Same testing as with previous patch:
     arm-qemu/
     arm-qemu//-mfpu=neon-fp-armv8
     arm-qemu//-mfpu=neon

Still OK ?

+/* Restore the TREE_TARGET_GLOBALS from previous state, or save it.  */
+static void
+save_restore_target_globals (tree new_tree)
+{
+  /* If we have a previous state, use it.  */
+  if (TREE_TARGET_GLOBALS (new_tree))
+    restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
+  else if (new_tree == target_option_default_node)
+    restore_target_globals (&default_target_globals);
+  else
+    {
+      /* Call target_reinit and save the state for TARGET_GLOBALS.  */
+      TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
+    }
+
+  arm_option_params_internal ();
+}

Space before the function comment and signature.
what do you mean ? a new line between the comment and the function signature ? I usually mimic what's done in the other arm.c declarations, which sometimes have a new line, sometime not. It's not clear to me what's mandatory here, even in the other parts of the compiler.

  Also, you need to document what is the NEW_TREE
parameter.

   /* Invalidate arm_previous_fndecl.  */
   void
-arm_reset_previous_fndecl (void)
+arm_reset_previous_fndecl (tree new_tree)
   {
+  if (new_tree)
+    save_restore_target_globals (new_tree);
+
     arm_previous_fndecl = NULL_TREE;
   }

I'm a bit wary of complicating this function. Suddenly it doesn't just reset the previous fndecl
but also restores globals and can save stuff into its argument. It's suddenly not clear what it's
purpose is.
I think it would be clearer if you just added save_restore_target_globals to arm_protos.h and called
it explicitly from arm_pragma_target_parse when appropriate.

sure, like this one attached (sanity checked) ?



+
+  /* If nothing to do return. #pragma GCC reset or #pragma GCC pop to
+     the default have been handled by save_restore_target_globals from
+     arm_pragma_target_parse.  */

Two spaces between fullstop and "#pragma GCC".

thanks,

Christian

2016-01-20  Christian Bruel  <christian.bruel@st.com>

	PR target/69245
	* config/arm/arm-c.c (arm_pragma_target_parse): Add comments.
	Move arm_reset_previous_fndecl and set_target_option_current_node in
	the conditional part. Call save_restore_target_globals.
	* config/arm/arm.c (arm_set_current_function):
	Refactor to better support #pragma target and attribute mix.
	Call save_restore_target_globals.
	* config/arm/arm-protos.h (save_restore_target_globals): New function.

2016-01-20  Christian Bruel  <christian.bruel@st.com>

	PR target/69245
	* gcc.target/arm/pr69245.c: New test.

Index: gcc/config/arm/arm-c.c
===================================================================
--- gcc/config/arm/arm-c.c	(revision 232831)
+++ gcc/config/arm/arm-c.c	(working copy)
@@ -221,9 +221,6 @@ arm_pragma_target_parse (tree args, tree pop_targe
 	}
     }
 
-  target_option_current_node = cur_tree;
-  arm_reset_previous_fndecl ();
-
   /* Figure out the previous mode.  */
   prev_opt  = TREE_TARGET_OPTION (prev_tree);
   cur_opt   = TREE_TARGET_OPTION (cur_tree);
@@ -259,6 +256,18 @@ arm_pragma_target_parse (tree args, tree pop_targe
       arm_cpu_builtins (parse_in);
 
       cpp_opts->warn_unused_macros = saved_warn_unused_macros;
+
+      /* Make sure that target_reinit is called for next function, since
+	 TREE_TARGET_OPTION might change with the #pragma even if there is
+	 no target attribute attached to the function.  */
+      arm_reset_previous_fndecl ();
+
+      /* If going to the default mode, we restore the initial states.
+	 if cur_tree is a new target, states will be saved/restored on a per
+	 function basis in arm_set_current_function.  */
+      if (cur_tree == target_option_default_node)
+	save_restore_target_globals (cur_tree);
+
     }
 
   return true;
Index: gcc/config/arm/arm-protos.h
===================================================================
--- gcc/config/arm/arm-protos.h	(revision 232831)
+++ gcc/config/arm/arm-protos.h	(working copy)
@@ -332,6 +332,7 @@ extern bool arm_autoinc_modes_ok_p (machine_mode,
 extern void arm_emit_eabi_attribute (const char *, int, int);
 
 extern void arm_reset_previous_fndecl (void);
+extern void save_restore_target_globals (tree);
 
 /* Defined in gcc/common/config/arm-common.c.  */
 extern const char *arm_rewrite_selected_cpu (const char *name);
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	(revision 232831)
+++ gcc/config/arm/arm.c	(working copy)
@@ -3446,8 +3446,7 @@ arm_option_override (void)
 
   /* Save the initial options in case the user does function specific
      options.  */
-  target_option_default_node = target_option_current_node
-    = build_target_option_node (&global_options);
+  target_option_default_node = build_target_option_node (&global_options);
 
   /* Init initial mode for testing.  */
   thumb_flipper = TARGET_THUMB;
@@ -29746,7 +29745,27 @@ arm_is_constant_pool_ref (rtx x)
 /* Remember the last target of arm_set_current_function.  */
 static GTY(()) tree arm_previous_fndecl;
 
+/* Restore or save the TREE_TARGET_GLOBALS from or to NEW_TREE.  */
+
+void
+save_restore_target_globals (tree new_tree)
+{
+  /* If we have a previous state, use it.  */
+  if (TREE_TARGET_GLOBALS (new_tree))
+    restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
+  else if (new_tree == target_option_default_node)
+    restore_target_globals (&default_target_globals);
+  else
+    {
+      /* Call target_reinit and save the state for TARGET_GLOBALS.  */
+      TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
+    }
+
+  arm_option_params_internal ();
+}
+
 /* Invalidate arm_previous_fndecl.  */
+
 void
 arm_reset_previous_fndecl (void)
 {
@@ -29756,6 +29775,7 @@ arm_reset_previous_fndecl (void)
 /* Establish appropriate back-end context for processing the function
    FNDECL.  The argument might be NULL to indicate processing at top
    level, outside of any function scope.  */
+
 static void
 arm_set_current_function (tree fndecl)
 {
@@ -29768,38 +29788,23 @@ arm_set_current_function (tree fndecl)
 
   tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
 
-  arm_previous_fndecl = fndecl;
+  /* If current function has no attributes but previous one did,
+     use the default node."  */
+  if (! new_tree && old_tree)
+    new_tree = target_option_default_node;
+
+  /* If nothing to do return.  #pragma GCC reset or #pragma GCC pop to
+     the default have been handled by save_restore_target_globals from
+     arm_pragma_target_parse.  */
   if (old_tree == new_tree)
     return;
 
-  if (new_tree && new_tree != target_option_default_node)
-    {
-      cl_target_option_restore (&global_options,
-				TREE_TARGET_OPTION (new_tree));
+  arm_previous_fndecl = fndecl;
 
-      if (TREE_TARGET_GLOBALS (new_tree))
-	restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
-      else
-	TREE_TARGET_GLOBALS (new_tree)
-	  = save_target_globals_default_opts ();
-    }
+  /* First set the target options.  */
+  cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree));
 
-  else if (old_tree && old_tree != target_option_default_node)
-    {
-      new_tree = target_option_current_node;
-
-      cl_target_option_restore (&global_options,
-				TREE_TARGET_OPTION (new_tree));
-      if (TREE_TARGET_GLOBALS (new_tree))
-	restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
-      else if (new_tree == target_option_default_node)
-	restore_target_globals (&default_target_globals);
-      else
-	TREE_TARGET_GLOBALS (new_tree)
-	  = save_target_globals_default_opts ();
-    }
-
-  arm_option_params_internal ();
+  save_restore_target_globals (new_tree);
 }
 
 /* Implement TARGET_OPTION_PRINT.  */
Index: gcc/testsuite/gcc.target/arm/pr69245.c
===================================================================
--- gcc/testsuite/gcc.target/arm/pr69245.c	(revision 0)
+++ gcc/testsuite/gcc.target/arm/pr69245.c	(working copy)
@@ -0,0 +1,26 @@
+/* PR target/69245 */
+/* Test that pop_options restores the vfp fpu mode.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-require-effective-target arm_fp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_fp } */
+
+#pragma GCC target "fpu=vfp"
+
+#pragma GCC push_options
+#pragma GCC target "fpu=neon-vfpv4"
+int a, c, d;
+float b;
+static int fn1 ()
+{
+  return 0;
+}
+#pragma GCC pop_options
+
+void fn2 ()
+{
+  d = b * c + a;
+}
+
+/* { dg-final { scan-assembler-times "\.fpu vfp" 1 } } */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]