]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/70199 (Crash at -O2 when using labels.)
authorRichard Henderson <rth@redhat.com>
Wed, 16 Mar 2016 16:50:18 +0000 (09:50 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 16 Mar 2016 16:50:18 +0000 (09:50 -0700)
PR middle-end/70199

 * function.h (struct function): Add has_forced_label_in_static.
 * gimplify.c (force_labels_r): Set it.
 * lto-streamer-in.c (input_struct_function_base): Read it.
 * lto-streamer-out.c (output_struct_function_base): Write it.
 * tree-inline.c (has_label_address_in_static_1): Remove.
 (copy_forbidden): Remove fndecl parameter; test
 has_forced_label_in_static.
 (inline_forbidden_p): Update call to copy_forbidden.
 (tree_versionable_function_p): Likewise.
 * ipa-chkp.c (chkp_instrumentable_p): Likewise.
 (chkp_versioning): Likewise.
 * tree-inline.h (copy_forbidden): Update decl.

testsuite/
 * gcc.c-torture/compile/pr70199.c: New.

From-SVN: r234261

gcc/ChangeLog
gcc/function.h
gcc/gimplify.c
gcc/ipa-chkp.c
gcc/lto-streamer-in.c
gcc/lto-streamer-out.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr70199.c [new file with mode: 0644]
gcc/tree-inline.c
gcc/tree-inline.h

index 0af222ed70f61577bd31fea0f23d29a0e92ef77d..b673443c1038993116bc81d393e6ee0b3de3fa87 100644 (file)
@@ -1,3 +1,19 @@
+2016-03-16  Richard Henderson  <rth@redhat.com>
+
+       PR middle-end/70199
+       * function.h (struct function): Add has_forced_label_in_static.
+       * gimplify.c (force_labels_r): Set it.
+       * lto-streamer-in.c (input_struct_function_base): Read it.
+       * lto-streamer-out.c (output_struct_function_base): Write it.
+       * tree-inline.c (has_label_address_in_static_1): Remove.
+       (copy_forbidden): Remove fndecl parameter; test
+       has_forced_label_in_static.
+       (inline_forbidden_p): Update call to copy_forbidden.
+       (tree_versionable_function_p): Likewise.
+       * ipa-chkp.c (chkp_instrumentable_p): Likewise.
+       (chkp_versioning): Likewise.
+       * tree-inline.h (copy_forbidden): Update decl.
+
 2016-03-16  Marek Polacek  <polacek@redhat.com>
 
        PR c/70093
index c4368cda7f22a6c2c59bcff911199c688a854b4f..501ef68484018d5ebb1982a2b5e6b4df6130e75e 100644 (file)
@@ -328,6 +328,10 @@ struct GTY(()) function {
      from nested functions.  */
   unsigned int has_nonlocal_label : 1;
 
+  /* Nonzero if function being compiled has a forced label
+     placed into static storage.  */
+  unsigned int has_forced_label_in_static : 1;
+
   /* Nonzero if we've set cannot_be_copied_reason.  I.e. if
      (cannot_be_copied_set && !cannot_be_copied_reason), the function
      can in fact be copied.  */
index 692d168c3b4e1f0c6c390010938097eb5dc839da..84ce46ea1a3155cdfc5697b6ed24e98648dc82ec 100644 (file)
@@ -1414,7 +1414,10 @@ force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
   if (TYPE_P (*tp))
     *walk_subtrees = 0;
   if (TREE_CODE (*tp) == LABEL_DECL)
-    FORCED_LABEL (*tp) = 1;
+    {
+      FORCED_LABEL (*tp) = 1;
+      cfun->has_forced_label_in_static = 1;
+    }
 
   return NULL_TREE;
 }
index 4a6b43e7a8a3452b909750a8fa6de7e5fae6a0a5..5f5df6483a79657a3b5d09fd066170e440b8c2dd 100644 (file)
@@ -470,7 +470,7 @@ chkp_instrumentable_p (tree fndecl)
   return (!lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl))
          && (!flag_chkp_instrument_marked_only
              || lookup_attribute ("bnd_instrument", DECL_ATTRIBUTES (fndecl)))
