This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] S390: Nested functions can be hotpatched like all other functions.


The attached patch removes the special handling for nested
functions regarding the hotpatch feature on S390, i.e. nested
functions are made hotpatchable by default.

This also fixes a bug that caused part of the hotpatch prologue
being generated for nested functions.  A corresponding test case
is added.

The patch also cleans up the source code comments of the hotpatch
feature.

The patch is provided for 5.0 and as backports for 4.8 and 4.9.
For some reason 4.8 was missing a couple minor changes from 5.0,
so the first patch for 4.8 corrects this, and the real change is
added on top of that.

--

Accidentally, we have committed this patch before posting it.
Sorry for that.

Common ChangeLog:
-----------------

gcc/ChangeLog:

        * config/s390/s390.c (s390_function_num_hotpatch_hw): Allow hotpatching
        nested functions.
        (s390_reorg): Adapt to new signature of s390_function_num_hotpatch_hw.
        (s390_asm_output_function_label): Adapt to new signature of
        s390_function_num_hotpatch_hw
        Optimise the code generating assembler output.
        Add comments to assembler file.

gcc/testsuite/ChangeLog:

        * gcc.target/s390/hotpatch-25.c: New test.
        * gcc.target/s390/hotpatch-1.c: Update test.
        * gcc.target/s390/hotpatch-10.c: Update test.
        * gcc.target/s390/hotpatch-11.c: Update test.
        * gcc.target/s390/hotpatch-12.c: Update test.
        * gcc.target/s390/hotpatch-13.c: Update test.
        * gcc.target/s390/hotpatch-14.c: Update test.
        * gcc.target/s390/hotpatch-15.c: Update test.
        * gcc.target/s390/hotpatch-16.c: Update test.
        * gcc.target/s390/hotpatch-17.c: Update test.
        * gcc.target/s390/hotpatch-18.c: Update test.
        * gcc.target/s390/hotpatch-19.c: Update test.
        * gcc.target/s390/hotpatch-2.c: Update test.
        * gcc.target/s390/hotpatch-21.c: Update test.
        * gcc.target/s390/hotpatch-22.c: Update test.
        * gcc.target/s390/hotpatch-23.c: Update test.
        * gcc.target/s390/hotpatch-24.c: Update test.
        * gcc.target/s390/hotpatch-3.c: Update test.
        * gcc.target/s390/hotpatch-4.c: Update test.
        * gcc.target/s390/hotpatch-5.c: Update test.
        * gcc.target/s390/hotpatch-6.c: Update test.
        * gcc.target/s390/hotpatch-7.c: Update test.
        * gcc.target/s390/hotpatch-8.c: Update test.
        * gcc.target/s390/hotpatch-9.c: Update test.
        * gcc.target/s390/hotpatch-compile-16.c: Update test.

ChangeLog for the additional 4.8 changes:
-----------------------------------------

gcc/ChangeLog:

        * config/s390/s390.c (s390_function_num_hotpatch_hw): Remove special
        cases for not hotpatching main () and artificial functions.

gcc/testsuite/ChangeLog:

        * gcc.target/s390/hotpatch-compile-16.c: Remove include of stdio.h.

Ciao

Dominik ^_^  ^_^

-- 

Dominik Vogt
IBM Germany
>From a5947f5201b8d1ef7b52cf2cf02cac8365005c77 Mon Sep 17 00:00:00 2001
From: Dominik Vogt <vogt@linux.vnet.ibm.com>
Date: Fri, 27 Mar 2015 11:41:56 +0100
Subject: [PATCH] S390: Nested functions can be hotpatched like all other
 functions.

Also add comments to assembler files to mark the code inserted for hotpatching.
---
 gcc/config/s390/s390.c                             | 53 ++++++++++------------
 gcc/testsuite/gcc.target/s390/hotpatch-1.c         |  3 ++
 gcc/testsuite/gcc.target/s390/hotpatch-10.c        |  3 ++
 gcc/testsuite/gcc.target/s390/hotpatch-11.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-12.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-13.c        |  4 ++
 gcc/testsuite/gcc.target/s390/hotpatch-14.c        |  3 ++
 gcc/testsuite/gcc.target/s390/hotpatch-15.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-16.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-17.c        |  3 ++
 gcc/testsuite/gcc.target/s390/hotpatch-18.c        |  3 ++
 gcc/testsuite/gcc.target/s390/hotpatch-19.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-2.c         |  4 +-
 gcc/testsuite/gcc.target/s390/hotpatch-21.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-22.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-23.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-24.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-25.c        | 33 ++++++++++++++
 gcc/testsuite/gcc.target/s390/hotpatch-3.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-4.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-5.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-6.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-7.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-8.c         |  3 ++
 gcc/testsuite/gcc.target/s390/hotpatch-9.c         |  2 +
 .../gcc.target/s390/hotpatch-compile-16.c          |  4 +-
 26 files changed, 110 insertions(+), 36 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/hotpatch-25.c

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index d2b8704..7d16048 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -5234,21 +5234,18 @@ print_shift_count_operand (FILE *file, rtx op)
     fprintf (file, "(%s)", reg_names[REGNO (base)]);
 }
 
