Currently patchable area is at the wrong place.  It is placed immediately
after function label, before both .cfi_startproc and ENDBR.  This patch
adds UNSPECV_PATCHABLE_AREA for pseudo patchable area instruction and
changes ENDBR insertion pass to also insert patchable area instruction.
TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY is defined to avoid placing
patchable area before .cfi_startproc and ENDBR.

OK for master?

Thanks.

H.J.
---
gcc/

        PR target/93492
        * config/i386/i386-features.c (rest_of_insert_endbranch):
        Renamed to ...
        (rest_of_insert_endbr_and_patchable_area): Change return type
        to void. Add need_endbr and patchable_area_size arguments.
        Don't call timevar_push nor timevar_pop.  Replace
        endbr_queued_at_entrance with insn_queued_at_entrance.  Insert
        UNSPECV_PATCHABLE_AREA for patchable area.
        (pass_data_insert_endbranch): Renamed to ...
        (pass_data_insert_endbr_and_patchable_area): This.  Change
        pass name to endbr_and_patchable_area.
        (pass_insert_endbranch): Renamed to ...
        (pass_insert_endbr_and_patchable_area): This.  Add need_endbr
        and patchable_area_size;.
        (pass_insert_endbr_and_patchable_area::gate): Set and check
        need_endbr and patchable_area_size.
        (pass_insert_endbr_and_patchable_area::execute): Call
        timevar_push and timevar_pop.  Pass need_endbr and
        patchable_area_size to rest_of_insert_endbr_and_patchable_area.
        (make_pass_insert_endbranch): Renamed to ...
        (make_pass_insert_endbr_and_patchable_area): This.
        * config/i386/i386-passes.def: Replace pass_insert_endbranch
        with pass_insert_endbr_and_patchable_area.
        * config/i386/i386-protos.h (ix86_output_patchable_area): New.
        (make_pass_insert_endbranch): Renamed to ...
        (make_pass_insert_endbr_and_patchable_area): This.
        * config/i386/i386.c (ix86_asm_output_function_label): Set
        function_label_emitted to true.
        (ix86_print_patchable_function_entry): New function.
        (ix86_output_patchable_area): Likewise.
        (x86_function_profiler): Replace endbr_queued_at_entrance with
        insn_queued_at_entrance.  Generate ENDBR only for TYPE_ENDBR.
        Call ix86_output_patchable_area to generate patchable area if
        needed.
        (TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY): New.
        * i386.h (queued_insn_type): New.
        (machine_function): Add function_label_emitted.  Replace
        endbr_queued_at_entrance with insn_queued_at_entrance.
        * config/i386/i386.md (UNSPECV_PATCHABLE_AREA): New.
        (patchable_area): New.

gcc/testsuite/

        PR target/93492
        * gcc.target/i386/pr93492-1.c: New test.
        * gcc.target/i386/pr93492-2.c: Likewise.
        * gcc.target/i386/pr93492-3.c: Likewise.
        * gcc.target/i386/pr93492-4.c: Likewise.
        * gcc.target/i386/pr93492-5.c: Likewise.
---
 gcc/config/i386/i386-features.c           | 142 ++++++++++++++--------
 gcc/config/i386/i386-passes.def           |   2 +-
 gcc/config/i386/i386-protos.h             |   5 +-
 gcc/config/i386/i386.c                    |  51 +++++++-
 gcc/config/i386/i386.h                    |  14 ++-
 gcc/config/i386/i386.md                   |  17 +++
 gcc/testsuite/gcc.target/i386/pr93492-1.c |  73 +++++++++++
 gcc/testsuite/gcc.target/i386/pr93492-2.c |  12 ++
 gcc/testsuite/gcc.target/i386/pr93492-3.c |  13 ++
 gcc/testsuite/gcc.target/i386/pr93492-4.c |  11 ++
 gcc/testsuite/gcc.target/i386/pr93492-5.c |  12 ++
 11 files changed, 296 insertions(+), 56 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr93492-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr93492-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr93492-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr93492-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr93492-5.c

diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c
index 78fb373db6e..41cc8b583b6 100644
--- a/gcc/config/i386/i386-features.c
+++ b/gcc/config/i386/i386-features.c
@@ -1941,48 +1941,83 @@ make_pass_stv (gcc::context *ctxt)
   return new pass_stv (ctxt);
 }
 
-/* Inserting ENDBRANCH instructions.  */
+/* Inserting ENDBR and pseudo patchable-area instructions.  */
 
-static unsigned int
-rest_of_insert_endbranch (void)
+static void
+rest_of_insert_endbr_and_patchable_area (bool need_endbr,
+                                        unsigned int patchable_area_size)
 {
-  timevar_push (TV_MACH_DEP);
-
-  rtx cet_eb;
+  rtx endbr;
   rtx_insn *insn;
+  rtx_insn *endbr_insn = NULL;
   basic_block bb;
 
-  /* Currently emit EB if it's a tracking function, i.e. 'nocf_check' is
-     absent among function attributes.  Later an optimization will be
-     introduced to make analysis if an address of a static function is
-     taken.  A static function whose address is not taken will get a
-     nocf_check attribute.  This will allow to reduce the number of EB.  */
-
-  if (!lookup_attribute ("nocf_check",
-                        TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
-      && (!flag_manual_endbr
-         || lookup_attribute ("cf_check",
-                              DECL_ATTRIBUTES (cfun->decl)))
-      && (!cgraph_node::get (cfun->decl)->only_called_directly_p ()
-         || ix86_cmodel == CM_LARGE
-         || ix86_cmodel == CM_LARGE_PIC
-         || flag_force_indirect_call
-         || (TARGET_DLLIMPORT_DECL_ATTRIBUTES
-             && DECL_DLLIMPORT_P (cfun->decl))))
-    {
-      /* Queue ENDBR insertion to x86_function_profiler.  */
+  if (need_endbr)
+    {
+      /* Currently emit EB if it's a tracking function, i.e. 'nocf_check'
+        is absent among function attributes.  Later an optimization will
+        be introduced to make analysis if an address of a static function
+        is taken.  A static function whose address is not taken will get
+        a nocf_check attribute.  This will allow to reduce the number of
+        EB.  */
+      if (!lookup_attribute ("nocf_check",
+                            TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
+         && (!flag_manual_endbr
+             || lookup_attribute ("cf_check",
+                                  DECL_ATTRIBUTES (cfun->decl)))
+         && (!cgraph_node::get (cfun->decl)->only_called_directly_p ()
+             || ix86_cmodel == CM_LARGE
+             || ix86_cmodel == CM_LARGE_PIC
+             || flag_force_indirect_call
+             || (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+                 && DECL_DLLIMPORT_P (cfun->decl))))
+       {
+         if (crtl->profile && flag_fentry)
+           {
+             /* Queue ENDBR insertion to x86_function_profiler.
+                NB: Any patchable-area insn will be inserted after
+                ENDBR.  */
+             cfun->machine->insn_queued_at_entrance = TYPE_ENDBR;
+           }
+         else
+           {
+             endbr = gen_nop_endbr ();
+             bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
+             rtx_insn *insn = BB_HEAD (bb);
+             endbr_insn = emit_insn_before (endbr, insn);
+           }
+       }
+    }
+
+  if (patchable_area_size)
+    {
       if (crtl->profile && flag_fentry)
-       cfun->machine->endbr_queued_at_entrance = true;
+       {
+         /* Queue patchable-area insertion to x86_function_profiler.
+            NB: If there is a queued ENDBR, x86_function_profiler
+            will also handle patchable-area.  */
+         if (!cfun->machine->insn_queued_at_entrance)
+           cfun->machine->insn_queued_at_entrance = TYPE_PATCHABLE_AREA;
+       }
       else
        {
-         cet_eb = gen_nop_endbr ();
-
-         bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
-         insn = BB_HEAD (bb);
-         emit_insn_before (cet_eb, insn);
+         rtx patchable_area
+           = gen_patchable_area (GEN_INT (patchable_area_size),
+                                 GEN_INT (crtl->patch_area_entry == 0));
+         if (endbr_insn)
+           emit_insn_after (patchable_area, endbr_insn);
+         else
+           {
+             bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
+             insn = BB_HEAD (bb);
+             emit_insn_before (patchable_area, insn);
+           }
        }
     }
 
+  if (!need_endbr)
+    return;
+
   bb = 0;
   FOR_EACH_BB_FN (bb, cfun)
     {
@@ -1991,7 +2026,6 @@ rest_of_insert_endbranch (void)
        {
          if (CALL_P (insn))
            {
-             bool need_endbr;
              need_endbr = find_reg_note (insn, REG_SETJMP, NULL) != NULL;
              if (!need_endbr && !SIBLING_CALL_P (insn))
                {
@@ -2022,8 +2056,8 @@ rest_of_insert_endbranch (void)
              /* Generate ENDBRANCH after CALL, which can return more than
                 twice, setjmp-like functions.  */
 
-             cet_eb = gen_nop_endbr ();
-             emit_insn_after_setloc (cet_eb, insn, INSN_LOCATION (insn));
+             endbr = gen_nop_endbr ();
+             emit_insn_after_setloc (endbr, insn, INSN_LOCATION (insn));
              continue;
            }
 
@@ -2053,31 +2087,30 @@ rest_of_insert_endbranch (void)
                  dest_blk = e->dest;
                  insn = BB_HEAD (dest_blk);
                  gcc_assert (LABEL_P (insn));
-                 cet_eb = gen_nop_endbr ();
-                 emit_insn_after (cet_eb, insn);
+                 endbr = gen_nop_endbr ();
+                 emit_insn_after (endbr, insn);
                }
              continue;
            }
 
          if (LABEL_P (insn) && LABEL_PRESERVE_P (insn))
            {
-             cet_eb = gen_nop_endbr ();
-             emit_insn_after (cet_eb, insn);
+             endbr = gen_nop_endbr ();
+             emit_insn_after (endbr, insn);
              continue;
            }
        }
     }
 
-  timevar_pop (TV_MACH_DEP);
-  return 0;
+  return;
 }
 
 namespace {
 
-const pass_data pass_data_insert_endbranch =
+const pass_data pass_data_insert_endbr_and_patchable_area =
 {
   RTL_PASS, /* type.  */
-  "cet", /* name.  */
+  "endbr_and_patchable_area", /* name.  */
   OPTGROUP_NONE, /* optinfo_flags.  */
   TV_MACH_DEP, /* tv_id.  */
   0, /* properties_required.  */
@@ -2087,32 +2120,41 @@ const pass_data pass_data_insert_endbranch =
   0, /* todo_flags_finish.  */
 };
 
-class pass_insert_endbranch : public rtl_opt_pass
+class pass_insert_endbr_and_patchable_area : public rtl_opt_pass
 {
 public:
-  pass_insert_endbranch (gcc::context *ctxt)
-    : rtl_opt_pass (pass_data_insert_endbranch, ctxt)
+  pass_insert_endbr_and_patchable_area (gcc::context *ctxt)
+    : rtl_opt_pass (pass_data_insert_endbr_and_patchable_area, ctxt)
   {}
 
   /* opt_pass methods: */
   virtual bool gate (function *)
     {
-      return ((flag_cf_protection & CF_BRANCH));
+      need_endbr = (flag_cf_protection & CF_BRANCH) != 0;
+      patchable_area_size = crtl->patch_area_size - crtl->patch_area_entry;
+      return need_endbr || patchable_area_size;
     }
 
   virtual unsigned int execute (function *)
     {
-      return rest_of_insert_endbranch ();
+      timevar_push (TV_MACH_DEP);
+      rest_of_insert_endbr_and_patchable_area (need_endbr,
+                                              patchable_area_size);
+      timevar_pop (TV_MACH_DEP);
+      return 0;
     }
 
-}; // class pass_insert_endbranch
+private:
+  bool need_endbr;
+  unsigned int patchable_area_size;
+}; // class pass_insert_endbr_and_patchable_area
 
 } // anon namespace
 
 rtl_opt_pass *
-make_pass_insert_endbranch (gcc::context *ctxt)
+make_pass_insert_endbr_and_patchable_area (gcc::context *ctxt)
 {
-  return new pass_insert_endbranch (ctxt);
+  return new pass_insert_endbr_and_patchable_area (ctxt);
 }
 
 /* At entry of the nearest common dominator for basic blocks with
diff --git a/gcc/config/i386/i386-passes.def b/gcc/config/i386/i386-passes.def
index 41386a13d88..d83c7b956b1 100644
--- a/gcc/config/i386/i386-passes.def
+++ b/gcc/config/i386/i386-passes.def
@@ -30,6 +30,6 @@ along with GCC; see the file COPYING3.  If not see
      CONSTM1_RTX generated by the STV pass can be CSEed.  */
   INSERT_PASS_BEFORE (pass_cse2, 1, pass_stv, true /* timode_p */);
 
-  INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_endbranch);
+  INSERT_PASS_BEFORE (pass_shorten_branches, 1, 
pass_insert_endbr_and_patchable_area);
 
   INSERT_PASS_AFTER (pass_combine, 1, pass_remove_partial_avx_dependency);
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 39fcaa0ad5f..e5574496bb7 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -89,6 +89,8 @@ extern const char *output_fp_compare (rtx_insn *, rtx*, bool, 
bool);
 extern const char *output_adjust_stack_and_probe (rtx);
 extern const char *output_probe_stack_range (rtx, rtx);
 
