ENDBR must be the first instruction of a function.  This patch queues
ENDBR if we need to put the profiling counter call before the prologue
and generate ENDBR before the profiling counter call.

OK for trunk if there is no regressions?

H.J.
---
gcc/

        PR target/82699
        * config/i386/i386.c (ix86_profile_before_prologue): Add a
        prototype.
        (rest_of_insert_endbranch): Set endbr_queued_at_entrance to
        true and don't insert ENDBR if ix86_profile_before_prologue ()
        returns true.
        (x86_function_profiler): Insert ENDBR if endbr_queued_at_entrance
        is true.

gcc/testsuite/

        PR target/82699
        * gcc.target/i386/pr82699-1.c: New file.
        * gcc.target/i386/pr82699-2.c: Likewise.
        * gcc.target/i386/pr82699-3.c: Likewise.
        * gcc.target/i386/pr82699-4.c: Likewise.
---
 gcc/config/i386/i386.c                    | 18 ++++++++++++++----
 gcc/config/i386/i386.h                    |  3 +++
 gcc/testsuite/gcc.target/i386/pr82699-1.c | 11 +++++++++++
 gcc/testsuite/gcc.target/i386/pr82699-2.c | 11 +++++++++++
 gcc/testsuite/gcc.target/i386/pr82699-3.c | 11 +++++++++++
 gcc/testsuite/gcc.target/i386/pr82699-4.c | 11 +++++++++++
 6 files changed, 61 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr82699-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr82699-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr82699-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr82699-4.c

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index d2188ad6086..4e6936cd987 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -101,6 +101,7 @@ static void ix86_print_operand_address_as (FILE *, rtx, 
addr_space_t, bool);
 static bool ix86_save_reg (unsigned int, bool, bool);
 static bool ix86_function_naked (const_tree);
 static bool ix86_notrack_prefixed_insn_p (rtx);
+static bool ix86_profile_before_prologue (void);
 
 #ifndef CHECK_STACK_LIMIT
 #define CHECK_STACK_LIMIT (-1)
@@ -2590,11 +2591,16 @@ rest_of_insert_endbranch (void)
                         TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
       && !cgraph_node::get (cfun->decl)->only_called_directly_p ())
     {
-      cet_eb = gen_nop_endbr ();
+      if (ix86_profile_before_prologue ())
+       cfun->machine->endbr_queued_at_entrance = true;
+      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);
+         bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
+         insn = BB_HEAD (bb);
+         emit_insn_before (cet_eb, insn);
+       }
     }
 
   bb = 0;
@@ -40427,6 +40433,10 @@ x86_function_profiler (FILE *file, int labelno 
ATTRIBUTE_UNUSED)
 {
   const char *mcount_name = (flag_fentry ? MCOUNT_NAME_BEFORE_PROLOGUE
                                         : MCOUNT_NAME);
+
+  if (cfun->machine->endbr_queued_at_entrance)
+    fprintf (file, "\t%s\n", TARGET_64BIT ? "endbr64" : "endbr32");
+
   if (TARGET_64BIT)
     {
 #ifndef NO_PROFILE_COUNTERS
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 27fc9f08cc7..925557d32cb 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2581,6 +2581,9 @@ 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;
+
   /* During prologue/epilogue generation, the current frame state.
      Otherwise, the frame state at the end of the prologue.  */
   struct machine_frame_state fs;
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-1.c 
b/gcc/testsuite/gcc.target/i386/pr82699-1.c
new file mode 100644
index 00000000000..4fc404753e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82699-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fcf-protection -mcet -pg 
-fasynchronous-unwind-tables" } */
+/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
+
+extern int bar (int);
+
+int
+foo (int i)
+{
+  return bar (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-2.c 
b/gcc/testsuite/gcc.target/i386/pr82699-2.c
new file mode 100644
index 00000000000..4fb9cb9e68b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82699-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fcf-protection -mcet -pg -mfentry 
-fasynchronous-unwind-tables" } */
+/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
+
+extern int bar (int);
+
+int
+foo (int i)
+{
+  return bar (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-3.c 
b/gcc/testsuite/gcc.target/i386/pr82699-3.c
new file mode 100644
index 00000000000..92d84ee4ab5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82699-3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fcf-protection -mcet -pg 
-fasynchronous-unwind-tables" } */
+/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
+
+extern int bar (int);
+
+int
+foo (int i)
+{
+  return bar (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-4.c 
b/gcc/testsuite/gcc.target/i386/pr82699-4.c
new file mode 100644
index 00000000000..415ce3b913a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82699-4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-options "-O2 -fpic -fcf-protection -mcet -pg -mfentry 
-fasynchronous-unwind-tables" } */
+/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
+
+extern int bar (int);
+
+int
+foo (int i)
+{
+  return bar (i);
+}
-- 
2.13.6

Reply via email to