-/* Returns false if the function should not be made hotpatchable.
-   Otherwise it assigns the number of NOP halfwords to be emitted
-   before and after the function label to hw_before and hw_after.
-   Both must not be NULL.  */
+/* Assigns the number of NOP halfwords to be emitted before and after the
+   function label to *HW_BEFORE and *HW_AFTER.  Both pointers must not be NULL.
+   If hotpatching is disabled for the function, the values are set to zero.
+*/
 
-static bool
+static void
 s390_function_num_hotpatch_hw (tree decl,
 			       int *hw_before,
 			       int *hw_after)
 {
   tree attr;
 
-  *hw_before = 0;
-  *hw_after = 0;
-
   attr = lookup_attribute ("hotpatch", DECL_ATTRIBUTES (decl));
 
   /* Handle the arguments of the hotpatch attribute.  The values
@@ -5267,18 +5264,6 @@ s390_function_num_hotpatch_hw (tree decl,
       *hw_before = s390_hotpatch_hw_before_label;
       *hw_after = s390_hotpatch_hw_after_label;
     }
-
-  if (*hw_before == 0 && *hw_after == 0)
-    return false;
-
-  if (decl_function_context (decl) != NULL_TREE)
-    {
-      warning_at (DECL_SOURCE_LOCATION (decl), OPT_mhotpatch_,
-		  "hotpatching is not compatible with nested functions");
-      return false;
-    }
-
-  return true;
 }
 
 /* Write the extra assembler code needed to declare a function properly.  */
@@ -5288,12 +5273,9 @@ s390_asm_output_function_label (FILE *asm_out_file, const char *fname,
 				tree decl)
 {
   int hw_before, hw_after;
-  bool hotpatch_p = (decl
-		     ? s390_function_num_hotpatch_hw (decl,
-						      &hw_before, &hw_after)
-		     : false);
 
-  if (hotpatch_p)
+  s390_function_num_hotpatch_hw (decl, &hw_before, &hw_after);
+  if (hw_before > 0)
     {
       unsigned int function_alignment;
       int i;
@@ -5301,22 +5283,35 @@ s390_asm_output_function_label (FILE *asm_out_file, const char *fname,
       /* Add a trampoline code area before the function label and initialize it
 	 with two-byte nop instructions.  This area can be overwritten with code
 	 that jumps to a patched version of the function.  */
-      for (i = 0; i < hw_before; i++)
-	asm_fprintf (asm_out_file, "\tnopr\t%%r7\n");
+      asm_fprintf (asm_out_file, "\tnopr\t%%r7"
+		   "\t# pre-label NOPs for hotpatch (%d halfwords)\n",
+		   hw_before);
+      for (i = 1; i < hw_before; i++)
+	fputs ("\tnopr\t%r7\n", asm_out_file);
+
       /* Note:  The function label must be aligned so that (a) the bytes of the
 	 following nop do not cross a cacheline boundary, and (b) a jump address
 	 (eight bytes for 64 bit targets, 4 bytes for 32 bit targets) can be
 	 stored directly before the label without crossing a cacheline
 	 boundary.  All this is necessary to make sure the trampoline code can
-	 be changed atomically.  */
+	 be changed atomically.
+	 This alignment is done automatically using the FOUNCTION_BOUNDARY, but
+	 if there are NOPs before the function label, the alignment is placed
+	 before them.  So it is necessary to duplicate the alignment after the
+	 NOPs.  */
       function_alignment = MAX (8, DECL_ALIGN (decl) / BITS_PER_UNIT);
       if (! DECL_USER_ALIGN (decl))
 	function_alignment = MAX (function_alignment,
 				  (unsigned int) align_functions);
+      fputs ("\t# alignment for hotpatch\n", asm_out_file);
       ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (function_alignment));
     }
 
   ASM_OUTPUT_LABEL (asm_out_file, fname);
+  if (hw_after > 0)
+    asm_fprintf (asm_out_file,
+		 "\t# post-label NOPs for hotpatch (%d halfwords)\n",
+		 hw_after);
 }
 
 /* Output machine-dependent UNSPECs occurring in address constant X
@@ -11491,7 +11486,7 @@ s390_reorg (void)
     {
       rtx_insn *insn;
 
-      /* Inject nops for hotpatching. */
+      /* Insert NOPs for hotpatching. */
       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
 	{
 	  if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-1.c b/gcc/testsuite/gcc.target/s390/hotpatch-1.c
index 4e29817..b14fa90 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-1.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-1.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-10.c b/gcc/testsuite/gcc.target/s390/hotpatch-10.c
index 352c9d5..a990c4c 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-10.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-10.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-11.c b/gcc/testsuite/gcc.target/s390/hotpatch-11.c
index beb8738..6f8a52b 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-11.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-11.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-12.c b/gcc/testsuite/gcc.target/s390/hotpatch-12.c
index d109478..b73ca90 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-12.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-12.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(999 halfwords)" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 999 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-13.c b/gcc/testsuite/gcc.target/s390/hotpatch-13.c
index 9ac9f84..150667a 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-13.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-13.c
@@ -12,6 +12,10 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler "alignment for hotpatch" } } */
+/* { dg-final { scan-assembler-times "\.align\t8" 2 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-14.c b/gcc/testsuite/gcc.target/s390/hotpatch-14.c
index 209e4ac..c5f118c 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-14.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-14.c
@@ -12,6 +12,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-15.c b/gcc/testsuite/gcc.target/s390/hotpatch-15.c
index 109034e..ef0fb74 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-15.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-15.c
@@ -12,6 +12,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-16.c b/gcc/testsuite/gcc.target/s390/hotpatch-16.c
index b01c1c3..a34bf95 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-16.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-16.c
@@ -12,6 +12,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-17.c b/gcc/testsuite/gcc.target/s390/hotpatch-17.c
index ce0b950..66ac725 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-17.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-17.c
@@ -12,6 +12,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-18.c b/gcc/testsuite/gcc.target/s390/hotpatch-18.c
index 9a24d5e..8b076a4 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-18.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-18.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-19.c b/gcc/testsuite/gcc.target/s390/hotpatch-19.c
index 3586da2..6993c7e 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-19.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-19.c
@@ -18,6 +18,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-2.c b/gcc/testsuite/gcc.target/s390/hotpatch-2.c
index 18be5aa..67189f8 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-2.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-2.c
@@ -11,7 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(1 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
-/* { dg-final { scan-assembler-times "\.align\t8" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-21.c b/gcc/testsuite/gcc.target/s390/hotpatch-21.c
index d72dee3..e909990 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-21.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-21.c
@@ -11,4 +11,4 @@ void __attribute__ ((aligned(512))) hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t512" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-22.c b/gcc/testsuite/gcc.target/s390/hotpatch-22.c
index 6507466..d89d779 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-22.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-22.c
@@ -11,4 +11,4 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t1024" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-23.c b/gcc/testsuite/gcc.target/s390/hotpatch-23.c
index 7dce5b8..1e05d12 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-23.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-23.c
@@ -11,4 +11,4 @@ void __attribute__ ((aligned(2048))) hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t2048" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-24.c b/gcc/testsuite/gcc.target/s390/hotpatch-24.c
index 4d6815c..fc64274 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-24.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-24.c
@@ -11,4 +11,4 @@ void __attribute__ ((aligned(4096))) hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t4096" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-25.c b/gcc/testsuite/gcc.target/s390/hotpatch-25.c
new file mode 100644
index 0000000..e9257e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-25.c
@@ -0,0 +1,33 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch" } */
+
+typedef long (*fn_t)(void);
+
+__attribute__ ((hotpatch(1,2)))
+fn_t outer(void)
+{
+  __attribute__ ((hotpatch(4,8)))
+  long nested1(void)
+  {
+    __attribute__ ((hotpatch(16,32)))
+    long nested2(void)
+    {
+      return 2;
+    }
+    return (long)(void *)nested2;
+  }
+
+  return nested1;
+}
+
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "pre-label.*(4 halfwords)" } } */
+/* { dg-final { scan-assembler "pre-label.*(16 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(8 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(32 halfwords)" } } */
+/* { dg-final { scan-assembler-times "alignment for hotpatch" 3 } } */
+/* { dg-final { scan-assembler-times "\.align\t8" 6 } } */
+/* { dg-final { scan-assembler "nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-3.c b/gcc/testsuite/gcc.target/s390/hotpatch-3.c
index 8a2ab53..ec4a978 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-3.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-3.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-4.c b/gcc/testsuite/gcc.target/s390/hotpatch-4.c
index 9a69459..d55e71d 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-4.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-4.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(3 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-5.c b/gcc/testsuite/gcc.target/s390/hotpatch-5.c
index b3d990f..f77d83a 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-5.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-5.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(4 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-6.c b/gcc/testsuite/gcc.target/s390/hotpatch-6.c
index 10ba558..330cf5d 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-6.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-6.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(5 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-7.c b/gcc/testsuite/gcc.target/s390/hotpatch-7.c
index edf67d3..2f24e3cc 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-7.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-7.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(6 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 2 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-8.c b/gcc/testsuite/gcc.target/s390/hotpatch-8.c
index a179c4a..7b266bd 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-8.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-8.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(3 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-9.c b/gcc/testsuite/gcc.target/s390/hotpatch-9.c
index c4e21f2..c0ad319 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-9.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-9.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(4 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 2 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
index 3c5c782..2e8291e 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
@@ -1,4 +1,4 @@
-/* A warning will be issued when requesting hotpatching on a nested function.  */
+/* Functional tests for the function hotpatching feature.  */
 
 /* { dg-do compile } */
 /* { dg-options "-O3 -mzarch" } */
