This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] i386: Don't generate ENDBR if function is only called directly
On Tue, Oct 24, 2017 at 2:33 AM, Uros Bizjak <ubizjak@gmail.com> wrote:
> On Tue, Oct 24, 2017 at 10:39 AM, Tsimbalist, Igor V
> <igor.v.tsimbalist@intel.com> wrote:
>> OK.
>
> +/* { dg-final { scan-assembler-times "endbr32" 2 { target ia32 } } } */
> +/* { dg-final { scan-assembler-times "endbr64" 2 { target { ! ia32 } } } } */
>
> I think we can only check for {\mendbr} in the testcases. There are
> already plenty of testcases that check for the correct instruction.
>
> Otherwise, LGTM
>
This is what I checked in.
Thanks.
--
H.J.
From 81893b3645f6f0771771690e58629d3d233fcdb2 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sun, 22 Oct 2017 06:09:27 -0700
Subject: [PATCH] i386: Don't insert ENDBR at function entrance when called
directly
There is no need to insert ENDBR instruction at function entrance if
function is only called directly.
gcc/
PR target/82659
* config/i386/i386.c (rest_of_insert_endbranch): Don't insert
ENDBR instruction at function entrance if function is only
called directly.
gcc/testsuite/
PR target/82659
* gcc.target/i386/cet-label-2.c: New test.
* gcc.target/i386/cet-sjlj-4.c: Likewise.
* gcc.target/i386/cet-sjlj-5.c: Likewise.
* gcc.target/i386/cet-switch-3.c: Likewise.
* gcc.target/i386/pr82659-1.c: Likewise.
* gcc.target/i386/pr82659-2.c: Likewise.
* gcc.target/i386/pr82659-3.c: Likewise.
* gcc.target/i386/pr82659-4.c: Likewise.
* gcc.target/i386/pr82659-5.c: Likewise.
* gcc.target/i386/pr82659-6.c: Likewise.
---
gcc/config/i386/i386.c | 3 +-
gcc/testsuite/gcc.target/i386/cet-label-2.c | 24 ++++++++++++++
gcc/testsuite/gcc.target/i386/cet-sjlj-4.c | 45 ++++++++++++++++++++++++++
gcc/testsuite/gcc.target/i386/cet-sjlj-5.c | 48 ++++++++++++++++++++++++++++
gcc/testsuite/gcc.target/i386/cet-switch-3.c | 34 ++++++++++++++++++++
gcc/testsuite/gcc.target/i386/pr82659-1.c | 18 +++++++++++
gcc/testsuite/gcc.target/i386/pr82659-2.c | 17 ++++++++++
gcc/testsuite/gcc.target/i386/pr82659-3.c | 20 ++++++++++++
gcc/testsuite/gcc.target/i386/pr82659-4.c | 14 ++++++++
gcc/testsuite/gcc.target/i386/pr82659-5.c | 10 ++++++
gcc/testsuite/gcc.target/i386/pr82659-6.c | 18 +++++++++++
11 files changed, 250 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/i386/cet-label-2.c
create mode 100644 gcc/testsuite/gcc.target/i386/cet-sjlj-4.c
create mode 100644 gcc/testsuite/gcc.target/i386/cet-sjlj-5.c
create mode 100644 gcc/testsuite/gcc.target/i386/cet-switch-3.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr82659-1.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr82659-2.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr82659-3.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr82659-4.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr82659-5.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr82659-6.c
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 72caf62bbf8..c75c8ef95e5 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2587,7 +2587,8 @@ rest_of_insert_endbranch (void)
nocf_check attribute. This will allow to reduce the number of EB. */
if (!lookup_attribute ("nocf_check",
- TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl))))
+ TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
+ && !cgraph_node::get (cfun->decl)->only_called_directly_p ())
{
cet_eb = gen_nop_endbr ();
diff --git a/gcc/testsuite/gcc.target/i386/cet-label-2.c b/gcc/testsuite/gcc.target/i386/cet-label-2.c
new file mode 100644
index 00000000000..c7f79819079
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cet-label-2.c
@@ -0,0 +1,24 @@
+/* Verify that CET works. */
+/* { dg-do compile } */
+/* { dg-options "-O -fcf-protection -mcet" } */
+/* { dg-final { scan-assembler-times "endbr32" 3 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "endbr64" 3 { target { ! ia32 } } } } */
+
+__attribute__ ((noinline, noclone))
+static int
+func (int arg)
+{
+ static void *array[] = { &&foo, &&bar };
+
+ goto *array[arg];
+foo:
+ return arg*111;
+bar:
+ return arg*777;
+}
+
+int
+foo (int arg)
+{
+ return func (arg);
+}
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-4.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-4.c
new file mode 100644
index 00000000000..d41406fde1f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-4.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fcf-protection -mcet" } */
+/* { dg-final { scan-assembler-times "endbr32" 3 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "endbr64" 3 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "rdssp\[dq]" 2 } } */
+/* { dg-final { scan-assembler-times "incssp\[dq]" 1 } } */
+
+/* Based on gcc.dg/setjmp-3.c. */
+
+void *buf[5];
+
+extern void abort (void);
+
+void
+raise0 (void)
+{
+ __builtin_longjmp (buf, 1);
+}
+
+__attribute__ ((noinline, noclone))
+static int
+execute (int cmd)
+{
+ int last = 0;
+
+ if (__builtin_setjmp (buf) == 0)
+ while (1)
+ {
+ last = 1;
+ raise0 ();
+ }
+
+ if (last == 0)
+ return 0;
+ else
+ return cmd;
+}
+
+int main(void)
+{
+ if (execute (1) == 0)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-5.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-5.c
new file mode 100644
index 00000000000..12ea9f4e442
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-5.c
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fcf-protection -mcet" } */
+/* { dg-final { scan-assembler-times "endbr32" 2 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "endbr64" 2 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "call _setjmp" 1 } } */
+/* { dg-final { scan-assembler-times "call longjmp" 1 } } */
+
+#include <stdio.h>
+#include <setjmp.h>
+
+jmp_buf buf;
+static int bar (int);
+
+__attribute__ ((noinline, noclone))
+static int
+foo (int i)
+{
+ int j = i * 11;
+
+ if (!setjmp (buf))
+ {
+ j += 33;
+ printf ("After setjmp: j = %d\n", j);
+ bar (j);
+ }
+
+ return j + i;
+}
+
+__attribute__ ((noinline, noclone))
+static int
+bar (int i)
+{
+ int j = i;
+
+ j -= 111;
+ printf ("In longjmp: j = %d\n", j);
+ longjmp (buf, 1);
+
+ return j;
+}
+
+int
+main ()
+{
+ foo (10);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/cet-switch-3.c b/gcc/testsuite/gcc.target/i386/cet-switch-3.c
new file mode 100644
index 00000000000..9b1b4369582
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cet-switch-3.c
@@ -0,0 +1,34 @@
+/* Verify that CET works. */
+/* { dg-do compile } */
+/* { dg-options "-O -fcf-protection -mcet -mcet-switch" } */
+/* { dg-final { scan-assembler-times "endbr32" 12 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "endbr64" 12 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "\[ \t]+jmp\[ \t]+\[*]" 1 } } */
+
+void func2 (int);
+
+__attribute__ ((noinline, noclone))
+static int
+func1 (int arg)
+{
+ switch (arg)
+ {
+ case 1: func2 (arg*100);
+ case 2: func2 (arg*300);
+ case 5: func2 (arg*500);
+ case 8: func2 (arg*700);
+ case 7: func2 (arg*900);
+ case -1: func2 (arg*-100);
+ case -2: func2 (arg*-300);
+ case -5: func2 (arg*-500);
+ case -7: func2 (arg*-700);
+ case -9: func2 (arg*-900);
+ }
+ return 0;
+}
+
+int
+foo (int arg)
+{
+ return func1 (arg);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82659-1.c b/gcc/testsuite/gcc.target/i386/pr82659-1.c
new file mode 100644
index 00000000000..485771d0f38
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82659-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection -mcet" } */
+/* { dg-final { scan-assembler-times {\mendbr} 1 } } */
+
+extern int x;
+
+static void
+__attribute__ ((noinline, noclone))
+test (int i)
+{
+ x = i;
+}
+
+void
+bar (int i)
+{
+ test (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82659-2.c b/gcc/testsuite/gcc.target/i386/pr82659-2.c
new file mode 100644
index 00000000000..7afffa440aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82659-2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection -mcet" } */
+/* { dg-final { scan-assembler-times {\mendbr} 2 } } */
+
+extern int x;
+
+void
+test (int i)
+{
+ x = i;
+}
+
+void
+bar (int i)
+{
+ test (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82659-3.c b/gcc/testsuite/gcc.target/i386/pr82659-3.c
new file mode 100644
index 00000000000..5f97b314092
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82659-3.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection -mcet" } */
+/* { dg-final { scan-assembler-times {\mendbr} 2 } } */
+
+extern int x;
+
+static void
+__attribute__ ((noinline, noclone))
+test (int i)
+{
+ x = i;
+}
+
+extern __typeof (test) foo __attribute__ ((alias ("test")));
+
+void
+bar (int i)
+{
+ test (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82659-4.c b/gcc/testsuite/gcc.target/i386/pr82659-4.c
new file mode 100644
index 00000000000..c3cacaccbef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82659-4.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection -mcet" } */
+/* { dg-final { scan-assembler-times {\mendbr} 2 } } */
+
+static void
+test (void)
+{
+}
+
+void *
+bar (void)
+{
+ return test;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82659-5.c b/gcc/testsuite/gcc.target/i386/pr82659-5.c
new file mode 100644
index 00000000000..95413671d5c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82659-5.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection -mcet" } */
+/* { dg-final { scan-assembler-times {\mendbr} 1 } } */
+
+static void
+test (void)
+{
+}
+
+void (*test_p) (void) = test;
diff --git a/gcc/testsuite/gcc.target/i386/pr82659-6.c b/gcc/testsuite/gcc.target/i386/pr82659-6.c
new file mode 100644
index 00000000000..51fc1a9f5c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82659-6.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection -mcet" } */
+/* { dg-final { scan-assembler-times {\mendbr} 2 } } */
+
+extern int x;
+
+ __attribute__ ((visibility ("hidden")))
+void
+test (int i)
+{
+ x = i;
+}
+
+void
+bar (int i)
+{
+ test (i);
+}
--
2.13.6