s390.c (s390_hotpatch_trampoline_halfwords_default): New constant
authorDominik Vogt <vogt@linux.vnet.ibm.com>
Thu, 19 Dec 2013 12:00:43 +0000 (12:00 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Thu, 19 Dec 2013 12:00:43 +0000 (12:00 +0000)
2013-12-19  Dominik Vogt  <vogt@linux.vnet.ibm.com>
    Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

* config/s390/s390.c (s390_hotpatch_trampoline_halfwords_default): New
constant
(s390_hotpatch_trampoline_halfwords_max): New constant
(s390_hotpatch_trampoline_halfwords): New static variable
(get_hotpatch_attribute): New function
(s390_handle_hotpatch_attribute): New function
(s390_attribute_table): New target specific attribute table to implement
the hotpatch attribute
(s390_option_override): Parse hotpatch options
(s390_function_num_hotpatch_trampoline_halfwords): New function
(s390_can_inline_p): Implement target hook to
suppress hotpatching for explicitly inlined functions
(s390_asm_output_function_label): Generate hotpatch prologue
(TARGET_ATTRIBUTE_TABLE): Define to implement target attribute table
(TARGET_CAN_INLINE_P): Define to implement target hook
* config/s390/s390.opt (mhotpatch): New options -mhotpatch, -mhotpatch=
* config/s390/s390-protos.h (s390_asm_output_function_label): Add
prototype
* config/s390/s390.h (ASM_OUTPUT_FUNCTION_LABEL): Target specific
function label generation for hotpatching
(FUNCTION_BOUNDARY): Align functions to eight bytes
* doc/extend.texi: Document hotpatch attribute
* doc/invoke.texi: Document -mhotpatch option

2013-12-19  Dominik Vogt  <vogt@linux.vnet.ibm.com>
    Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

* gcc/testsuite/gcc.target/s390/hotpatch-1.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-2.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-3.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-4.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-5.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-6.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-7.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-8.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-9.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-10.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-11.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-12.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-compile-1.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-compile-2.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-compile-3.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-compile-4.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-compile-5.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-compile-6.c: New test
* gcc/testsuite/gcc.target/s390/hotpatch-compile-7.c: New test

Co-Authored-By: Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
From-SVN: r206111

27 files changed:
gcc/ChangeLog
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.opt
gcc/doc/extend.texi
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/s390/hotpatch-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-11.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-12.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-9.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-compile-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-compile-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-compile-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-compile-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-compile-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-compile-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/hotpatch-compile-7.c [new file with mode: 0644]

index 6f69334..9417065 100644 (file)
@@ -1,3 +1,30 @@
+2013-12-19  Dominik Vogt  <vogt@linux.vnet.ibm.com>
+           Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
+
+       * config/s390/s390.c (s390_hotpatch_trampoline_halfwords_default): New
+       constant
+       (s390_hotpatch_trampoline_halfwords_max): New constant
+       (s390_hotpatch_trampoline_halfwords): New static variable
+       (get_hotpatch_attribute): New function
+       (s390_handle_hotpatch_attribute): New function
+       (s390_attribute_table): New target specific attribute table to implement
+       the hotpatch attribute
+       (s390_option_override): Parse hotpatch options
+       (s390_function_num_hotpatch_trampoline_halfwords): New function
+       (s390_can_inline_p): Implement target hook to
+       suppress hotpatching for explicitly inlined functions
+       (s390_asm_output_function_label): Generate hotpatch prologue
+       (TARGET_ATTRIBUTE_TABLE): Define to implement target attribute table
+       (TARGET_CAN_INLINE_P): Define to implement target hook
+       * config/s390/s390.opt (mhotpatch): New options -mhotpatch, -mhotpatch=
+       * config/s390/s390-protos.h (s390_asm_output_function_label): Add
+       prototype
+       * config/s390/s390.h (ASM_OUTPUT_FUNCTION_LABEL): Target specific
+       function label generation for hotpatching
+       (FUNCTION_BOUNDARY): Align functions to eight bytes
+       * doc/extend.texi: Document hotpatch attribute
+       * doc/invoke.texi: Document -mhotpatch option
+
 2013-12-19  Ganesh Gopalasubramanian  <Ganesh.Gopalasubramanian@amd.com>
 
        * config/i386/i386.c: Include cfgloop.h. 
index 67283df..7b43ed0 100644 (file)
@@ -110,5 +110,6 @@ extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *);
 extern int s390_branch_condition_mask (rtx);
 extern int s390_compare_and_branch_condition_mask (rtx);
 extern bool s390_extzv_shift_ok (int, int, unsigned HOST_WIDE_INT);
