[3/3] S/390: Implement -mnop-mcount

Message ID 20180716074807.43653-4-iii@linux.ibm.com
State New
Headers show
Series
  • [1/3] S/390: Implement -mfentry
Related show

Commit Message

Ilya Leoshkevich July 16, 2018, 7:48 a.m.
This is the counterpart of the i386 feature introduced by
39a5a6a4: Add direct support for Linux kernel __fentry__ patching.

On i386 the profiler call sequence always consists of 1 call
instruction, so -mnop-mcount generates a single nop with the same
length as a call. For S/390 longer sequences may be used in some
cases, so -mnop-mcount generates the corresponding amount of nops.

        * gcc/config/s390/s390.c (s390_function_profiler): Generate
        nops instead of profiler call sequences.
        * gcc/config/s390/s390.opt: Add the new option.
        * gcc/testsuite/gcc.target/s390/mnop-mcount-m31-fpic.c:
        New testcase.
        * gcc/testsuite/gcc.target/s390/mnop-mcount-m31-mzarch.c
        New testcase.
        * gcc/testsuite/gcc.target/s390/mnop-mcount-m31.c
        New testcase.
        * gcc/testsuite/gcc.target/s390/mnop-mcount-m64-mfentry.c
        New testcase.
        * gcc/testsuite/gcc.target/s390/mnop-mcount-m64.c
        New testcase.
---
 gcc/config/s390/s390.c                        | 113 +++++++++++++-----
 gcc/config/s390/s390.opt                      |   5 +
 .../gcc.target/s390/mnop-mcount-m31-fpic.c    |   8 ++
 .../gcc.target/s390/mnop-mcount-m31-mzarch.c  |   8 ++
 .../gcc.target/s390/mnop-mcount-m31.c         |   8 ++
 .../gcc.target/s390/mnop-mcount-m64-mfentry.c |   8 ++
 .../gcc.target/s390/mnop-mcount-m64.c         |   8 ++
 7 files changed, 129 insertions(+), 29 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/mnop-mcount-m31-fpic.c
 create mode 100644 gcc/testsuite/gcc.target/s390/mnop-mcount-m31-mzarch.c
 create mode 100644 gcc/testsuite/gcc.target/s390/mnop-mcount-m31.c
 create mode 100644 gcc/testsuite/gcc.target/s390/mnop-mcount-m64-mfentry.c
 create mode 100644 gcc/testsuite/gcc.target/s390/mnop-mcount-m64.c

-- 
2.17.1

Comments

Andreas Krebbel July 16, 2018, 2:42 p.m. | #1
On 07/16/2018 09:48 AM, Ilya Leoshkevich wrote:
> This is the counterpart of the i386 feature introduced by

> 39a5a6a4: Add direct support for Linux kernel __fentry__ patching.

> 

> On i386 the profiler call sequence always consists of 1 call

> instruction, so -mnop-mcount generates a single nop with the same

> length as a call. For S/390 longer sequences may be used in some

> cases, so -mnop-mcount generates the corresponding amount of nops.

> 

>         * gcc/config/s390/s390.c (s390_function_profiler): Generate

>         nops instead of profiler call sequences.

>         * gcc/config/s390/s390.opt: Add the new option.

>         * gcc/testsuite/gcc.target/s390/mnop-mcount-m31-fpic.c:

>         New testcase.

>         * gcc/testsuite/gcc.target/s390/mnop-mcount-m31-mzarch.c

>         New testcase.

>         * gcc/testsuite/gcc.target/s390/mnop-mcount-m31.c

>         New testcase.

>         * gcc/testsuite/gcc.target/s390/mnop-mcount-m64-mfentry.c

>         New testcase.

>         * gcc/testsuite/gcc.target/s390/mnop-mcount-m64.c

>         New testcase.


Applied. Thanks!

Andreas

Patch

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 600501c1e27..ba18cb1c39a 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -13123,6 +13123,30 @@  s390_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
   emit_move_insn (mem, fnaddr);
 }
 
+static void
+output_asm_nops (const char *user, int hw)
+{
+  asm_fprintf (asm_out_file, "\t# NOPs for %s (%d halfwords)\n", user, hw);
+  while (hw > 0)
+    {
+      if (TARGET_CPU_ZARCH && hw >= 3)
+        {
+          output_asm_insn ("brcl\t0,0", NULL);
+          hw -= 3;
+        }
+      else if (hw >= 2)
+        {
+          output_asm_insn ("bc\t0,0", NULL);
+          hw -= 2;
+        }
+      else
+        {
+          output_asm_insn ("bcr\t0,0", NULL);
+          hw -= 1;
+        }
+    }
+}
+
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  */
 