@@ -17,7 +17,7 @@ fn_t hp1(void)
 fn_t hp2(void)
 {
   __attribute__ ((hotpatch(1,2)))
-  int nested2(void) /* { dg-warning "hotpatching is not compatible with nested functions" } */
+  int nested2(void)
   { return 2; }
 
   return nested2;
-- 
2.3.0

>From cac223aab2834d8f1e0e384d3772c153a3ce0de1 Mon Sep 17 00:00:00 2001
From: Dominik Vogt <vogt@linux.vnet.ibm.com>
Date: Fri, 27 Mar 2015 11:41:56 +0100
Subject: [PATCH] S390: Nested functions can be hotpatched like all other
 functions.

Also add comments to assembler files to mark the code inserted for hotpatching.
---
 gcc/config/s390/s390.c                             | 66 ++++++++++------------
 gcc/testsuite/gcc.target/s390/hotpatch-1.c         |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-10.c        |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-11.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-12.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-13.c        |  4 ++
 gcc/testsuite/gcc.target/s390/hotpatch-14.c        |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-15.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-16.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-17.c        |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-18.c        |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-19.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-2.c         |  4 +-
 gcc/testsuite/gcc.target/s390/hotpatch-21.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-22.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-23.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-24.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-25.c        | 33 +++++++++++
 gcc/testsuite/gcc.target/s390/hotpatch-3.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-4.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-5.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-6.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-7.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-8.c         |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-9.c         |  2 +
 .../gcc.target/s390/hotpatch-compile-16.c          |  4 +-
 26 files changed, 116 insertions(+), 43 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/hotpatch-25.c

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 9717f22..7a9c31f 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -5253,51 +5253,35 @@ get_some_local_dynamic_name (void)
   gcc_unreachable ();
 }
 