+extern void ix86_output_patchable_area (unsigned int, bool);
+
 extern void ix86_expand_clear (rtx);
 extern void ix86_expand_move (machine_mode, rtx[]);
 extern void ix86_expand_vector_move (machine_mode, rtx[]);
@@ -378,6 +380,7 @@ class rtl_opt_pass;
 
 extern rtl_opt_pass *make_pass_insert_vzeroupper (gcc::context *);
 extern rtl_opt_pass *make_pass_stv (gcc::context *);
-extern rtl_opt_pass *make_pass_insert_endbranch (gcc::context *);
+extern rtl_opt_pass *make_pass_insert_endbr_and_patchable_area
+  (gcc::context *);
 extern rtl_opt_pass *make_pass_remove_partial_avx_dependency
   (gcc::context *);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index c4a538ed0c8..bdfe149e39e 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1562,6 +1562,9 @@ ix86_asm_output_function_label (FILE *asm_out_file, const 
char *fname,
 {
   bool is_ms_hook = ix86_function_ms_hook_prologue (decl);
 
+  if (cfun)
+    cfun->machine->function_label_emitted = true;
+
   if (is_ms_hook)
     {
       int i, filler_count = (TARGET_64BIT ? 32 : 16);
@@ -9368,6 +9371,38 @@ ix86_output_function_epilogue (FILE *file 
ATTRIBUTE_UNUSED)
     }
 }
 
+/* Implement TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY.  */
+
+void
+ix86_print_patchable_function_entry (FILE *file,
+                                    unsigned HOST_WIDE_INT patch_area_size,
+                                    bool record_p)
+{
+  if (cfun->machine->function_label_emitted)
+    {
+      /* NB: When ix86_print_patchable_function_entry is called after
+        function table has been emitted, we have inserted or queued
+        a pseudo UNSPECV_PATCHABLE_AREA instruction at the proper
+        place.  There is nothing to do here.  */
+      return;
+    }
+
+  default_print_patchable_function_entry (file, patch_area_size,
+                                         record_p);
+}
+
+/* Output patchable area.  NB: default_print_patchable_function_entry
+   isn't available in i386.md.  */
+
+void
+ix86_output_patchable_area (unsigned int patch_area_size,
+                           bool record_p)
+{
+  default_print_patchable_function_entry (asm_out_file,
+                                         patch_area_size,
+                                         record_p);
+}
+
 /* Return a scratch register to use in the split stack prologue.  The
    split stack prologue is used for -fsplit-stack.  It is the first
    instructions in the function, even before the regular prologue.
@@ -20415,8 +20450,16 @@ current_fentry_section (const char **name)
 void
 x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
 {
-  if (cfun->machine->endbr_queued_at_entrance)
-    fprintf (file, "\t%s\n", TARGET_64BIT ? "endbr64" : "endbr32");
+  if (cfun->machine->insn_queued_at_entrance)
+    {
+      if (cfun->machine->insn_queued_at_entrance == TYPE_ENDBR)
+       fprintf (file, "\t%s\n", TARGET_64BIT ? "endbr64" : "endbr32");
+      unsigned int patch_area_size
+       = crtl->patch_area_size - crtl->patch_area_entry;
+      if (patch_area_size)
+       ix86_output_patchable_area (patch_area_size,
+                                   crtl->patch_area_entry == 0);
+    }
 
   const char *mcount_name = MCOUNT_NAME;
 
@@ -23013,6 +23056,10 @@ ix86_run_selftests (void)
 #undef TARGET_ASM_FUNCTION_EPILOGUE
 #define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue
 
+#undef TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY
+#define TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY \
+  ix86_print_patchable_function_entry
+
 #undef TARGET_ENCODE_SECTION_INFO
 #ifndef SUBTARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO ix86_encode_section_info
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 08245f64322..77575875192 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2757,6 +2757,13 @@ enum function_type
   TYPE_EXCEPTION
 };
 
+enum queued_insn_type
+{
+  TYPE_NONE = 0,
+  TYPE_ENDBR,
+  TYPE_PATCHABLE_AREA
+};
+
 struct GTY(()) machine_function {
   struct stack_local_entry *stack_locals;
   int varargs_gpr_size;
@@ -2847,8 +2854,11 @@ struct GTY(()) machine_function {
   /* Nonzero if the function places outgoing arguments on stack.  */
   BOOL_BITFIELD outgoing_args_on_stack : 1;
 
-  /* If true, ENDBR is queued at function entrance.  */
-  BOOL_BITFIELD endbr_queued_at_entrance : 1;
+  /* If true, ENDBR or patchable area is queued at function entrance.  */
+  ENUM_BITFIELD(queued_insn_type) insn_queued_at_entrance : 2;
+
+  /* If true, the function label has been emitted.  */
+  BOOL_BITFIELD function_label_emitted : 1;
 
   /* True if the function needs a stack frame.  */
   BOOL_BITFIELD stack_frame_required : 1;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index b426c21d3dd..f7ca55ab4de 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -300,6 +300,9 @@ (define_c_enum "unspecv" [
   ;; For ENQCMD and ENQCMDS support
   UNSPECV_ENQCMD
   UNSPECV_ENQCMDS
+
+  ;; For patchable area support
+  UNSPECV_PATCHABLE_AREA
 ])
 
 ;; Constants to represent rounding modes in the ROUND instruction
@@ -21135,6 +21138,20 @@ (define_insn "speculation_barrier"
   [(set_attr "type" "other")
    (set_attr "length" "3")])
 
+(define_insn "patchable_area"
+  [(unspec_volatile [(match_operand 0 "const_int_operand")
+                    (match_operand 1 "const_int_operand")]
+                   UNSPECV_PATCHABLE_AREA)]
+  ""
+{
+  ix86_output_patchable_area (INTVAL (operands[0]),
+                             INTVAL (operands[1]) != 0);
+  return "";
+}
+  [(set (attr "length") (symbol_ref "INTVAL (operands[0])"))
+   (set_attr "length_immediate" "0")
+   (set_attr "modrm" "0")])
+
 (include "mmx.md")
 (include "sse.md")
 (include "sync.md")
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-1.c 
b/gcc/testsuite/gcc.target/i386/pr93492-1.c
new file mode 100644
index 00000000000..f978d2e5220
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93492-1.c
@@ -0,0 +1,73 @@
+/* { dg-do "compile" } */
+/* { dg-options "-O1 -fcf-protection -mmanual-endbr" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Note: this test only checks the instructions in the function bodies,
+   not the placement of the patch label or nops before the function.  */
+
+/*
+**f10_none:
+**     nop
+**     ret
+*/
+void
+__attribute__ ((nocf_check,patchable_function_entry (1, 0)))
+f10_none (void)
+{
+}
+
+/*
+**f10_endbr:
+**     endbr(32|64)
+**     nop
+**     ret
+*/
+void
+__attribute__ ((cf_check,patchable_function_entry (1, 0)))
+f10_endbr (void)
+{
+}
+
+/*
+**f11_none:
+**     ret
+*/
+void
+__attribute__ ((nocf_check,patchable_function_entry (1, 1)))
+f11_none (void)
+{
+}
+
+/*
+**f11_endbr:
+**     endbr(32|64)
+**     ret
+*/
+void
+__attribute__ ((cf_check,patchable_function_entry (1, 1)))
+f11_endbr (void)
+{
+}
+
+/*
+**f21_none:
+**     nop
+**     ret
+*/
+void
+__attribute__ ((nocf_check,patchable_function_entry (2, 1)))
+f21_none (void)
+{
+}
+
+/*
+**f21_endbr:
+**     endbr(32|64)
+**     nop
+**     ret
+*/
+void
+__attribute__ ((cf_check,patchable_function_entry (2, 1)))
+f21_endbr (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-2.c 
b/gcc/testsuite/gcc.target/i386/pr93492-2.c
new file mode 100644
index 00000000000..ec26d4cc367
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93492-2.c
@@ -0,0 +1,12 @@
+/* { dg-do "compile" } */
+/* { dg-options "-O1 -fcf-protection -mmanual-endbr 
-fasynchronous-unwind-tables" } */
+
+/* Test the placement of the .LPFE1 label.  */
+
+void
+__attribute__ ((cf_check,patchable_function_entry (1, 0)))
+f10_endbr (void)
+{
+}
+
+/* { dg-final { scan-assembler 
"\t\.cfi_startproc\n\tendbr(32|64)\n.*\.LPFE1:\n\tnop\n\tret\n" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-3.c 
b/gcc/testsuite/gcc.target/i386/pr93492-3.c
new file mode 100644
index 00000000000..1f03c627120
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93492-3.c
@@ -0,0 +1,13 @@
+/* { dg-do "compile" } */
+/* { dg-require-effective-target mfentry } */
+/* { dg-options "-O1 -fcf-protection -mmanual-endbr -mfentry -pg 
-fasynchronous-unwind-tables" } */
+
+/* Test the placement of the .LPFE1 label.  */
+
+void
+__attribute__ ((cf_check,patchable_function_entry (1, 0)))
+f10_endbr (void)
+{
+}
+
+/* { dg-final { scan-assembler 
"\t\.cfi_startproc\n\tendbr(32|64)\n.*\.LPFE1:\n\tnop\n1:\tcall\t__fentry__\n\tret\n"
 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-4.c 
b/gcc/testsuite/gcc.target/i386/pr93492-4.c
new file mode 100644
index 00000000000..d193df8e66d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93492-4.c
@@ -0,0 +1,11 @@
+/* { dg-do "compile" } */
+/* { dg-options "-O1 -fpatchable-function-entry=1 
-fasynchronous-unwind-tables" } */
+
+/* Test the placement of the .LPFE1 label.  */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "\t\.cfi_startproc\n.*\.LPFE1:\n\tnop\n\tret\n" 
} } */
diff --git a/gcc/testsuite/gcc.target/i386/pr93492-5.c 
b/gcc/testsuite/gcc.target/i386/pr93492-5.c
new file mode 100644
index 00000000000..d04077c6007
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93492-5.c
@@ -0,0 +1,12 @@
+/* { dg-do "compile" } */
+/* { dg-require-effective-target mfentry } */
+/* { dg-options "-O1 -fpatchable-function-entry=1 -mfentry -pg 
-fasynchronous-unwind-tables" } */
+
+/* Test the placement of the .LPFE1 label.  */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler 
"\t\.cfi_startproc\n.*\.LPFE1:\n\tnop\n1:\tcall\t__fentry__\n\tret\n" } } */
-- 
2.26.2

Reply via email to