builtins: Commonise default handling of nonlocal_goto

Message ID mpt7czzqjwp.fsf@arm.com
State New
Headers
Series builtins: Commonise default handling of nonlocal_goto |

Commit Message

Richard Sandiford Nov. 13, 2022, 9:32 a.m. UTC
  expand_builtin_longjmp and expand_builtin_nonlocal_goto both
emit nonlocal gotos.  They first try to use a target-provided
pattern and fall back to generic code otherwise.  These pieces
of generic code are almost identical, and having them inline
like this makes it difficult to define a nonlocal_goto pattern
that only wants to add extra steps, not change the default ones.

Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

Richard

gcc/
	* builtins.h (emit_standard_nonlocal_goto): Declare.
	* builtins.cc (emit_standard_nonlocal_goto): New function,
	commonizing code from...
	(expand_builtin_longjmp, expand_builtin_nonlocal_goto): ...here.
	* genemit.cc (main): Emit an include of builtins.h.
---
 gcc/builtins.cc | 103 +++++++++++++++++++++---------------------------
 gcc/builtins.h  |   1 +
 gcc/genemit.cc  |   1 +
 3 files changed, 47 insertions(+), 58 deletions(-)
  

Comments

Richard Biener Nov. 14, 2022, 9:42 a.m. UTC | #1
On Sun, Nov 13, 2022 at 10:33 AM Richard Sandiford via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> expand_builtin_longjmp and expand_builtin_nonlocal_goto both
> emit nonlocal gotos.  They first try to use a target-provided
> pattern and fall back to generic code otherwise.  These pieces
> of generic code are almost identical, and having them inline
> like this makes it difficult to define a nonlocal_goto pattern
> that only wants to add extra steps, not change the default ones.
>
> Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

OK.

