arm_option_override rejects -freorder-blocks-and-partition because a
function's literal pool cannot span the hot/cold section split.  A
per-function optimize attribute or pragma re-enables the flag behind
that check: the attribute's option set is built without re-running the
override, so pass_partition_blocks splits the function, its trailing
literal pool is emitted after the cold part in .text.unlikely, and the
assembler rejects the PC-relative loads left in .text:

  Error: symbol .text.unlikely is in a different section

Clear the flag in the override_options_after_change hook as well, which
runs whenever such per-function option sets are created or restored.

Tested on arm-none-eabi with gcc.target/arm/arm.exp.  The new test
needs a literal pool, so it runs at Armv6; from Armv7-A the constants
are built with movw/movt and no pool exists.

Assisted-by: Claude Opus 5 (Anthropic)

gcc/ChangeLog:

        * config/arm/arm.cc (arm_override_options_after_change_1): Clear
        flag_reorder_blocks_and_partition and restore flag_reorder_blocks,
        as arm_option_override does for the command line.

gcc/testsuite/ChangeLog:

        * gcc.target/arm/reorder-blocks-partition-1.c: New test.

Signed-off-by: Dominic P <[email protected]>
---
 gcc/config/arm/arm.cc                          |  8 ++++++++
 .../arm/reorder-blocks-partition-1.c           | 18 ++++++++++++++++++
 2 files changed, 26 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/arm/reorder-blocks-partition-1.c

diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 33b64995442..dab66236919 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -3083,6 +3083,14 @@ arm_override_options_after_change_1 (struct gcc_options 
*opts,
   if (opts->x_flag_align_functions && !opts_set->x_str_align_functions)
     opts->x_str_align_functions = TARGET_THUMB_P (opts->x_target_flags)
       && opts->x_optimize_size ? "2" : "4";
+
+  /* Not supported on this target (see arm_option_override); a
+     per-function optimize attribute would otherwise re-enable it.  */
+  if (opts->x_flag_reorder_blocks_and_partition)
+    {
+      opts->x_flag_reorder_blocks_and_partition = 0;
+      opts->x_flag_reorder_blocks = 1;
+    }
 }
 
 /* Implement targetm.override_options_after_change.  */
diff --git a/gcc/testsuite/gcc.target/arm/reorder-blocks-partition-1.c 
b/gcc/testsuite/gcc.target/arm/reorder-blocks-partition-1.c
new file mode 100644
index 00000000000..4326dc8ba6b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/reorder-blocks-partition-1.c
@@ -0,0 +1,18 @@
+/* The trailing literal pool must not land in .text.unlikely.  */
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_arch_v6_ok } */
+/* { dg-options "-O2 -marm" } */
+/* { dg-add-options arm_arch_v6 } */
+
+extern void cold_sink (int) __attribute__ ((cold, noreturn));
+extern double sink;
+
+__attribute__ ((optimize ("reorder-blocks-and-partition")))
+double
+f1 (int x)
+{
+  if (__builtin_expect (x == 42, 0))
+    cold_sink (x);
+  sink = 2.0;
+  return 3.14159265358979;
+}
-- 
2.55.0

Reply via email to