+extern void s390_asm_output_function_label (FILE *, const char *, tree);
 
 #endif /* RTX_CODE */
index f9b7cd0..5319a69 100644 (file)
@@ -434,6 +434,65 @@ struct GTY(()) machine_function
    bytes on a z10 (or higher) CPU.  */
 #define PREDICT_DISTANCE (TARGET_Z10 ? 384 : 2048)
 
+static const int s390_hotpatch_trampoline_halfwords_default = 12;
+static const int s390_hotpatch_trampoline_halfwords_max = 1000000;
+static int s390_hotpatch_trampoline_halfwords = -1;
+
+/* Return the argument of the given hotpatch attribute or the default value if
+   no argument is present.  */
+
+static inline int
+get_hotpatch_attribute (tree hotpatch_attr)
+{
+  const_tree args;
+
+  args = TREE_VALUE (hotpatch_attr);
+
+  return (args) ?
+    TREE_INT_CST_LOW (TREE_VALUE (args)):
+    s390_hotpatch_trampoline_halfwords_default;
+}
+
+/* Check whether the hotpatch attribute is applied to a function and, if it has
+   an argument, the argument is valid.  */
+
+static tree
+s390_handle_hotpatch_attribute (tree *node, tree name, tree args,
+                               int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute only applies to functions",
+              name);
+      *no_add_attrs = true;
+    }
+  else if (args)
+    {
+      tree expr = TREE_VALUE (args);
+
+      if (TREE_CODE (expr) != INTEGER_CST
+         || !INTEGRAL_TYPE_P (TREE_TYPE (expr))
+         || TREE_INT_CST_HIGH (expr) != 0
+         || TREE_INT_CST_LOW (expr) > (unsigned int)
+         s390_hotpatch_trampoline_halfwords_max)
+       {
+         error ("requested %qE attribute is not a non-negative integer"
+                " constant or too large (max. %d)", name,
+                s390_hotpatch_trampoline_halfwords_max);
+         *no_add_attrs = true;
+       }
+    }
+
+  return NULL_TREE;
+}
+
+static const struct attribute_spec s390_attribute_table[] = {
+  { "hotpatch", 0, 1, true, false, false, s390_handle_hotpatch_attribute, false
+  },
+  /* End element.  */
+  { NULL,        0, 0, false, false, false, NULL, false }
+};
+
 /* Return the alignment for LABEL.  We default to the -falign-labels
    value except for the literal pool base label.  */
 int
@@ -1622,6 +1681,46 @@ s390_init_machine_status (void)
 static void
 s390_option_override (void)
 {
+  unsigned int i;
+  cl_deferred_option *opt;
+  vec<cl_deferred_option> *v =
+    (vec<cl_deferred_option> *) s390_deferred_options;
+
+  if (v)
+    FOR_EACH_VEC_ELT (*v, i, opt)
+      {
+       switch (opt->opt_index)
+         {
+         case OPT_mhotpatch:
+           s390_hotpatch_trampoline_halfwords = (opt->value) ?
+             s390_hotpatch_trampoline_halfwords_default : -1;
+           break;
+         case OPT_mhotpatch_:
+           {
+             int val;
+
+             val = integral_argument (opt->arg);
+             if (val == -1)
+               {
+                 /* argument is not a plain number */
+                 error ("argument to %qs should be a non-negative integer",
+                        "-mhotpatch=");
+                 break;
+               }
+             else if (val > s390_hotpatch_trampoline_halfwords_max)
+               {
+                 error ("argument to %qs is too large (max. %d)",
+                        "-mhotpatch=", s390_hotpatch_trampoline_halfwords_max);
+                 break;
+               }
+             s390_hotpatch_trampoline_halfwords = val;
+             break;
+           }
+         default:
+           gcc_unreachable ();
+         }
+      }
+
   /* Set up function hooks.  */
   init_machine_status = s390_init_machine_status;
 
@@ -5347,6 +5446,102 @@ get_some_local_dynamic_name (void)
   gcc_unreachable ();
 }
 