-/* Returns false if the function should not be made hotpatchable.
-   Otherwise it assigns the number of NOP halfwords to be emitted
-   before and after the function label to hw_before and hw_after.
-   Both must not be NULL.  */
+/* Assigns the number of NOP halfwords to be emitted before and after the
+   function label to *HW_BEFORE and *HW_AFTER.  Both pointers must not be NULL.
+   If hotpatching is disabled for the function, the values are set to zero.
+*/
 
-static bool
+static void
 s390_function_num_hotpatch_hw (tree decl,
 			       int *hw_before,
 			       int *hw_after)
 {
   tree attr;
 
-  *hw_before = 0;
-  *hw_after = 0;
-
   attr = lookup_attribute ("hotpatch", DECL_ATTRIBUTES (decl));
 
-  /* Handle the arguments of the hotpatch attribute.  The values
-     specified via attribute might override the cmdline argument
-     values.  */
   if (attr)
     {
       tree args = TREE_VALUE (attr);
 
+      /* If the hotpatch attribute is present, its values are used even if the
+	 -mhotpatch cmdline option is used.  */
       *hw_before = TREE_INT_CST_LOW (TREE_VALUE (args));
       *hw_after = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args)));
     }
   else
     {
-      /* Use the values specified by the cmdline arguments.  */
+      /* Values specified by the -mhotpatch cmdline option.  */
       *hw_before = s390_hotpatch_hw_before_label;
       *hw_after = s390_hotpatch_hw_after_label;
     }
-
-  if (*hw_before == 0 && *hw_after == 0)
-    return false;
-
-  if (decl_function_context (decl) != NULL_TREE)
-    {
-      warning_at (DECL_SOURCE_LOCATION (decl), OPT_mhotpatch_,
-		  "hotpatching is not compatible with nested functions");
-      return false;
-    }
-
-  return true;
 }
 
 /* Write the extra assembler code needed to declare a function properly.  */
@@ -5307,35 +5291,45 @@ s390_asm_output_function_label (FILE *asm_out_file, const char *fname,
 				tree decl)
 {
   int hw_before, hw_after;
-  bool hotpatch_p = (decl
-		     ? s390_function_num_hotpatch_hw (decl,
-						      &hw_before, &hw_after)
-		     : false);
 
-  if (hotpatch_p)
+  s390_function_num_hotpatch_hw (decl, &hw_before, &hw_after);
+  if (hw_before > 0)
     {
       unsigned int function_alignment;
       int i;
 
-      /* Add a trampoline code area before the function label and initialize it
-	 with two-byte nop instructions.  This area can be overwritten with code
+      /* Add trampoline code area before the function label and initialize it
+	 with two-byte NOP instructions.  This area can be overwritten with code
 	 that jumps to a patched version of the function.  */
-      for (i = 0; i < hw_before; i++)
-	asm_fprintf (asm_out_file, "\tnopr\t%%r7\n");
+      asm_fprintf (asm_out_file, "\tnopr\t%%r7"
+		   "\t# pre-label NOPs for hotpatch (%d halfwords)\n",
+		   hw_before);
+      for (i = 1; i < hw_before; i++)
+	fputs ("\tnopr\t%r7\n", asm_out_file);
+
       /* Note:  The function label must be aligned so that (a) the bytes of the
-	 following nop do not cross a cacheline boundary, and (b) a jump address
+	 following NOP do not cross a cacheline boundary, and (b) a jump address
 	 (eight bytes for 64 bit targets, 4 bytes for 32 bit targets) can be
 	 stored directly before the label without crossing a cacheline
 	 boundary.  All this is necessary to make sure the trampoline code can
-	 be changed atomically.  */
+	 be changed atomically.
+	 This alignment is done automatically using the FOUNCTION_BOUNDARY
+	 macro, but if there are NOPs before the function label, the alignment
+	 is placed before them.  So it is necessary to duplicate the alignment
+	 after the NOPs.  */
       function_alignment = MAX (8, DECL_ALIGN (decl) / BITS_PER_UNIT);
       if (! DECL_USER_ALIGN (decl))
 	function_alignment = MAX (function_alignment,
 				  (unsigned int) align_functions);
+      fputs ("\t# alignment for hotpatch\n", asm_out_file);
       ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (function_alignment));
     }
 
   ASM_OUTPUT_LABEL (asm_out_file, fname);
