aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-03-07 10:02:49 +0100
committerJakub Jelinek <jakub@redhat.com>2024-06-11 12:35:33 +0200
commitb294d461e2efd6894ba6570ca003701c20fc3cd8 (patch)
tree60f2a35e47b70388588ec1fdcc34e0c576e13bb2
parent929972273e858a9a913b0d74e69ac2f8d7255c28 (diff)
downloadgcc-b294d461e2efd6894ba6570ca003701c20fc3cd8.zip
gcc-b294d461e2efd6894ba6570ca003701c20fc3cd8.tar.gz
gcc-b294d461e2efd6894ba6570ca003701c20fc3cd8.tar.bz2
bb-reorder: Fix -freorder-blocks-and-partition ICEs on aarch64 with asm goto [PR110079]
The following testcase ICEs, because fix_crossing_unconditional_branches thinks that asm goto is an unconditional jump and removes it, replacing it with unconditional jump to one of the labels. This doesn't happen on x86 because the function in question isn't invoked there at all: /* If the architecture does not have unconditional branches that can span all of memory, convert crossing unconditional branches into indirect jumps. Since adding an indirect jump also adds a new register usage, update the register usage information as well. */ if (!HAS_LONG_UNCOND_BRANCH) fix_crossing_unconditional_branches (); I think for the asm goto case, for the non-fallthru edge if any we should handle it like any other fallthru (and fix_crossing_unconditional_branches doesn't really deal with those, it only looks at explicit branches at the end of bbs and we are in cfglayout mode at that point) and for the labels we just pass the labels as immediates to the assembly and it is up to the user to figure out how to store them/branch to them or whatever they want to do. So, the following patch fixes this by not treating asm goto as a simple unconditional jump. I really think that on the !HAS_LONG_UNCOND_BRANCH targets we have a bug somewhere else, where outofcfglayout or whatever should actually create those indirect jumps on the crossing edges instead of adding normal unconditional jumps, I see e.g. in __attribute__((cold)) int bar (char *); __attribute__((hot)) int baz (char *); void qux (int x) { if (__builtin_expect (!x, 1)) goto l1; bar (""); goto l1; l1: baz (""); } void corge (int x) { if (__builtin_expect (!x, 0)) goto l1; baz (""); l2: return; l1: bar (""); goto l2; } with -O2 -freorder-blocks-and-partition on aarch64 before/after this patch just b .L? jumps which I believe are +-32MB, so if .text is larger than 32MB, it could fail to link, but this patch doesn't address that. 2024-03-07 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/110079 * bb-reorder.cc (fix_crossing_unconditional_branches): Don't adjust asm goto. * gcc.dg/pr110079.c: New test. (cherry picked from commit b209d905f5ce1fa9d76ce634fd54245ff340960b)
-rw-r--r--gcc/bb-reorder.cc3
-rw-r--r--gcc/testsuite/gcc.dg/pr110079.c43
2 files changed, 45 insertions, 1 deletions
diff --git a/gcc/bb-reorder.cc b/gcc/bb-reorder.cc
index 2c194aa..ef2a192 100644
--- a/gcc/bb-reorder.cc
+++ b/gcc/bb-reorder.cc
@@ -2266,7 +2266,8 @@ fix_crossing_unconditional_branches (void)
/* Make sure the jump is not already an indirect or table jump. */
if (!computed_jump_p (last_insn)
- && !tablejump_p (last_insn, NULL, NULL))
+ && !tablejump_p (last_insn, NULL, NULL)
+ && asm_noperands (PATTERN (last_insn)) < 0)
{
/* We have found a "crossing" unconditional branch. Now
we must convert it to an indirect jump. First create
diff --git a/gcc/testsuite/gcc.dg/pr110079.c b/gcc/testsuite/gcc.dg/pr110079.c
new file mode 100644
index 0000000..1682f9c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr110079.c
@@ -0,0 +1,43 @@
+/* PR rtl-optimization/110079 */
+/* { dg-do compile { target lra } } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-freorder-blocks-and-partition" { target freorder } } */
+
+int a;
+__attribute__((cold)) int bar (char *);
+__attribute__((hot)) int baz (char *);
+
+void
+foo (void)
+{
+l1:
+ while (a)
+ ;
+ bar ("");
+ asm goto ("" : : : : l2);
+ asm ("");
+l2:
+ goto l1;
+}
+
+void
+qux (void)
+{
+ asm goto ("" : : : : l1);
+ bar ("");
+ goto l1;
+l1:
+ baz ("");
+}
+
+void
+corge (void)
+{
+ asm goto ("" : : : : l1);
+ baz ("");
+l2:
+ return;
+l1:
+ bar ("");
+ goto l2;
+}