-         && (!fn || !copy_forbidden (fn, fndecl)));
+         && (!fn || !copy_forbidden (fn)));
 }
 
 /* Return clone created for instrumentation of NODE or NULL.  */
@@ -644,22 +644,22 @@ chkp_versioning (void)
 
   FOR_EACH_DEFINED_FUNCTION (node)
     {
+      tree decl = node->decl;
       if (!node->instrumentation_clone
          && !node->instrumented_version
          && !node->alias
          && !node->thunk.thunk_p
-         && (!DECL_BUILT_IN (node->decl)
-             || (DECL_BUILT_IN_CLASS (node->decl) == BUILT_IN_NORMAL
-                 && DECL_FUNCTION_CODE (node->decl) < BEGIN_CHKP_BUILTINS)))
+         && (!DECL_BUILT_IN (decl)
+             || (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
+                 && DECL_FUNCTION_CODE (decl) < BEGIN_CHKP_BUILTINS)))
        {
-         if (chkp_instrumentable_p (node->decl))
-           chkp_maybe_create_clone (node->decl);
-         else if ((reason = copy_forbidden (DECL_STRUCT_FUNCTION (node->decl),
-                                            node->decl)))
+         if (chkp_instrumentable_p (decl))
+           chkp_maybe_create_clone (decl);
+         else if ((reason = copy_forbidden (DECL_STRUCT_FUNCTION (decl))))
            {
-             if (warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wchkp,
+             if (warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wchkp,
                              "function cannot be instrumented"))
-               inform (DECL_SOURCE_LOCATION (node->decl), reason, node->decl);
+               inform (DECL_SOURCE_LOCATION (decl), reason, decl);
            }
        }
     }
index 48a1c868bac9f402d7365e1f23374e57cde5f06f..dd48777effa2b2a6cec085027794a98c6a460d38 100644 (file)
@@ -1008,6 +1008,7 @@ input_struct_function_base (struct function *fn, struct data_in *data_in,
   fn->after_inlining = bp_unpack_value (&bp, 1);
   fn->stdarg = bp_unpack_value (&bp, 1);
   fn->has_nonlocal_label = bp_unpack_value (&bp, 1);
+  fn->has_forced_label_in_static = bp_unpack_value (&bp, 1);
   fn->calls_alloca = bp_unpack_value (&bp, 1);
   fn->calls_setjmp = bp_unpack_value (&bp, 1);
   fn->has_force_vectorize_loops = bp_unpack_value (&bp, 1);
index 997a28b01598c681b0c5e1cb4513f664c2084e94..6703d4106deea19f05f727b59776e1f8d9ff6782 100644 (file)
@@ -2014,6 +2014,7 @@ output_struct_function_base (struct output_block *ob, struct function *fn)
   bp_pack_value (&bp, fn->after_inlining, 1);
   bp_pack_value (&bp, fn->stdarg, 1);
   bp_pack_value (&bp, fn->has_nonlocal_label, 1);
+  bp_pack_value (&bp, fn->has_forced_label_in_static, 1);
   bp_pack_value (&bp, fn->calls_alloca, 1);
   bp_pack_value (&bp, fn->calls_setjmp, 1);
   bp_pack_value (&bp, fn->has_force_vectorize_loops, 1);
index 8bbcf35ba27db2f9ffef67b49c7ef90ebc64fc35..451e65365fcc655176f80635a6e75618e55f813d 100644 (file)
@@ -1,3 +1,8 @@
+2016-03-16  Richard Henderson  <rth@redhat.com>
+
+       PR middle-end/70199
+       * gcc.c-torture/compile/pr70199.c: New.
+
 2016-03-16  H.J. Lu  <hongjiu.lu@intel.com>
 
        * gcc.dg/uninit-19.c: Run dos2unix.
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr70199.c b/gcc/testsuite/gcc.c-torture/compile/pr70199.c
new file mode 100644 (file)
index 0000000..a4323f0
--- /dev/null
@@ -0,0 +1,20 @@
+static volatile int v = 0;
+static
+void benchmark(long runs) {
+  void* labels[] = {
+    &&l0, &&l1, &&l2
+  };
+  for(unsigned int mask = 0x1F; mask > 0; mask >>= 1) {
+    unsigned lfsr = 0xACE1u;
+    long n = 10000000;
+    while(n > 0) {
+      l2: v;
+      l1: v;
+      goto *labels[lfsr & mask];
+      l0: n--;
+    }
+  }
+}
+int f(void) {
+  benchmark(10000000);
+}
index d52e0c6e20275c42018fc9b7a02e884476cc1edb..9d4f8f7815d56b8e4c066598be232cd22b3e7d75 100644 (file)
@@ -3504,33 +3504,13 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
   return use;
 }
 
