diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 22056f260a22a29c6b1354fcb36362161c11b061..bd9ce0f9dc280632297b87558ad6ac07cacd6eec 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2002-03-01  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+	* Makefile.in (CRTSTUFF_CFLAGS): Add -fno-zero-initialized-in-bss.
+	* doc/invoke.texi (-fno-zero-initialized-in-bss): Document.
+	* flags.h (flag_zero_initialized_in_bss): Declare.
+	* toplev.c (flag_zero_initialized_in_bss): New flag.
+	(lang_independent_options): Add flag_zero_initialized_in_bss.
+	* tree.c (initializer_zerop): New function.
+	* tree.h (initializer_zerop): Declare.
+	* varasm.c (assemble_variable): If we can emit bss, put zero
+	initializers in the bss section.
+
 2002-03-02  Alan Modra  <amodra@bigpond.net.au>
 
 	* config/rs6000/rs6000.h (ASM_WEAKEN_DECL): AIX assembler doesn't
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 604dd7dd8ff00707601b5469ec25df02bd6e1066..5d1802f174495bec352027b95ec12513b69fba1b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -372,7 +372,8 @@ TARGET_LIBGCC2_CFLAGS =
 
 # Options to use when compiling crtbegin/end.
 CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
-  -finhibit-size-directive -fno-inline-functions -fno-exceptions
+  -finhibit-size-directive -fno-inline-functions -fno-exceptions \
+  -fno-zero-initialized-in-bss
 
 # Additional sources to handle exceptions; overridden on ia64.
 LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8dab7a0f3a8004eaaef4b5ef021d2c0f2950b4dd..10b69c846d02612e3b8a403ab724020fe3aac665 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -273,6 +273,7 @@ in the following sections.
 -fno-function-cse  -fno-guess-branch-probability @gol
 -fno-inline  -fno-math-errno  -fno-peephole  -fno-peephole2 @gol
 -funsafe-math-optimizations -fno-trapping-math @gol
+-fno-zero-initialized-in-bss @gol
 -fomit-frame-pointer  -foptimize-register-move @gol
 -foptimize-sibling-calls  -fprefetch-loop-arrays @gol
 -freduce-all-givs -fregmove  -frename-registers @gol
@@ -3407,6 +3408,19 @@ an exact implementation of IEEE or ISO rules/specifications for
 math functions.
 
 The default is @option{-ftrapping-math}.
+
+@item -fno-zero-initialized-in-bss
+@opindex fno-zero-initialized-in-bss
+If the target supports a BSS section, GCC by default puts variables that
+are initialized to zero into BSS@.  This can save space in the resulting
+code.
+
+This option turns off this behavior because some programs explicitly
+rely on variables going to the data section.  E.g., so that the
+resulting executable can find the beginning of that section and/or make
+assumptions based on that.
+
+The default is @option{-fzero-initialized-in-bss}.
 @end table
 
 The following options control specific optimizations.  The @option{-O2}
diff --git a/gcc/flags.h b/gcc/flags.h
index 65353e61677f71b9b3deb2aa7bec16ce5d631fa3..6de5d9b59574e8fb46832c7b30def13fdec056cd 100644
--- a/gcc/flags.h
+++ b/gcc/flags.h
@@ -636,4 +636,7 @@ extern int flag_detailed_statistics;
 /* Nonzero means enable synchronous exceptions for non-call instructions.  */
 extern int flag_non_call_exceptions;
 
+/* Nonzero means put zero initialized data in the bss section.  */
+extern int flag_zero_initialized_in_bss;
+
 #endif /* ! GCC_FLAGS_H */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 83de90890ec1781ea8ba4a739d615917ef0bb961..74605824da8cea678ba10b1bdc38b5ae4e7bf5a7 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -803,6 +803,9 @@ int flag_gnu_linker = 0;
 int flag_gnu_linker = 1;
 #endif
 
+/* Nonzero means put zero initialized data in the bss section.  */
+int flag_zero_initialized_in_bss = 1;
+
 /* Enable SSA.  */
 int flag_ssa = 0;
 
@@ -1135,6 +1138,8 @@ static const lang_independent_options f_options[] =
    N_("Suppress output of instruction numbers and line number notes in debugging dumps") },
   {"instrument-functions", &flag_instrument_function_entry_exit, 1,
    N_("Instrument function entry/exit with profiling calls") },
+  {"zero-initialized-in-bss", &flag_zero_initialized_in_bss, 1,
+   N_("Put zero initialized data in the bss section") },
   {"ssa", &flag_ssa, 1,
    N_("Enable SSA optimizations") },
   {"ssa-ccp", &flag_ssa_ccp, 1,
diff --git a/gcc/tree.c b/gcc/tree.c
index 5e0210b7676f5413aba751cebf6548cdf6979ab7..de65191e672135ca4b91cb8271d3d2426dee68da 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4975,3 +4975,45 @@ make_vector (mode, innertype, unsignedp)
 
   return t;
 }
+
+/* Given an initializer INIT, return TRUE if INIT is zero or some
+   aggregate of zeros.  Otherwise return FALSE.  */
+
+bool
+initializer_zerop (init)
+     tree init;
+{
+  STRIP_NOPS (init);
+
+  switch (TREE_CODE (init))
+    {
+    case INTEGER_CST:
+      return integer_zerop (init);
+    case REAL_CST:
+      return real_zerop (init)
+	&& ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init));
+    case COMPLEX_CST:
+      return integer_zerop (init)
+	|| (real_zerop (init)
+	    && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_REALPART (init)))
+	    && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init))));
+    case CONSTRUCTOR:
+      {
+	if (AGGREGATE_TYPE_P (TREE_TYPE (init)))
+	{
+	  tree aggr_init = TREE_OPERAND (init, 1);
+	  
+	  while (aggr_init)
+	    {
+	      if (! initializer_zerop (TREE_VALUE (aggr_init)))
+		return false;
+	      aggr_init = TREE_CHAIN (aggr_init);
+	    }
+	  return true;
+	}
+	return false;
+      }
+    default:
+      return false;
+    }
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index b13fc53cdb5397a69cce7035a03f76bc957266ac..68b96e8258771c40467cbf32a89a357a65dfee8b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2495,6 +2495,11 @@ extern int list_length			PARAMS ((tree));
 
 extern int fields_length		PARAMS ((tree));
 
+/* Given an initializer INIT, return TRUE if INIT is zero or some
+   aggregate of zeros.  Otherwise return FALSE.  */
+
+extern bool initializer_zerop		PARAMS ((tree));
+
 /* integer_zerop (tree x) is nonzero if X is an integer constant of value 0 */
 
 extern int integer_zerop		PARAMS ((tree));
diff --git a/gcc/varasm.c b/gcc/varasm.c
index f8fb16cc88032dd6553963298fc2261be0e893d0..e7505a8c39cd93913726cd1f4eea197048eea65b 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -1608,7 +1608,12 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
 
   /* Handle uninitialized definitions.  */
 
-  if ((DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)
+  if ((DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node
+#if defined ASM_EMIT_BSS
+       || (flag_zero_initialized_in_bss
+	   && initializer_zerop (DECL_INITIAL (decl)))
+#endif
+       )
       /* If the target can't output uninitialized but not common global data
 	 in .bss, then we have to use .data.  */
 #if ! defined ASM_EMIT_BSS