@@ -13156,7 +13180,9 @@  s390_function_profiler (FILE *file, int labelno)
 
   if (flag_fentry)
     {
-      if (cfun->static_chain_decl)
+      if (flag_nop_mcount)
+        output_asm_nops ("-mnop-mcount", /* brasl */ 3);
+      else if (cfun->static_chain_decl)
         warning (OPT_Wcannot_profile, "nested functions cannot be profiled "
                  "with -mfentry on s390");
       else
@@ -13164,48 +13190,77 @@  s390_function_profiler (FILE *file, int labelno)
     }
   else if (TARGET_64BIT)
     {
-      output_asm_insn ("stg\t%0,%1", op);
-      output_asm_insn ("larl\t%2,%3", op);
-      output_asm_insn ("brasl\t%0,%4", op);
-      output_asm_insn ("lg\t%0,%1", op);
+      if (flag_nop_mcount)
+        output_asm_nops ("-mnop-mcount", /* stg */ 3 + /* larl */ 3 +
+                         /* brasl */ 3 + /* lg */ 3);
+      else
+        {
+          output_asm_insn ("stg\t%0,%1", op);
+          output_asm_insn ("larl\t%2,%3", op);
+          output_asm_insn ("brasl\t%0,%4", op);
+          output_asm_insn ("lg\t%0,%1", op);
+        }
     }
   else if (TARGET_CPU_ZARCH)
     {
-      output_asm_insn ("st\t%0,%1", op);
-      output_asm_insn ("larl\t%2,%3", op);
-      output_asm_insn ("brasl\t%0,%4", op);
-      output_asm_insn ("l\t%0,%1", op);
+      if (flag_nop_mcount)
+        output_asm_nops ("-mnop-mcount", /* st */ 2 + /* larl */ 3 +
+                         /* brasl */ 3 + /* l */ 2);
+      else
+        {
+          output_asm_insn ("st\t%0,%1", op);
+          output_asm_insn ("larl\t%2,%3", op);
+          output_asm_insn ("brasl\t%0,%4", op);
+          output_asm_insn ("l\t%0,%1", op);
+        }
     }
   else if (!flag_pic)
     {
       op[6] = gen_label_rtx ();
 
-      output_asm_insn ("st\t%0,%1", op);
-      output_asm_insn ("bras\t%2,%l6", op);
-      output_asm_insn (".long\t%4", op);
-      output_asm_insn (".long\t%3", op);
-      targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (op[6]));
-      output_asm_insn ("l\t%0,0(%2)", op);
-      output_asm_insn ("l\t%2,4(%2)", op);
-      output_asm_insn ("basr\t%0,%0", op);
-      output_asm_insn ("l\t%0,%1", op);
+      if (flag_nop_mcount)
+        output_asm_nops ("-mnop-mcount", /* st */ 2 + /* bras */ 2 +
+                         /* .long */ 2 + /* .long */ 2 + /* l */ 2 +
+                         /* l */ 2 + /* basr */ 1 + /* l */ 2);
+      else
+        {
+          output_asm_insn ("st\t%0,%1", op);
+          output_asm_insn ("bras\t%2,%l6", op);
+          output_asm_insn (".long\t%4", op);
+          output_asm_insn (".long\t%3", op);
+          targetm.asm_out.internal_label (file, "L",
+                                          CODE_LABEL_NUMBER (op[6]));
+          output_asm_insn ("l\t%0,0(%2)", op);
+          output_asm_insn ("l\t%2,4(%2)", op);
+          output_asm_insn ("basr\t%0,%0", op);
+          output_asm_insn ("l\t%0,%1", op);
+        }
     }
   else
     {
       op[5] = gen_label_rtx ();
       op[6] = gen_label_rtx ();
 
-      output_asm_insn ("st\t%0,%1", op);
-      output_asm_insn ("bras\t%2,%l6", op);
-      targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (op[5]));
-      output_asm_insn (".long\t%4-%l5", op);
-      output_asm_insn (".long\t%3-%l5", op);
-      targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (op[6]));
-      output_asm_insn ("lr\t%0,%2", op);
-      output_asm_insn ("a\t%0,0(%2)", op);
-      output_asm_insn ("a\t%2,4(%2)", op);
-      output_asm_insn ("basr\t%0,%0", op);
-      output_asm_insn ("l\t%0,%1", op);
+      if (flag_nop_mcount)
+        output_asm_nops ("-mnop-mcount", /* st */ 2 + /* bras */ 2 +
+                         /* .long */ 2 + /* .long */ 2 + /* lr */ 1 +
+                         /* a */ 2 + /* a */ 2 + /* basr */ 1 + /* l */ 2);
+      else
+        {
+          output_asm_insn ("st\t%0,%1", op);
+          output_asm_insn ("bras\t%2,%l6", op);
+          targetm.asm_out.internal_label (file, "L",
+                                          CODE_LABEL_NUMBER (op[5]));
+          output_asm_insn (".long\t%4-%l5", op);
+          output_asm_insn (".long\t%3-%l5", op);
+          targetm.asm_out.internal_label (file, "L",
+                                          CODE_LABEL_NUMBER (op[6]));
+          output_asm_insn ("lr\t%0,%2", op);
+          output_asm_insn ("a\t%0,0(%2)", op);
+          output_asm_insn ("a\t%2,4(%2)", op);
+          output_asm_insn ("basr\t%0,%0", op);
+          output_asm_insn ("l\t%0,%1", op);
+        }
     }
 
   if (flag_record_mcount)