+/* Returns -1 if the function should not be made hotpatchable.  Otherwise it
+   returns a number >= 0 that is the desired size of the hotpatch trampoline
+   in halfwords. */
+
+static int s390_function_num_hotpatch_trampoline_halfwords (tree decl,
+                                                           bool do_warn)
+{
+  tree attr;
+
+  if (DECL_DECLARED_INLINE_P (decl)
+      || DECL_ARTIFICIAL (decl)
+      || MAIN_NAME_P (DECL_NAME (decl)))
+    {
+      /* - Explicitly inlined functions cannot be hotpatched.
+        - Artificial functions need not be hotpatched.
+        - Making the main function hotpatchable is useless. */
+      return -1;
+    }
+  attr = lookup_attribute ("hotpatch", DECL_ATTRIBUTES (decl));
+  if (attr || s390_hotpatch_trampoline_halfwords >= 0)
+    {
+      if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl)))
+       {
+         if (do_warn)
+           warning (OPT_Wattributes, "function %qE with the %qs attribute"
+                    " is not hotpatchable", DECL_NAME (decl), "always_inline");
+         return -1;
+       }
+      else
+       {
+         return (attr) ?
+           get_hotpatch_attribute (attr) : s390_hotpatch_trampoline_halfwords;
+       }
+    }
+
+  return -1;
+}
+
+/* Hook to determine if one function can safely inline another.  */
+
+static bool
+s390_can_inline_p (tree caller, tree callee)
+{
+  if (s390_function_num_hotpatch_trampoline_halfwords (callee, false) >= 0)
+    return false;
+
+  return default_target_can_inline_p (caller, callee);
+}
+
+/* Write the extra assembler code needed to declare a function properly.  */
+
+void
+s390_asm_output_function_label (FILE *asm_out_file, const char *fname,
+                               tree decl)
+{
+  int hotpatch_trampoline_halfwords = -1;
+
+  if (decl)
+    {
+      hotpatch_trampoline_halfwords =
+       s390_function_num_hotpatch_trampoline_halfwords (decl, true);
+      if (hotpatch_trampoline_halfwords >= 0
+         && decl_function_context (decl) != NULL_TREE)
+       {
+         warning_at (0, DECL_SOURCE_LOCATION (decl),
+                     "hotpatch_prologue is not compatible with nested"
+                     " function");
+         hotpatch_trampoline_halfwords = -1;
+       }
+    }
+
+  if (hotpatch_trampoline_halfwords > 0)
+    {
+      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
+        that jumps to a patched version of the function.  */
+      for (i = 0; i < hotpatch_trampoline_halfwords; i++)
+       asm_fprintf (asm_out_file, "\tnopr\t%%r7\n");
+      /* 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.  */
+    }
+
+  ASM_OUTPUT_LABEL (asm_out_file, fname);
+
+  /* Output a four-byte nop if hotpatching is enabled.  This can be overwritten
+     atomically with a relative backwards jump to the trampoline area.  */
+  if (hotpatch_trampoline_halfwords >= 0)
+    asm_fprintf (asm_out_file, "\tnop\t0\n");
+}
+
 /* Output machine-dependent UNSPECs occurring in address constant X
    in assembler syntax to stdio stream FILE.  Returns true if the
    constant X could be recognized, false otherwise.  */
@@ -11920,6 +12115,12 @@ s390_loop_unroll_adjust (unsigned nunroll, struct loop *loop)
 #undef TARGET_HARD_REGNO_SCRATCH_OK
 #define TARGET_HARD_REGNO_SCRATCH_OK s390_hard_regno_scratch_ok
 
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE s390_attribute_table
+
+#undef TARGET_CAN_INLINE_P
+#define TARGET_CAN_INLINE_P s390_can_inline_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-s390.h"
index bca18fe..75b642b 100644 (file)
@@ -217,7 +217,7 @@ enum processor_flags
 #define STACK_BOUNDARY 64
 
 /* Allocation boundary (in *bits*) for the code of a function.  */