+  if (hw_after > 0)
+    asm_fprintf (asm_out_file,
+		 "\t# post-label NOPs for hotpatch (%d halfwords)\n",
+		 hw_after);
 }
 
 /* Output machine-dependent UNSPECs occurring in address constant X
@@ -11454,7 +11448,7 @@ s390_reorg (void)
     {
       rtx insn;
 
-      /* Inject nops for hotpatching. */
+      /* Insert NOPs for hotpatching. */
       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
 	{
 	  if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-1.c b/gcc/testsuite/gcc.target/s390/hotpatch-1.c
index 4e29817..b14fa90 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-1.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-1.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-10.c b/gcc/testsuite/gcc.target/s390/hotpatch-10.c
index 352c9d5..a990c4c 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-10.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-10.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-11.c b/gcc/testsuite/gcc.target/s390/hotpatch-11.c
index beb8738..6f8a52b 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-11.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-11.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-12.c b/gcc/testsuite/gcc.target/s390/hotpatch-12.c
index d109478..b73ca90 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-12.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-12.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(999 halfwords)" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 999 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-13.c b/gcc/testsuite/gcc.target/s390/hotpatch-13.c
index 9ac9f84..150667a 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-13.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-13.c
@@ -12,6 +12,10 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler "alignment for hotpatch" } } */
+/* { dg-final { scan-assembler-times "\.align\t8" 2 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-14.c b/gcc/testsuite/gcc.target/s390/hotpatch-14.c
index 209e4ac..c5f118c 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-14.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-14.c
@@ -12,6 +12,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-15.c b/gcc/testsuite/gcc.target/s390/hotpatch-15.c
index 109034e..ef0fb74 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-15.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-15.c
@@ -12,6 +12,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-16.c b/gcc/testsuite/gcc.target/s390/hotpatch-16.c
index b01c1c3..a34bf95 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-16.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-16.c
@@ -12,6 +12,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-17.c b/gcc/testsuite/gcc.target/s390/hotpatch-17.c
index ce0b950..66ac725 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-17.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-17.c
@@ -12,6 +12,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-18.c b/gcc/testsuite/gcc.target/s390/hotpatch-18.c
index 9a24d5e..8b076a4 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-18.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-18.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-19.c b/gcc/testsuite/gcc.target/s390/hotpatch-19.c
index 3586da2..6993c7e 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-19.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-19.c
@@ -18,6 +18,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-2.c b/gcc/testsuite/gcc.target/s390/hotpatch-2.c
index 18be5aa..67189f8 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-2.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-2.c
@@ -11,7 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(1 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
-/* { dg-final { scan-assembler-times "\.align\t8" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-21.c b/gcc/testsuite/gcc.target/s390/hotpatch-21.c
index d72dee3..e909990 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-21.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-21.c
@@ -11,4 +11,4 @@ void __attribute__ ((aligned(512))) hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t512" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-22.c b/gcc/testsuite/gcc.target/s390/hotpatch-22.c
index 6507466..d89d779 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-22.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-22.c
@@ -11,4 +11,4 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t1024" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-23.c b/gcc/testsuite/gcc.target/s390/hotpatch-23.c
index 7dce5b8..1e05d12 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-23.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-23.c
@@ -11,4 +11,4 @@ void __attribute__ ((aligned(2048))) hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t2048" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-24.c b/gcc/testsuite/gcc.target/s390/hotpatch-24.c
index 4d6815c..fc64274 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-24.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-24.c
@@ -11,4 +11,4 @@ void __attribute__ ((aligned(4096))) hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t4096" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-25.c b/gcc/testsuite/gcc.target/s390/hotpatch-25.c
new file mode 100644
index 0000000..e9257e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-25.c
@@ -0,0 +1,33 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch" } */
+
+typedef long (*fn_t)(void);
+
+__attribute__ ((hotpatch(1,2)))
+fn_t outer(void)
+{
+  __attribute__ ((hotpatch(4,8)))
+  long nested1(void)
+  {
+    __attribute__ ((hotpatch(16,32)))
+    long nested2(void)
+    {
+      return 2;
+    }
+    return (long)(void *)nested2;
+  }
+
+  return nested1;
+}
+
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "pre-label.*(4 halfwords)" } } */
+/* { dg-final { scan-assembler "pre-label.*(16 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(8 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(32 halfwords)" } } */
+/* { dg-final { scan-assembler-times "alignment for hotpatch" 3 } } */
+/* { dg-final { scan-assembler-times "\.align\t8" 6 } } */
+/* { dg-final { scan-assembler "nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-3.c b/gcc/testsuite/gcc.target/s390/hotpatch-3.c
index 8a2ab53..ec4a978 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-3.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-3.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-4.c b/gcc/testsuite/gcc.target/s390/hotpatch-4.c
index 9a69459..d55e71d 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-4.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-4.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(3 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-5.c b/gcc/testsuite/gcc.target/s390/hotpatch-5.c
index b3d990f..f77d83a 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-5.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-5.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(4 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-6.c b/gcc/testsuite/gcc.target/s390/hotpatch-6.c
index 10ba558..330cf5d 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-6.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-6.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(5 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-7.c b/gcc/testsuite/gcc.target/s390/hotpatch-7.c
index edf67d3..2f24e3cc 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-7.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-7.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(6 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 2 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-8.c b/gcc/testsuite/gcc.target/s390/hotpatch-8.c
index a179c4a..7b266bd 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-8.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-8.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(3 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-9.c b/gcc/testsuite/gcc.target/s390/hotpatch-9.c
index c4e21f2..c0ad319 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-9.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-9.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(4 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 2 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
index 3c5c782..2e8291e 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
@@ -1,4 +1,4 @@
-/* A warning will be issued when requesting hotpatching on a nested function.  */
+/* Functional tests for the function hotpatching feature.  */
 
 /* { dg-do compile } */
 /* { dg-options "-O3 -mzarch" } */