diff --git a/gcc/config/s390/s390.opt b/gcc/config/s390/s390.opt
index 9a3ed651450..4214b1714c2 100644
--- a/gcc/config/s390/s390.opt
+++ b/gcc/config/s390/s390.opt
@@ -302,3 +302,8 @@  code will require a 64-bit CPU and glibc 2.29 or newer to run.
 mrecord-mcount
 Target Report Var(flag_record_mcount)
 Generate __mcount_loc section with all _mcount and __fentry__ calls.
+
+mnop-mcount
+Target Report Var(flag_nop_mcount)
+Generate mcount/__fentry__ calls as nops. To activate they need to be
+patched in.
diff --git a/gcc/testsuite/gcc.target/s390/mnop-mcount-m31-fpic.c b/gcc/testsuite/gcc.target/s390/mnop-mcount-m31-fpic.c
new file mode 100644
index 00000000000..5b00ab65668
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/mnop-mcount-m31-fpic.c
@@ -0,0 +1,8 @@ 
+/* { dg-do compile } */
+/* { dg-options "-m31 -mesa -march=g5 -fPIC -pg -mnop-mcount -Wno-deprecated" } */
+
+void
+profileme (void)
+{
+  /* { dg-final { scan-assembler "NOPs for -mnop-mcount \\(16 halfwords\\)\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0" } } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/mnop-mcount-m31-mzarch.c b/gcc/testsuite/gcc.target/s390/mnop-mcount-m31-mzarch.c
new file mode 100644
index 00000000000..b2ad9f5bced
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/mnop-mcount-m31-mzarch.c
@@ -0,0 +1,8 @@ 
+/* { dg-do compile } */
+/* { dg-options "-m31 -mzarch -pg -mnop-mcount" } */
+
+void
+profileme (void)
+{
+  /* { dg-final { scan-assembler "NOPs for -mnop-mcount \\(10 halfwords\\)\n.*brcl\t0,0\n.*brcl\t0,0\n.*brcl\t0,0\n.*bcr\t0,0" } } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/mnop-mcount-m31.c b/gcc/testsuite/gcc.target/s390/mnop-mcount-m31.c
new file mode 100644
index 00000000000..e64c8d7d7bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/mnop-mcount-m31.c
@@ -0,0 +1,8 @@ 
+/* { dg-do compile } */
+/* { dg-options "-m31 -mesa -march=g5 -pg -mnop-mcount -Wno-deprecated" } */
+
+void
+profileme (void)
+{
+  /* { dg-final { scan-assembler "NOPs for -mnop-mcount \\(15 halfwords\\)\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bcr\t0,0" } } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/mnop-mcount-m64-mfentry.c b/gcc/testsuite/gcc.target/s390/mnop-mcount-m64-mfentry.c
new file mode 100644
index 00000000000..9c1504e8d63
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/mnop-mcount-m64-mfentry.c
@@ -0,0 +1,8 @@ 
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-pg -mfentry -mnop-mcount" } */
+
+void
+profileme (void)
+{
+  /* { dg-final { scan-assembler "NOPs for -mnop-mcount \\(3 halfwords\\)\n.*brcl\t0,0" } } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/mnop-mcount-m64.c b/gcc/testsuite/gcc.target/s390/mnop-mcount-m64.c
new file mode 100644
index 00000000000..c0e3c4e91b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/mnop-mcount-m64.c
@@ -0,0 +1,8 @@ 
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-pg -mnop-mcount" } */
+
+void
+profileme (void)
+{
+  /* { dg-final { scan-assembler "NOPs for -mnop-mcount \\(12 halfwords\\)\n.*brcl\t0,0\n.*brcl\t0,0\n.*brcl\t0,0\n.*brcl\t0,0" } } */
+}