-#define FUNCTION_BOUNDARY 32
+#define FUNCTION_BOUNDARY 64
 
 /* There is no point aligning anything to a rounder boundary than this.  */
 #define BIGGEST_ALIGNMENT 64
@@ -878,6 +878,9 @@ do {                                                                        \
   fputc ('\n', (FILE));                                                        \
 } while (0)
 
+#undef ASM_OUTPUT_FUNCTION_LABEL
+#define ASM_OUTPUT_FUNCTION_LABEL(FILE, NAME, DECL) \
+  s390_asm_output_function_label (FILE, NAME, DECL)
 
 /* Miscellaneous parameters.  */
 
index 7dedb83..ef92f46 100644 (file)
@@ -96,6 +96,14 @@ mhard-float
 Target Report RejectNegative Negative(msoft-float) InverseMask(SOFT_FLOAT, HARD_FLOAT)
 Enable hardware floating point
 
+mhotpatch
+Target Report Var(s390_deferred_options) Defer
+Prepend the function label with 12 two-byte Nop instructions, and add a four byte Nop instruction after the label for hotpatching.
+
+mhotpatch=
+Target RejectNegative Report Joined Var(s390_deferred_options) Defer
+Prepend the function label with the given number of two-byte Nop instructions, and add a four byte Nop instruction after the label for hotpatching.
+
 mlong-double-128
 Target Report RejectNegative Negative(mlong-double-64) Mask(LONG_DOUBLE_128)
 Use 128-bit long double
index af258d7..2ce0098 100644 (file)
@@ -3266,6 +3266,17 @@ this function attribute to make GCC generate the ``hot-patching'' function
 prologue used in Win32 API functions in Microsoft Windows XP Service Pack 2
 and newer.
 
+@item hotpatch [(@var{prologue-halfwords})]
+@cindex @code{hotpatch} attribute
+
+On S/390 System z targets, you can use this function attribute to
+make GCC generate a ``hot-patching'' function prologue.  The
+@code{hotpatch} has no effect on funtions that are explicitly
+inline.  If the @option{-mhotpatch} or @option{-mno-hotpatch}
+command-line option is used at the same time, the @code{hotpatch}
+attribute takes precedence.  If an argument is given, the maximum
+allowed value is 1000000.
+
 @item naked
 @cindex function without a prologue/epilogue code
 Use this attribute on the ARM, AVR, MCORE, MSP430, NDS32, RL78, RX and SPU
index 1a6d815..6e888bd 100644 (file)
@@ -933,7 +933,8 @@ See RS/6000 and PowerPC Options.
 -msmall-exec  -mno-small-exec  -mmvcle -mno-mvcle @gol
 -m64  -m31  -mdebug  -mno-debug  -mesa  -mzarch @gol
 -mtpf-trace -mno-tpf-trace  -mfused-madd  -mno-fused-madd @gol
