diff mbox series

bb-reorder: Fix -freorder-blocks-and-partition ICEs on aarch64 with asm goto [PR110079]

Message ID Zel5TMMr/3BHgl0g@tucnak
State New
Headers show
Series bb-reorder: Fix -freorder-blocks-and-partition ICEs on aarch64 with asm goto [PR110079] | expand

Commit Message

Jakub Jelinek March 7, 2024, 8:22 a.m. UTC
Hi!

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.

Bootstrapped/regtested on x86_64-linux, i686-linux and aarch64-linux, ok for
trunk?

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.


	Jakub

Comments

Richard Biener March 7, 2024, 8:52 a.m. UTC | #1
On Thu, 7 Mar 2024, Jakub Jelinek wrote:

> Hi!
> 
> 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.
> 
> Bootstrapped/regtested on x86_64-linux, i686-linux and aarch64-linux, ok for
> trunk?

OK.

Thanks,
Richard.

> 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.
> 
> --- gcc/bb-reorder.cc.jj	2024-01-03 11:51:32.000000000 +0100
> +++ gcc/bb-reorder.cc	2024-03-06 18:34:29.468016144 +0100
> @@ -2266,7 +2266,8 @@ fix_crossing_unconditional_branches (voi
>  	  /* 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)))
>  	    {
>  	      /* We have found a "crossing" unconditional branch.  Now
>  		 we must convert it to an indirect jump.  First create
> --- gcc/testsuite/gcc.dg/pr110079.c.jj	2024-03-06 18:42:47.175250069 +0100
> +++ gcc/testsuite/gcc.dg/pr110079.c	2024-03-06 18:44:47.008620726 +0100
> @@ -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;
> +}
> 
> 	Jakub
> 
>
diff mbox series

Patch

--- gcc/bb-reorder.cc.jj	2024-01-03 11:51:32.000000000 +0100
+++ gcc/bb-reorder.cc	2024-03-06 18:34:29.468016144 +0100
@@ -2266,7 +2266,8 @@  fix_crossing_unconditional_branches (voi
 	  /* 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)))
 	    {
 	      /* We have found a "crossing" unconditional branch.  Now
 		 we must convert it to an indirect jump.  First create
--- gcc/testsuite/gcc.dg/pr110079.c.jj	2024-03-06 18:42:47.175250069 +0100
+++ gcc/testsuite/gcc.dg/pr110079.c	2024-03-06 18:44:47.008620726 +0100
@@ -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;
+}