@@ -17,7 +17,7 @@ fn_t hp1(void)
 fn_t hp2(void)
 {
   __attribute__ ((hotpatch(1,2)))
-  int nested2(void) /* { dg-warning "hotpatching is not compatible with nested functions" } */
+  int nested2(void)
   { return 2; }
 
   return nested2;
-- 
2.3.0

>From 1c52a1ddb3758dbbaf554aab25a6a3af4742a492 Mon Sep 17 00:00:00 2001
From: Dominik Vogt <vogt@linux.vnet.ibm.com>
Date: Fri, 27 Mar 2015 15:48:39 +0100
Subject: [PATCH 1/2] S390: Missing diff hunks of backport of the last hotpatch
 changes.

---
 gcc/config/s390/s390.c                              | 7 -------
 gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c | 2 --
 2 files changed, 9 deletions(-)

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 88a17c0..fc884e5 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -5447,13 +5447,6 @@ s390_function_num_hotpatch_hw (tree decl,
   *hw_before = 0;
   *hw_after = 0;
 
-  if (DECL_ARTIFICIAL (decl)
-      || MAIN_NAME_P (DECL_NAME (decl)))
-    {
-      /* - Artificial functions need not be hotpatched.
-	 - Making the main function hotpatchable is useless.  */
-      return false;
-    }
   attr = lookup_attribute ("hotpatch", DECL_ATTRIBUTES (decl));
 
   /* Handle the arguments of the hotpatch attribute.  The values
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
index d5ba7f0..3c5c782 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
@@ -3,8 +3,6 @@
 /* { dg-do compile } */
 /* { dg-options "-O3 -mzarch" } */
 
-#include <stdio.h>
-
 typedef int (*fn_t)(void);
 
 fn_t hp1(void)
-- 
2.3.0

>From 60b4cf71435225c2282d2556ecb6ecde94d38ec9 Mon Sep 17 00:00:00 2001
From: Dominik Vogt <vogt@linux.vnet.ibm.com>
Date: Fri, 27 Mar 2015 11:41:56 +0100
Subject: [PATCH 2/2] S390: Nested functions can be hotpatched like all other
 functions.

Also add comments to assembler files to mark the code inserted for hotpatching.
---
 gcc/config/s390/s390.c                             | 67 ++++++++++------------
 gcc/testsuite/gcc.target/s390/hotpatch-1.c         |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-10.c        |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-11.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-12.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-13.c        |  4 ++
 gcc/testsuite/gcc.target/s390/hotpatch-14.c        |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-15.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-16.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-17.c        |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-18.c        |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-19.c        |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-2.c         |  4 +-
 gcc/testsuite/gcc.target/s390/hotpatch-21.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-22.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-23.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-24.c        |  2 +-
 gcc/testsuite/gcc.target/s390/hotpatch-25.c        | 33 +++++++++++
 gcc/testsuite/gcc.target/s390/hotpatch-3.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-4.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-5.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-6.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-7.c         |  2 +
 gcc/testsuite/gcc.target/s390/hotpatch-8.c         |  3 +
 gcc/testsuite/gcc.target/s390/hotpatch-9.c         |  2 +
 .../gcc.target/s390/hotpatch-compile-16.c          |  4 +-
 26 files changed, 116 insertions(+), 44 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/hotpatch-25.c

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index fc884e5..57cd8bd 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -5432,51 +5432,35 @@ get_some_local_dynamic_name (void)
   gcc_unreachable ();
 }
 
-/* Returns false if the function should not be made hotpatchable.
-   Otherwise it assigns the number of NOP halfwords to be emitted
-   before and after the function label to hw_before and hw_after.
-   Both must not be NULL.  */
+/* Assigns the number of NOP halfwords to be emitted before and after the
+   function label to *HW_BEFORE and *HW_AFTER.  Both pointers must not be NULL.
+   If hotpatching is disabled for the function, the values are set to zero.
+*/
 
-static bool
+static void
 s390_function_num_hotpatch_hw (tree decl,
 			       int *hw_before,
 			       int *hw_after)
 {
   tree attr;
 
-  *hw_before = 0;
-  *hw_after = 0;
-
   attr = lookup_attribute ("hotpatch", DECL_ATTRIBUTES (decl));
 
-  /* Handle the arguments of the hotpatch attribute.  The values
-     specified via attribute might override the cmdline argument
-     values.  */
   if (attr)
     {
       tree args = TREE_VALUE (attr);
 
+      /* If the hotpatch attribute is present, its values are used even if the
+	 -mhotpatch cmdline option is used.  */
       *hw_before = TREE_INT_CST_LOW (TREE_VALUE (args));
       *hw_after = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args)));
     }
   else
     {
-      /* Use the values specified by the cmdline arguments.  */
+      /* Values specified by the -mhotpatch cmdline option.  */
       *hw_before = s390_hotpatch_hw_before_label;
       *hw_after = s390_hotpatch_hw_after_label;
     }
