diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 8283e959c89..6f8288326ee 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -2394,6 +2394,10 @@ handle_noinit_attribute (tree * node,
 	     valid.  */
 	  if (DECL_COMMON (*node))
 	    DECL_COMMON (*node) = 0;
+
+	  /* Set DECL_NOINIT_P to indicate the decaration should not be
+	     initialized by the startup code.  */
+	  DECL_NOINIT_P (*node) = 1;
 	}
     }
 
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 96d6cf609fe..4176f761482 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -120,7 +120,7 @@ public:
       used_from_other_partition (false), in_other_partition (false),
       address_taken (false), in_init_priority_hash (false),
       need_lto_streaming (false), offloadable (false), ifunc_resolver (false),
-      order (false), next_sharing_asm_name (NULL),
+      noinit (false), order (false), next_sharing_asm_name (NULL),
       previous_sharing_asm_name (NULL), same_comdat_group (NULL), ref_list (),
       alias_target (NULL), lto_file_data (NULL), aux (NULL),
       x_comdat_group (NULL_TREE), x_section (NULL)
@@ -577,6 +577,10 @@ public:
   /* Set when symbol is an IFUNC resolver.  */
   unsigned ifunc_resolver : 1;
 
+  /* Set when the symbol is decorated with the "noinit" attribute,
+     which indicates it should not be initialized by the runtime
+     startup code.  */
+  unsigned noinit : 1;
 
   /* Ordering of all symtab entries.  */
   int order;
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 19ae8763373..9437e7b719e 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -915,6 +915,8 @@ process_function_and_variable_attributes (cgraph_node *first,
       if (DECL_EXTERNAL (decl)
 	  && DECL_INITIAL (decl))
 	varpool_node::finalize_decl (decl);
+      if (DECL_NOINIT_P (decl))
+	vnode->noinit = true;
       if (DECL_PRESERVE_P (decl))
 	vnode->force_output = true;
       else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 93a99f3465b..8d6ba74dcad 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -631,6 +631,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
   bp_pack_value (&bp, node->tls_model, 3);
   bp_pack_value (&bp, node->used_by_single_function, 1);
   bp_pack_value (&bp, node->dynamically_initialized, 1);
+  bp_pack_value (&bp, node->noinit, 1);
   streamer_write_bitpack (&bp);
 
   group = node->get_comdat_group ();
@@ -1395,6 +1396,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
   node->tls_model = (enum tls_model)bp_unpack_value (&bp, 3);
   node->used_by_single_function = (enum tls_model)bp_unpack_value (&bp, 1);
   node->dynamically_initialized = bp_unpack_value (&bp, 1);
+  node->noinit = bp_unpack_value (&bp, 1);
   group = read_identifier (ib);
   if (group)
     {
diff --git a/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c b/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c
index 20a2a452e79..c8fa22bf38b 100644
--- a/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c
+++ b/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 /* { dg-require-effective-target noinit } */
-/* { dg-options "-O2" } */
+/* { dg-options "-Wattributes" } */
 /* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */
 
 /* This test checks that noinit data is handled correctly.
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 8439720baea..4122285cc1d 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -368,7 +368,7 @@ proc check_weak_override_available { } {
     return [check_weak_available]
 }
 
-# The noinit attribute is only supported by some targets.
+# The "noinit" attribute is only supported by some targets.
 # This proc returns 1 if it's supported, 0 if it's not.
 
 proc check_effective_target_noinit { } {
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 752bec31c3f..b2deb332ce5 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1691,6 +1691,7 @@ struct GTY(()) tree_decl_common {
   unsigned abstract_flag : 1;
   unsigned artificial_flag : 1;
   unsigned preserve_flag: 1;
+  unsigned noinit_flag: 1;
   unsigned debug_expr_is_from : 1;
 
   unsigned lang_flag_0 : 1;
diff --git a/gcc/tree.h b/gcc/tree.h
index f43ac9f1942..ac73f3c3af9 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2648,6 +2648,12 @@ extern tree vector_element_bits_tree (const_tree);
 #define DECL_PRESERVE_P(DECL) \
   DECL_COMMON_CHECK (DECL)->decl_common.preserve_flag
 
+/* Nonzero for a decl that is decorated with the "noinit" attribute.
+   decls with this attribute are placed into a special section so they are not
+   initialized by the target's startup code.  */
+#define DECL_NOINIT_P(DECL) \
+  DECL_COMMON_CHECK (DECL)->decl_common.noinit_flag
+
 /* For function local variables of COMPLEX and VECTOR types,
    indicates that the variable is not aliased, and that all
    modifications to the variable have been adjusted so that
diff --git a/gcc/varasm.c b/gcc/varasm.c
index ea0b59cf44a..0d44342e813 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -1156,6 +1156,7 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
     {
       vnode = vnode->ultimate_alias_target ();
       decl = vnode->decl;
+      DECL_NOINIT_P (decl) = vnode->noinit;
     }
 
   if (TREE_TYPE (decl) != error_mark_node)
@@ -1203,6 +1204,7 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
 
   if (ADDR_SPACE_GENERIC_P (as)
       && !DECL_THREAD_LOCAL_P (decl)
+      && !DECL_NOINIT_P (decl)
       && !(prefer_noswitch_p && targetm.have_switchable_bss_sections)
       && bss_initializer_p (decl))
     {
@@ -7004,13 +7006,11 @@ default_elf_select_section (tree decl, int reloc,
       sname = ".tdata";
       break;
     case SECCAT_BSS:
-      if (DECL_P (decl)
-	  && lookup_attribute ("noinit", DECL_ATTRIBUTES (decl)) != NULL_TREE)
+      if (DECL_P (decl) && DECL_NOINIT_P (decl))
 	{
 	  sname = ".noinit";
 	  break;
 	}
-
       if (bss_section)
 	return bss_section;
       sname = ".bss";
@@ -7073,6 +7073,11 @@ default_unique_section (tree decl, int reloc)
       prefix = one_only ? ".s" : ".sdata";
       break;
     case SECCAT_BSS:
+      if (DECL_P (decl) && DECL_NOINIT_P (decl))
+	{
+	  prefix = one_only ? ".n" : ".noinit";
+	  break;
+	}
       prefix = one_only ? ".b" : ".bss";
       break;
     case SECCAT_SBSS:
