gcc: remove unneeded global related to hot/cold partitioning
authorAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 16 Nov 2016 22:10:52 +0000 (22:10 +0000)
committerAndrew Burgess <aburgess@gcc.gnu.org>
Wed, 16 Nov 2016 22:10:52 +0000 (22:10 +0000)
The `user_defined_section_attribute' is used as part of the condition to
determine if GCC should partition blocks within a function into hot and
cold blocks.  This global is initially false, and is set to true from
within the file parse phase of GCC, as part of the attribute handling
hook.

The `user_defined_section_attribute' is reset to false as part of the
final pass of GCC.  However, the final pass is part of the optimisation
phase of the compiler, and so if at any point during the file parse
phase any function, or data, has a section attribute the global
`user_defined_section_attribute' will be set to true.

When GCC performs the block partitioning pass on the first function, if
`user_defined_section_attribute' is true then the function will not be
partitioned.  Notice though, that due to the above, whether we partition
this first function or not has nothing to do with whether the function
has a section attribute, instead, if any function or data in the parsed
file has a section attribute then we don't partition the first
function.

After performing (or not) the block partitioning pass on the first
function we perform the final pass on the first function, at which point
we reset `user_defined_section_attribute' to false.  As parsing is
complete by this point, we will never set
`user_defined_section_attribute' to true after that, and so all of the
following functions will have the partition blocks pass performed on
them, even if the function has a section attribute, and will not be
partitioned.

Luckily we don't end up partitioning functions that should not be
partitioned though.  Due to the way that functions are selected during
the assembler writing phase, if a function has a section attribute this
takes priority over any hot/cold block partitioning that has been done.

What we see from the above then is that the
`user_defined_section_attribute' mechanism is broken.  It was originally
created when GCC parsed, optimised, and generated assembler function at
a time.  Now that we deal with the whole file in one go, we need to
update the mechanism used to gate the block partitioning pass.

This patch does this by looking specifically for a section attribute on
the function DECL, which removes the need for a global variable, and
will work whether we parse the whole file in one go, or one function at
a time.

A few new tests have been added.  These check for the case where a
function is not partitioned when it could be.

gcc/ChangeLog:

* gcc/bb-reorder.c: Remove 'toplev.h' include.
(pass_partition_blocks::gate): No longer check
user_defined_section_attribute, instead check the function decl
for a section attribute.
* gcc/c-family/c-attribs.c (handle_section_attribute): No longer
set user_defined_section_attribute.
* gcc/final.c (rest_of_handle_final): Likewise.
* gcc/toplev.c: Remove definition of user_defined_section_attribute.
* gcc/toplev.h: Remove declaration of
user_defined_section_attribute.

gcc/testsuiteChangeLog:

* gcc.dg/tree-prof/section-attr-1.c: New file.
* gcc.dg/tree-prof/section-attr-2.c: New file.
* gcc.dg/tree-prof/section-attr-3.c: New file.

From-SVN: r242519

gcc/ChangeLog
gcc/bb-reorder.c
gcc/c-family/c-attribs.c
gcc/final.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c [new file with mode: 0644]
gcc/toplev.c
gcc/toplev.h

index 9b0462151fb7dcbb66913fb0287416cf6b630b27..bd70d4ea54d95e0454c86d369b680bf4c694e333 100644 (file)
@@ -1,3 +1,16 @@
+2016-11-16  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gcc/bb-reorder.c: Remove 'toplev.h' include.
+       (pass_partition_blocks::gate): No longer check
+       user_defined_section_attribute, instead check the function decl
+       for a section attribute.
+       * gcc/c-family/c-attribs.c (handle_section_attribute): No longer
+       set user_defined_section_attribute.
+       * gcc/final.c (rest_of_handle_final): Likewise.
+       * gcc/toplev.c: Remove definition of user_defined_section_attribute.
+       * gcc/toplev.h: Remove declaration of
+       user_defined_section_attribute.
+
 2016-11-16  Maciej W. Rozycki  <macro@imgtec.com>
 
        * config/mips/mips.md (casesi_internal_mips16_<mode>):
index 85bc5698090af6e909aac82d1cbb18e3cad7ade8..e51ec085ca01d2da6095316eb576118680f679a3 100644 (file)
 #include "output.h"
 #include "expr.h"
 #include "params.h"
-#include "toplev.h" /* user_defined_section_attribute */
 #include "tree-pass.h"
 #include "cfgrtl.h"
 #include "cfganal.h"
@@ -2894,7 +2893,7 @@ pass_partition_blocks::gate (function *fun)
             we are going to omit the reordering.  */
          && optimize_function_for_speed_p (fun)
          && !DECL_COMDAT_GROUP (current_function_decl)
-         && !user_defined_section_attribute);
+         && !lookup_attribute ("section", DECL_ATTRIBUTES (fun->decl)));
 }
 
 unsigned
index 925f1b20c5096bb09724aa82df144c8a122ec49a..964efe94bb7261696abcde97e99c5db9c7906a0b 100644 (file)
@@ -1438,8 +1438,6 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       goto fail;
     }
 
-  user_defined_section_attribute = true;
-
   if (!VAR_OR_FUNCTION_DECL_P (decl))
     {
       error ("section attribute not allowed for %q+D", *node);
index 5709d0e2406bb9aa025ffe9aa6ece2cd0da7176f..d3a53c3cbe6b51af9035d32f89bcb18b11221c91 100644 (file)
@@ -4484,8 +4484,6 @@ rest_of_handle_final (void)
 
   assemble_end_function (current_function_decl, fnname);
 
-  user_defined_section_attribute = false;
-
   /* Free up reg info memory.  */
   free_reg_info ();
 
index 3707e7c29d2b7948cd8082e185f788bfcfa7f6fa..8958f86b898e556ffd1f681238a9c6cc2bc729d2 100644 (file)
@@ -1,3 +1,9 @@
+2016-11-16  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gcc.dg/tree-prof/section-attr-1.c: New file.
+       * gcc.dg/tree-prof/section-attr-2.c: New file.
+       * gcc.dg/tree-prof/section-attr-3.c: New file.
+
 2016-11-16  Maciej W. Rozycki  <macro@imgtec.com>
 
        * gcc.target/mips/code-readable-4.c (dg-final): Expect `dla'
diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c
new file mode 100644 (file)
index 0000000..ee6662e
--- /dev/null
@@ -0,0 +1,45 @@
+/* Checks for a bug where a function with a section attribute would prevent
+   all later functions from being partitioned into hot and cold blocks.  */
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O2 -fno-profile-reorder-functions -freorder-blocks-and-partition -save-temps" } */
+
+#define SIZE 10000
+
+#define NOINLINE __attribute__((noinline)) __attribute__ ((noclone))
+
+const char *sarr[SIZE];
+const char *buf_hot;
+const char *buf_cold;
+
+void foo (int path);
+
+__attribute__((section(".text")))
+int
+main (int argc, char *argv[])
+{
+  int i;
+  buf_hot =  "hello";
+  buf_cold = "world";
+  for (i = 0; i < 1000000; i++)
+    foo (argc);
+  return 0;
+}
+
+
+void NOINLINE
+foo (int path)
+{
+  int i;
+  if (path)
+    {
+      for (i = 0; i < SIZE; i++)
+       sarr[i] = buf_hot;
+    }
+  else
+    {
+      for (i = 0; i < SIZE; i++)
+       sarr[i] = buf_cold;
+    }
+}
+
+/* { dg-final-use { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold\.0" { target *-*-linux* *-*-gnu* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c
new file mode 100644 (file)
index 0000000..898a395
--- /dev/null
@@ -0,0 +1,44 @@
+/* Checks for a bug where static data with a section attribute within a
+   function would stop the function being partitioned into hot and cold
+   blocks.  */
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O2 -fno-profile-reorder-functions -freorder-blocks-and-partition -save-temps" } */
+
+#define SIZE 10000
+
+#define NOINLINE __attribute__((noinline)) __attribute__ ((noclone))
+
+const char *sarr[SIZE];
+const char *buf_hot;
+const char *buf_cold;
+
+void foo (int path);
+
+int
+main (int argc, char *argv[])
+{
+  int i;
+  buf_hot =  "hello";
+  buf_cold = "world";
+  for (i = 0; i < 1000000; i++)
+    foo (argc);
+  return 0;
+}
+
+void NOINLINE
+foo (int path)
+{
+  static int i __attribute__((section(".data")));
+  if (path)
+    {
+      for (i = 0; i < SIZE; i++)
+       sarr[i] = buf_hot;
+    }
+  else
+    {
+      for (i = 0; i < SIZE; i++)
+       sarr[i] = buf_cold;
+    }
+}
+
+/* { dg-final-use { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold\.0" { target *-*-linux* *-*-gnu* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c
new file mode 100644 (file)
index 0000000..36829dc
--- /dev/null
@@ -0,0 +1,45 @@
+/* Checks for a bug where static data with a section attribute within a
+   function would stop the function being partitioned into hot and cold
+   blocks.  */
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O2 -fno-profile-reorder-functions -freorder-blocks-and-partition -save-temps" } */
+
+#define SIZE 10000
+
+#define NOINLINE __attribute__((noinline)) __attribute__ ((noclone))
+
+const char *sarr[SIZE];
+const char *buf_hot __attribute__ ((section (".data")));
+const char *buf_cold;
+
+void foo (int path);
+
+int
+main (int argc, char *argv[])
+{
+  int i;
+  buf_hot =  "hello";
+  buf_cold = "world";
+  for (i = 0; i < 1000000; i++)
+    foo (argc);
+  return 0;
+}
+
+
+void NOINLINE
+foo (int path)
+{
+  int i;
+  if (path)
+    {
+      for (i = 0; i < SIZE; i++)
+       sarr[i] = buf_hot;
+    }
+  else
+    {
+      for (i = 0; i < SIZE; i++)
+       sarr[i] = buf_cold;
+    }
+}
+
+/* { dg-final-use { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold\.0" { target *-*-linux* *-*-gnu* } } } */
index 59b84eb4d4be9f61df80494783150f2c457ab5fe..d43234a65c1d86aed729a1703f6a02f675a6c777 100644 (file)
@@ -151,11 +151,6 @@ HOST_WIDE_INT random_seed;
    the support provided depends on the backend.  */
 rtx stack_limit_rtx;
 
-/* True if the user has tagged the function with the 'section'
-   attribute.  */
-
-bool user_defined_section_attribute = false;
-
 struct target_flag_state default_target_flag_state;
 #if SWITCHABLE_TARGET
 struct target_flag_state *this_target_flag_state = &default_target_flag_state;
index 06923cf0c94e3ababebfb0f017d87c8d8a0e66ae..f62a172cc52ee2471384953e8d43a8bd1bfaa359 100644 (file)
@@ -74,11 +74,6 @@ extern void target_reinit (void);
 /* A unique local time stamp, might be zero if none is available.  */
 extern unsigned local_tick;
 
-/* True if the user has tagged the function with the 'section'
-   attribute.  */
-
-extern bool user_defined_section_attribute;
-
 /* See toplev.c.  */
 extern int flag_rerun_cse_after_global_opts;