-
-  if (*hw_before == 0 && *hw_after == 0)
-    return false;
-
-  if (decl_function_context (decl) != NULL_TREE)
-    {
-      warning_at (DECL_SOURCE_LOCATION (decl), OPT_mhotpatch_,
-		  "hotpatching is not compatible with nested functions");
-      return false;
-    }
-
-  return true;
 }
 
 
@@ -5487,36 +5471,45 @@ s390_asm_output_function_label (FILE *asm_out_file, const char *fname,
 				tree decl)
 {
   int hw_before, hw_after;
-  bool hotpatch_p = (decl
-		     ? s390_function_num_hotpatch_hw (decl,
-						      &hw_before, &hw_after)
-		     : false);
 
-  if (hotpatch_p)
+  s390_function_num_hotpatch_hw (decl, &hw_before, &hw_after);
+  if (hw_before > 0)
     {
       unsigned int function_alignment;
       int i;
 
-      /* Add a trampoline code area before the function label and initialize it
-	 with two-byte nop instructions.  This area can be overwritten with code
+      /* Add trampoline code area before the function label and initialize it
+	 with two-byte NOP instructions.  This area can be overwritten with code
 	 that jumps to a patched version of the function.  */
-      for (i = 0; i < hw_before; i++)
-	asm_fprintf (asm_out_file, "\tnopr\t%%r7\n");
+      asm_fprintf (asm_out_file, "\tnopr\t%%r7"
+		   "\t# pre-label NOPs for hotpatch (%d halfwords)\n",
+		   hw_before);
+      for (i = 1; i < hw_before; i++)
+	fputs ("\tnopr\t%r7\n", asm_out_file);
+
       /* Note:  The function label must be aligned so that (a) the bytes of the
-	 following nop do not cross a cacheline boundary, and (b) a jump address
+	 following NOP do not cross a cacheline boundary, and (b) a jump address
 	 (eight bytes for 64 bit targets, 4 bytes for 32 bit targets) can be
 	 stored directly before the label without crossing a cacheline
 	 boundary.  All this is necessary to make sure the trampoline code can
-	 be changed atomically.  */
+	 be changed atomically.
+	 This alignment is done automatically using the FOUNCTION_BOUNDARY
+	 macro, but if there are NOPs before the function label, the alignment
+	 is placed before them.  So it is necessary to duplicate the alignment
+	 after the NOPs.  */
       function_alignment = MAX (8, DECL_ALIGN (decl) / BITS_PER_UNIT);
       if (! DECL_USER_ALIGN (decl))
 	function_alignment = MAX (function_alignment,
 				  (unsigned int) align_functions);
+      fputs ("\t# alignment for hotpatch\n", asm_out_file);
       ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (function_alignment));
     }
 
   ASM_OUTPUT_LABEL (asm_out_file, fname);