> Richard
>
> gcc/
>         * builtins.h (emit_standard_nonlocal_goto): Declare.
>         * builtins.cc (emit_standard_nonlocal_goto): New function,
>         commonizing code from...
>         (expand_builtin_longjmp, expand_builtin_nonlocal_goto): ...here.
>         * genemit.cc (main): Emit an include of builtins.h.
> ---
>  gcc/builtins.cc | 103 +++++++++++++++++++++---------------------------
>  gcc/builtins.h  |   1 +
>  gcc/genemit.cc  |   1 +
>  3 files changed, 47 insertions(+), 58 deletions(-)
>
> diff --git a/gcc/builtins.cc b/gcc/builtins.cc
> index 4dc1ca672b2..2507745c17a 100644
> --- a/gcc/builtins.cc
> +++ b/gcc/builtins.cc
> @@ -998,6 +998,49 @@ expand_builtin_setjmp_receiver (rtx receiver_label)
>    emit_insn (gen_blockage ());
>  }
>
> +/* Emit the standard sequence for a nonlocal_goto.  The arguments are
> +   the operands to the .md pattern.  */
> +
> +void
> +emit_standard_nonlocal_goto (rtx value, rtx label, rtx stack, rtx fp)
> +{
> +  emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
> +  emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
> +
> +  label = copy_to_reg (label);
> +
> +  /* Restore the frame pointer and stack pointer.  We must use a
> +     temporary since the setjmp buffer may be a local.  */
> +  fp = copy_to_reg (fp);
> +  emit_stack_restore (SAVE_NONLOCAL, stack);
> +
> +  /* Ensure the frame pointer move is not optimized.  */
> +  emit_insn (gen_blockage ());
> +  emit_clobber (hard_frame_pointer_rtx);
> +  emit_clobber (frame_pointer_rtx);
> +  emit_move_insn (hard_frame_pointer_rtx, fp);
> +
> +  /* USE of hard_frame_pointer_rtx added for consistency;
> +     not clear if really needed.  */
> +  emit_use (hard_frame_pointer_rtx);
> +  emit_use (stack_pointer_rtx);
> +
> +  /* If the architecture is using a GP register, we must
> +     conservatively assume that the target function makes use of it.
> +     The prologue of functions with nonlocal gotos must therefore
> +     initialize the GP register to the appropriate value, and we
> +     must then make sure that this value is live at the point
> +     of the jump.  (Note that this doesn't necessarily apply
> +     to targets with a nonlocal_goto pattern; they are free
> +     to implement it in their own way.  Note also that this is
> +     a no-op if the GP register is a global invariant.)  */
> +  unsigned regnum = PIC_OFFSET_TABLE_REGNUM;
> +  if (value == const0_rtx && regnum != INVALID_REGNUM && fixed_regs[regnum])
> +    emit_use (pic_offset_table_rtx);
> +
> +  emit_indirect_jump (label);
> +}
> +
>  /* __builtin_longjmp is passed a pointer to an array of five words (not
>     all will be used on all machines).  It operates similarly to the C
>     library function of the same name, but is more efficient.  Much of
> @@ -1049,27 +1092,7 @@ expand_builtin_longjmp (rtx buf_addr, rtx value)
>            what that value is, because builtin_setjmp does not use it.  */
>         emit_insn (targetm.gen_nonlocal_goto (value, lab, stack, fp));
>        else
> -       {
> -         emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
> -         emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
> -
> -         lab = copy_to_reg (lab);
> -
> -         /* Restore the frame pointer and stack pointer.  We must use a
> -            temporary since the setjmp buffer may be a local.  */
> -         fp = copy_to_reg (fp);
> -         emit_stack_restore (SAVE_NONLOCAL, stack);
> -
> -         /* Ensure the frame pointer move is not optimized.  */
> -         emit_insn (gen_blockage ());
> -         emit_clobber (hard_frame_pointer_rtx);
> -         emit_clobber (frame_pointer_rtx);
> -         emit_move_insn (hard_frame_pointer_rtx, fp);
> -
> -         emit_use (hard_frame_pointer_rtx);
> -         emit_use (stack_pointer_rtx);
> -         emit_indirect_jump (lab);
> -       }
> +       emit_standard_nonlocal_goto (value, lab, stack, fp);
>      }
>
>    /* Search backwards and mark the jump insn as a non-local goto.
> @@ -1201,43 +1224,7 @@ expand_builtin_nonlocal_goto (tree exp)
>    if (targetm.have_nonlocal_goto ())
>      emit_insn (targetm.gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
>    else
> -    {
> -      emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
> -      emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
> -
> -      r_label = copy_to_reg (r_label);
> -
> -      /* Restore the frame pointer and stack pointer.  We must use a
> -        temporary since the setjmp buffer may be a local.  */
> -      r_fp = copy_to_reg (r_fp);
> -      emit_stack_restore (SAVE_NONLOCAL, r_sp);
> -
> -      /* Ensure the frame pointer move is not optimized.  */
> -      emit_insn (gen_blockage ());
> -      emit_clobber (hard_frame_pointer_rtx);
> -      emit_clobber (frame_pointer_rtx);
> -      emit_move_insn (hard_frame_pointer_rtx, r_fp);
> -
> -      /* USE of hard_frame_pointer_rtx added for consistency;
> -        not clear if really needed.  */
> -      emit_use (hard_frame_pointer_rtx);
> -      emit_use (stack_pointer_rtx);
> -
> -      /* If the architecture is using a GP register, we must
> -        conservatively assume that the target function makes use of it.
> -        The prologue of functions with nonlocal gotos must therefore
> -        initialize the GP register to the appropriate value, and we
> -        must then make sure that this value is live at the point
> -        of the jump.  (Note that this doesn't necessarily apply
> -        to targets with a nonlocal_goto pattern; they are free
> -        to implement it in their own way.  Note also that this is
> -        a no-op if the GP register is a global invariant.)  */
> -      unsigned regnum = PIC_OFFSET_TABLE_REGNUM;
> -      if (regnum != INVALID_REGNUM && fixed_regs[regnum])
> -       emit_use (pic_offset_table_rtx);
> -
> -      emit_indirect_jump (r_label);
> -    }
> +    emit_standard_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp);
>
>    /* Search backwards to the jump insn and mark it as a
>       non-local goto.  */
> diff --git a/gcc/builtins.h b/gcc/builtins.h
> index 5ad830c9fbf..5c86b241fea 100644
> --- a/gcc/builtins.h
> +++ b/gcc/builtins.h
> @@ -150,6 +150,7 @@ extern char target_percent_c[3];
>  extern char target_percent_s_newline[4];
>  extern bool target_char_cst_p (tree t, char *p);
>  extern rtx get_memory_rtx (tree exp, tree len);
> +extern void emit_standard_nonlocal_goto (rtx, rtx, rtx, rtx);
>
>  extern internal_fn associated_internal_fn (combined_fn, tree);
>  extern internal_fn associated_internal_fn (tree);
> diff --git a/gcc/genemit.cc b/gcc/genemit.cc
> index 909ac89a16b..c3e2152a491 100644
> --- a/gcc/genemit.cc
> +++ b/gcc/genemit.cc
> @@ -905,6 +905,7 @@ from the machine description file `md'.  */\n\n");
>    printf ("#include \"tm-constrs.h\"\n");
>    printf ("#include \"ggc.h\"\n");
>    printf ("#include \"target.h\"\n\n");
> +  printf ("#include \"builtins.h\"\n\n");
>
>    /* Read the machine description.  */
>
> --
> 2.25.1
>
  

Patch

diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index 4dc1ca672b2..2507745c17a 100644
--- a/gcc/builtins.cc
+++ b/gcc/builtins.cc
@@ -998,6 +998,49 @@  expand_builtin_setjmp_receiver (rtx receiver_label)
   emit_insn (gen_blockage ());
 }
 
+/* Emit the standard sequence for a nonlocal_goto.  The arguments are
+   the operands to the .md pattern.  */
+
+void
+emit_standard_nonlocal_goto (rtx value, rtx label, rtx stack, rtx fp)
+{
+  emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
+  emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
+
+  label = copy_to_reg (label);
+
+  /* Restore the frame pointer and stack pointer.  We must use a
+     temporary since the setjmp buffer may be a local.  */
+  fp = copy_to_reg (fp);
+  emit_stack_restore (SAVE_NONLOCAL, stack);
+
+  /* Ensure the frame pointer move is not optimized.  */
+  emit_insn (gen_blockage ());
+  emit_clobber (hard_frame_pointer_rtx);
+  emit_clobber (frame_pointer_rtx);
+  emit_move_insn (hard_frame_pointer_rtx, fp);
+
+  /* USE of hard_frame_pointer_rtx added for consistency;
+     not clear if really needed.  */
+  emit_use (hard_frame_pointer_rtx);
+  emit_use (stack_pointer_rtx);
+
+  /* If the architecture is using a GP register, we must
+     conservatively assume that the target function makes use of it.
+     The prologue of functions with nonlocal gotos must therefore
+     initialize the GP register to the appropriate value, and we
+     must then make sure that this value is live at the point
+     of the jump.  (Note that this doesn't necessarily apply
+     to targets with a nonlocal_goto pattern; they are free
+     to implement it in their own way.  Note also that this is
+     a no-op if the GP register is a global invariant.)  */
+  unsigned regnum = PIC_OFFSET_TABLE_REGNUM;
+  if (value == const0_rtx && regnum != INVALID_REGNUM && fixed_regs[regnum])
+    emit_use (pic_offset_table_rtx);
+
+  emit_indirect_jump (label);
+}
+
 /* __builtin_longjmp is passed a pointer to an array of five words (not
    all will be used on all machines).  It operates similarly to the C
    library function of the same name, but is more efficient.  Much of
@@ -1049,27 +1092,7 @@  expand_builtin_longjmp (rtx buf_addr, rtx value)
 	   what that value is, because builtin_setjmp does not use it.  */
 	emit_insn (targetm.gen_nonlocal_goto (value, lab, stack, fp));
       else
-	{
-	  emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
-	  emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
-
-	  lab = copy_to_reg (lab);
-
-	  /* Restore the frame pointer and stack pointer.  We must use a
-	     temporary since the setjmp buffer may be a local.  */
-	  fp = copy_to_reg (fp);
-	  emit_stack_restore (SAVE_NONLOCAL, stack);
-
-	  /* Ensure the frame pointer move is not optimized.  */
-	  emit_insn (gen_blockage ());
-	  emit_clobber (hard_frame_pointer_rtx);
-	  emit_clobber (frame_pointer_rtx);
-	  emit_move_insn (hard_frame_pointer_rtx, fp);
-
-	  emit_use (hard_frame_pointer_rtx);
-	  emit_use (stack_pointer_rtx);
-	  emit_indirect_jump (lab);
-	}
+	emit_standard_nonlocal_goto (value, lab, stack, fp);
     }
 
   /* Search backwards and mark the jump insn as a non-local goto.
@@ -1201,43 +1224,7 @@  expand_builtin_nonlocal_goto (tree exp)
   if (targetm.have_nonlocal_goto ())
     emit_insn (targetm.gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
   else
-    {
-      emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
-      emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
-
-      r_label = copy_to_reg (r_label);
-
-      /* Restore the frame pointer and stack pointer.  We must use a
-	 temporary since the setjmp buffer may be a local.  */
-      r_fp = copy_to_reg (r_fp);
-      emit_stack_restore (SAVE_NONLOCAL, r_sp);
-
-      /* Ensure the frame pointer move is not optimized.  */
-      emit_insn (gen_blockage ());
-      emit_clobber (hard_frame_pointer_rtx);
-      emit_clobber (frame_pointer_rtx);
-      emit_move_insn (hard_frame_pointer_rtx, r_fp);
-
-      /* USE of hard_frame_pointer_rtx added for consistency;
-	 not clear if really needed.  */
-      emit_use (hard_frame_pointer_rtx);
-      emit_use (stack_pointer_rtx);
-
-      /* If the architecture is using a GP register, we must
-	 conservatively assume that the target function makes use of it.
-	 The prologue of functions with nonlocal gotos must therefore
-	 initialize the GP register to the appropriate value, and we
-	 must then make sure that this value is live at the point
-	 of the jump.  (Note that this doesn't necessarily apply
-	 to targets with a nonlocal_goto pattern; they are free
-	 to implement it in their own way.  Note also that this is
-	 a no-op if the GP register is a global invariant.)  */
-      unsigned regnum = PIC_OFFSET_TABLE_REGNUM;
-      if (regnum != INVALID_REGNUM && fixed_regs[regnum])
-	emit_use (pic_offset_table_rtx);
-
-      emit_indirect_jump (r_label);
-    }
+    emit_standard_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp);
 
   /* Search backwards to the jump insn and mark it as a
      non-local goto.  */
diff --git a/gcc/builtins.h b/gcc/builtins.h
index 5ad830c9fbf..5c86b241fea 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -150,6 +150,7 @@  extern char target_percent_c[3];
 extern char target_percent_s_newline[4];
 extern bool target_char_cst_p (tree t, char *p);
 extern rtx get_memory_rtx (tree exp, tree len);
+extern void emit_standard_nonlocal_goto (rtx, rtx, rtx, rtx);
 
 extern internal_fn associated_internal_fn (combined_fn, tree);
 extern internal_fn associated_internal_fn (tree);
diff --git a/gcc/genemit.cc b/gcc/genemit.cc
index 909ac89a16b..c3e2152a491 100644
--- a/gcc/genemit.cc
+++ b/gcc/genemit.cc
@@ -905,6 +905,7 @@  from the machine description file `md'.  */\n\n");
   printf ("#include \"tm-constrs.h\"\n");
   printf ("#include \"ggc.h\"\n");
   printf ("#include \"target.h\"\n\n");
+  printf ("#include \"builtins.h\"\n\n");
 
   /* Read the machine description.  */