-/* Callback through walk_tree.  Determine if a DECL_INITIAL makes reference
-   to a local label.  */
-
-static tree
-has_label_address_in_static_1 (tree *nodep, int *walk_subtrees, void *fnp)
-{
-  tree node = *nodep;
-  tree fn = (tree) fnp;
-
-  if (TREE_CODE (node) == LABEL_DECL && DECL_CONTEXT (node) == fn)
-    return node;
-
-  if (TYPE_P (node))
-    *walk_subtrees = 0;
-
-  return NULL_TREE;
-}
-
 /* Determine if the function can be copied.  If so return NULL.  If
    not return a string describng the reason for failure.  */
 
 const char *
-copy_forbidden (struct function *fun, tree fndecl)
+copy_forbidden (struct function *fun)
 {
   const char *reason = fun->cannot_be_copied_reason;
-  tree decl;
-  unsigned ix;
 
   /* Only examine the function once.  */
   if (fun->cannot_be_copied_set)
@@ -3549,19 +3529,12 @@ copy_forbidden (struct function *fun, tree fndecl)
       goto fail;
     }
 
-  FOR_EACH_LOCAL_DECL (fun, ix, decl)
-    if (TREE_CODE (decl) == VAR_DECL
-       && TREE_STATIC (decl)
-       && !DECL_EXTERNAL (decl)
-       && DECL_INITIAL (decl)
-       && walk_tree_without_duplicates (&DECL_INITIAL (decl),
-                                        has_label_address_in_static_1,
-                                        fndecl))
-      {
-       reason = G_("function %q+F can never be copied because it saves "
-                   "address of local label in a static variable");
-       goto fail;
-      }
+  if (fun->has_forced_label_in_static)
+    {
+      reason = G_("function %q+F can never be copied because it saves "
+                 "address of local label in a static variable");
+      goto fail;
+    }
 
  fail:
   fun->cannot_be_copied_reason = reason;
@@ -3705,7 +3678,7 @@ inline_forbidden_p (tree fndecl)
   bool forbidden_p = false;
 
   /* First check for shared reasons not to copy the code.  */
-  inline_forbidden_reason = copy_forbidden (fun, fndecl);
+  inline_forbidden_reason = copy_forbidden (fun);
   if (inline_forbidden_reason != NULL)
     return true;
 
@@ -5552,7 +5525,7 @@ bool
 tree_versionable_function_p (tree fndecl)
 {
   return (!lookup_attribute ("noclone", DECL_ATTRIBUTES (fndecl))
-         && copy_forbidden (DECL_STRUCT_FUNCTION (fndecl), fndecl) == NULL);
+         && copy_forbidden (DECL_STRUCT_FUNCTION (fndecl)) == NULL);
 }
 
 /* Delete all unreachable basic blocks and update callgraph.
index 4cc1f19223a3d93cb7acf9b4349199a5e6ee3c03..9ca2a91f08f25cbab059a1aebf38b5eef28dbbed 100644 (file)
@@ -217,7 +217,7 @@ extern tree remap_type (tree type, copy_body_data *id);
 extern gimple_seq copy_gimple_seq_and_replace_locals (gimple_seq seq);
 extern bool debug_find_tree (tree, tree);
 extern tree copy_fn (tree, tree&, tree&);
-extern const char *copy_forbidden (struct function *fun, tree fndecl);
+extern const char *copy_forbidden (struct function *fun);
 
 /* This is in tree-inline.c since the routine uses
    data structures from the inliner.  */