--mwarn-framesize  -mwarn-dynamicstack  -mstack-size -mstack-guard}
+-mwarn-framesize  -mwarn-dynamicstack  -mstack-size -mstack-guard @gol
+-mhotpatch[=@var{halfwords}] -mno-hotpatch}
 
 @emph{Score Options}
 @gccoptlist{-meb -mel @gol
@@ -19777,6 +19778,21 @@ values have to be exact powers of 2 and @var{stack-size} has to be greater than
 In order to be efficient the extra code makes the assumption that the stack starts
 at an address aligned to the value given by @var{stack-size}.
 The @var{stack-guard} option can only be used in conjunction with @var{stack-size}.
+
+@item -mhotpatch[=@var{halfwords}]
+@itemx -mno-hotpatch
+@opindex mhotpatch
+If the hotpatch option is enabled, a ``hot-patching'' function
+prologue is generated for all functions in the compilation unit.
+The funtion label is prepended with the given number of two-byte
+Nop instructions (@var{halfwords}, maximum 1000000) or 12 Nop
+instructions if no argument is present.  Functions with a
+hot-patching prologue are never inlined automatically, and a
+hot-patching prologue is never generated for functions functions
+that are explicitly inline.
+
+This option can be overridden for individual functions with the
+@code{hotpatch} attribute.
 @end table
 
 @node Score Options
index b5100b7..3f9884f 100644 (file)
@@ -1,3 +1,26 @@
+2013-12-19  Dominik Vogt  <vogt@linux.vnet.ibm.com>
+           Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
+
+       * gcc/testsuite/gcc.target/s390/hotpatch-1.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-2.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-3.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-4.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-5.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-6.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-7.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-8.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-9.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-10.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-11.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-12.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-compile-1.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-compile-2.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-compile-3.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-compile-4.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-compile-5.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-compile-6.c: New test
+       * gcc/testsuite/gcc.target/s390/hotpatch-compile-7.c: New test
+
 2013-12-19  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * c-c++-common/cilk-plus/SE/ef_error.c: Add fopenmp effective
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-1.c b/gcc/testsuite/gcc.target/s390/hotpatch-1.c
new file mode 100644 (file)
index 0000000..b9d6139
--- /dev/null
@@ -0,0 +1,20 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 12 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-10.c b/gcc/testsuite/gcc.target/s390/hotpatch-10.c
new file mode 100644 (file)
index 0000000..b91b347
--- /dev/null
@@ -0,0 +1,21 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mno-hotpatch --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch(2)))
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 2 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-11.c b/gcc/testsuite/gcc.target/s390/hotpatch-11.c
new file mode 100644 (file)
index 0000000..4916773
--- /dev/null
@@ -0,0 +1,20 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch -mno-hotpatch --save-temps" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "nopr\t%r7" } } */
+/* { dg-final { scan-assembler-not "nop\t0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-12.c b/gcc/testsuite/gcc.target/s390/hotpatch-12.c
new file mode 100644 (file)
index 0000000..b3e9427
--- /dev/null
@@ -0,0 +1,20 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mno-hotpatch -mhotpatch=1 --save-temps" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-2.c b/gcc/testsuite/gcc.target/s390/hotpatch-2.c
new file mode 100644 (file)
index 0000000..6cc2944
--- /dev/null
@@ -0,0 +1,20 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch=1 --save-temps" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-3.c b/gcc/testsuite/gcc.target/s390/hotpatch-3.c
new file mode 100644 (file)
index 0000000..9f0b2b7
--- /dev/null
@@ -0,0 +1,20 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch=0 --save-temps" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "nopr\t%r7" } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-4.c b/gcc/testsuite/gcc.target/s390/hotpatch-4.c
new file mode 100644 (file)
index 0000000..c1dba20
--- /dev/null
@@ -0,0 +1,26 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+inline void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((always_inline))
+void hp2(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+  printf("hello, world!\n");
+} /* { dg-warning "function 'hp2' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "nopr\t%r7" } } */
+/* { dg-final { scan-assembler-not "nop\t0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-5.c b/gcc/testsuite/gcc.target/s390/hotpatch-5.c
new file mode 100644 (file)
index 0000000..ec267d6
--- /dev/null
@@ -0,0 +1,21 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch))
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 12 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-6.c b/gcc/testsuite/gcc.target/s390/hotpatch-6.c
new file mode 100644 (file)
index 0000000..5af090d
--- /dev/null
@@ -0,0 +1,21 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch(1)))
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 1 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-7.c b/gcc/testsuite/gcc.target/s390/hotpatch-7.c
new file mode 100644 (file)
index 0000000..e73a510
--- /dev/null
@@ -0,0 +1,21 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch(0)))
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "nopr\t%r7" } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-8.c b/gcc/testsuite/gcc.target/s390/hotpatch-8.c
new file mode 100644 (file)
index 0000000..399aa72
--- /dev/null
@@ -0,0 +1,28 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch))
+inline void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch))
+__attribute__ ((always_inline))
+void hp2(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+  printf("hello, world!\n");
+} /* { dg-warning "function 'hp2' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-not "nopr\t%r7" } } */
+/* { dg-final { scan-assembler-not "nop\t0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-9.c b/gcc/testsuite/gcc.target/s390/hotpatch-9.c
new file mode 100644 (file)
index 0000000..5da6758
--- /dev/null
@@ -0,0 +1,21 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch=1 --save-temps" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch(2)))
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+int main (void)
+{
+  return 0;
+}
+
+/* Check number of occurences of certain instructions.  */
+/* { dg-final { scan-assembler-times "nopr\t%r7" 2 } } */
+/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-1.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-1.c
new file mode 100644 (file)
index 0000000..45a2cc5
--- /dev/null
@@ -0,0 +1,27 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+inline void hp2(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((always_inline))
+void hp3(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+  printf("hello, world!\n");
+} /* { dg-warning "function 'hp3' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-2.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-2.c
new file mode 100644 (file)
index 0000000..5947f56
--- /dev/null
@@ -0,0 +1,27 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch=0" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+inline void hp2(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((always_inline))
+void hp3(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+  printf("hello, world!\n");
+} /* { dg-warning "function 'hp3' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-3.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-3.c
new file mode 100644 (file)
index 0000000..e0c7f6f
--- /dev/null
@@ -0,0 +1,27 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mhotpatch=1" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+inline void hp2(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((always_inline))
+void hp3(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+  printf("hello, world!\n");
+} /* { dg-warning "function 'hp3' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-4.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-4.c
new file mode 100644 (file)
index 0000000..d9f1342
--- /dev/null
@@ -0,0 +1,11 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch -mhotpatch=-1" } */
+
+int main (void)
+{
+  return 0;
+}
+
+/* { dg-excess-errors "argument to '-mhotpatch=' should be a non-negative integer" } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-5.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-5.c
new file mode 100644 (file)
index 0000000..53f7eac
--- /dev/null
@@ -0,0 +1,28 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch -mhotpatch=1000000" } */
+
+#include <stdio.h>
+
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(1000000)))
+void hp2(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(1000001)))
+void hp3(void)
+{ /* { dg-error "requested 'hotpatch' attribute is not a non-negative integer constant or too large .max. 1000000." } */
+  printf("hello, world!\n");
+}
+
+int main (void)
+{
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-6.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-6.c
new file mode 100644 (file)
index 0000000..cb10b66
--- /dev/null
@@ -0,0 +1,11 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch -mhotpatch=1000001" } */
+
+int main (void)
+{
+  return 0;
+}
+
+/* { dg-excess-errors "argument to '-mhotpatch=' is too large .max. 1000000." } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-compile-7.c b/gcc/testsuite/gcc.target/s390/hotpatch-compile-7.c
new file mode 100644 (file)
index 0000000..98ccb42
--- /dev/null
@@ -0,0 +1,68 @@
+/* Functional tests for the function hotpatching feature.  */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -mno-hotpatch" } */
+
+#include <stdio.h>
+
+__attribute__ ((hotpatch))
+void hp1(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch))
+inline void hp2(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch))
+__attribute__ ((always_inline))
+void hp3(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+  printf("hello, world!\n");
+} /* { dg-warning "function 'hp3' with the 'always_inline' attribute is not hotpatchable" } */
+
+__attribute__ ((hotpatch(0)))
+void hp4(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(0)))
+inline void hp5(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(0)))
+__attribute__ ((always_inline))
+void hp6(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+  printf("hello, world!\n");
+} /* { dg-warning "function 'hp6' with the 'always_inline' attribute is not hotpatchable" } */
+
+__attribute__ ((hotpatch(1)))
+void hp7(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(1)))
+inline void hp8(void)
+{
+  printf("hello, world!\n");
+}
+
+__attribute__ ((hotpatch(1)))
+__attribute__ ((always_inline))
+void hp9(void) /* { dg-warning "always_inline function might not be inlinable" } */
+{
+  printf("hello, world!\n");
+} /* { dg-warning "function 'hp9' with the 'always_inline' attribute is not hotpatchable" } */
+
+int main (void)
+{
+  return 0;
+}