-
+  if (hw_after > 0)
+    asm_fprintf (asm_out_file,
+		 "\t# post-label NOPs for hotpatch (%d halfwords)\n",
+		 hw_after);
 }
 
 /* Output machine-dependent UNSPECs occurring in address constant X
@@ -11268,7 +11261,7 @@ s390_reorg (void)
     {
       rtx insn;
 
-      /* Inject nops for hotpatching. */
+      /* Insert NOPs for hotpatching. */
       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
 	{
 	  if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-1.c b/gcc/testsuite/gcc.target/s390/hotpatch-1.c
index 4e29817..b14fa90 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-1.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-1.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-10.c b/gcc/testsuite/gcc.target/s390/hotpatch-10.c
index 352c9d5..a990c4c 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-10.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-10.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-11.c b/gcc/testsuite/gcc.target/s390/hotpatch-11.c
index beb8738..6f8a52b 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-11.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-11.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-12.c b/gcc/testsuite/gcc.target/s390/hotpatch-12.c
index d109478..b73ca90 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-12.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-12.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(999 halfwords)" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 999 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-13.c b/gcc/testsuite/gcc.target/s390/hotpatch-13.c
index 9ac9f84..150667a 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-13.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-13.c
@@ -12,6 +12,10 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler "alignment for hotpatch" } } */
+/* { dg-final { scan-assembler-times "\.align\t8" 2 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-14.c b/gcc/testsuite/gcc.target/s390/hotpatch-14.c
index 209e4ac..c5f118c 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-14.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-14.c
@@ -12,6 +12,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-15.c b/gcc/testsuite/gcc.target/s390/hotpatch-15.c
index 109034e..ef0fb74 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-15.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-15.c
@@ -12,6 +12,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-16.c b/gcc/testsuite/gcc.target/s390/hotpatch-16.c
index b01c1c3..a34bf95 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-16.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-16.c
@@ -12,6 +12,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-17.c b/gcc/testsuite/gcc.target/s390/hotpatch-17.c
index ce0b950..66ac725 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-17.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-17.c
@@ -12,6 +12,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-18.c b/gcc/testsuite/gcc.target/s390/hotpatch-18.c
index 9a24d5e..8b076a4 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-18.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-18.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler-not "post-label NOPs" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-19.c b/gcc/testsuite/gcc.target/s390/hotpatch-19.c
index 3586da2..6993c7e 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-19.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-19.c
@@ -18,6 +18,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-2.c b/gcc/testsuite/gcc.target/s390/hotpatch-2.c
index 18be5aa..67189f8 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-2.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-2.c
@@ -11,7 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(1 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
-/* { dg-final { scan-assembler-times "\.align\t8" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-21.c b/gcc/testsuite/gcc.target/s390/hotpatch-21.c
index d72dee3..e909990 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-21.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-21.c
@@ -11,4 +11,4 @@ void __attribute__ ((aligned(512))) hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t512" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-22.c b/gcc/testsuite/gcc.target/s390/hotpatch-22.c
index 6507466..d89d779 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-22.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-22.c
@@ -11,4 +11,4 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t1024" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-23.c b/gcc/testsuite/gcc.target/s390/hotpatch-23.c
index 7dce5b8..1e05d12 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-23.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-23.c
@@ -11,4 +11,4 @@ void __attribute__ ((aligned(2048))) hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t2048" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-24.c b/gcc/testsuite/gcc.target/s390/hotpatch-24.c
index 4d6815c..fc64274 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-24.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-24.c
@@ -11,4 +11,4 @@ void __attribute__ ((aligned(4096))) hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
-/* { dg-final { scan-assembler-times "\.align\t4096" 2 } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-25.c b/gcc/testsuite/gcc.target/s390/hotpatch-25.c
new file mode 100644
index 0000000..e9257e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-25.c
@@ -0,0 +1,33 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch" } */
+
+typedef long (*fn_t)(void);
+
+__attribute__ ((hotpatch(1,2)))
+fn_t outer(void)
+{
+  __attribute__ ((hotpatch(4,8)))
+  long nested1(void)
+  {
+    __attribute__ ((hotpatch(16,32)))
+    long nested2(void)
+    {
+      return 2;
+    }
+    return (long)(void *)nested2;
+  }
+
+  return nested1;
+}
+
+/* { dg-final { scan-assembler "pre-label.*(1 halfwords)" } } */
+/* { dg-final { scan-assembler "pre-label.*(4 halfwords)" } } */
+/* { dg-final { scan-assembler "pre-label.*(16 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(8 halfwords)" } } */
+/* { dg-final { scan-assembler "post-label.*(32 halfwords)" } } */
+/* { dg-final { scan-assembler-times "alignment for hotpatch" 3 } } */
+/* { dg-final { scan-assembler-times "\.align\t8" 6 } } */
+/* { dg-final { scan-assembler "nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr.*\n.*nopr" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-3.c b/gcc/testsuite/gcc.target/s390/hotpatch-3.c
index 8a2ab53..ec4a978 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-3.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-3.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(2 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-4.c b/gcc/testsuite/gcc.target/s390/hotpatch-4.c
index 9a69459..d55e71d 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-4.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-4.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(3 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-5.c b/gcc/testsuite/gcc.target/s390/hotpatch-5.c
index b3d990f..f77d83a 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-5.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-5.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(4 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-6.c b/gcc/testsuite/gcc.target/s390/hotpatch-6.c
index 10ba558..330cf5d 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-6.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-6.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(5 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-7.c b/gcc/testsuite/gcc.target/s390/hotpatch-7.c
index edf67d3..2f24e3cc 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-7.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-7.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(6 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-not "nop\t0" } } */
 /* { dg-final { scan-assembler-times "brcl\t0, 0" 2 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-8.c b/gcc/testsuite/gcc.target/s390/hotpatch-8.c
index a179c4a..7b266bd 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-8.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-8.c
@@ -11,6 +11,9 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(3 halfwords)" } } */
 /* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
 /* { dg-final { scan-assembler-times "nop\t0" 1 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
+/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-9.c b/gcc/testsuite/gcc.target/s390/hotpatch-9.c
index c4e21f2..c0ad319 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-9.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-9.c
@@ -11,6 +11,8 @@ void hp1(void)
 }
 
 /* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
+/* { dg-final { scan-assembler "post-label.*(4 halfwords)" } } */
 /* { dg-final { scan-assembler-not "nopr\t%r7" } } */
 /* { dg-final { scan-assembler-times "nop\t0" 2 } } */
 /* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
index 3c5c782..2e8291e 100644
--- a/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
+++ b/gcc/testsuite/gcc.target/s390/hotpatch-compile-16.c
@@ -1,4 +1,4 @@
-/* A warning will be issued when requesting hotpatching on a nested function.  */
+/* Functional tests for the function hotpatching feature.  */
 
 /* { dg-do compile } */
 /* { dg-options "-O3 -mzarch" } */
@@ -17,7 +17,7 @@ fn_t hp1(void)
 fn_t hp2(void)
 {
   __attribute__ ((hotpatch(1,2)))
-  int nested2(void) /* { dg-warning "hotpatching is not compatible with nested functions" } */
+  int nested2(void)
   { return 2; }
 
   return nested2;
-- 
2.3.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]