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