diff mbox

PR other/54324: allow bootstrapping with older compilers

Message ID 50C8111E.9020103@redhat.com
State New
Headers show

Commit Message

Aldy Hernandez Dec. 12, 2012, 5:07 a.m. UTC
Hi Richard.

Your last patch for this PR suggested we verify our assumptions wrt a 
least common C++ compiler to build trunk with.  Since I already had the 
offended system at hand (Red Hat Linux 8.0), I decided to investigate a 
bit further.

g++ 3.4 builds trunk just fine, but anything prior to this chokes on a 
variety of inputs.  The patch below fixes them all, and gets 4.8 to 
bootstrap with a GCC 3.2 system.

I don't know how much of this is a fool's errand, and if we want to 
commit to supporting < GCC 3.4, but your patch suggested c++98, and GCC 
3.2 claims such.

The fixed issues are as follows:

1. Older G++ cannot understand attributes among arguments:

	int foo(int bar __attribute__ ((__unused__)))

    It looks like we already have ARG_UNUSED for this precise problem,
    and it is already predicated on !__cplusplus || GCC_VERSION >= 3004.
    However, we've deviated from using ARG_UNUSED
    throughout the compiler, and I spent hours changing
    ATTRIBUTE_UNUSED into ARG_UNUSED until I gave up.  It's EVERYWHERE
    in the compiler-- all the way into our gen*.c files.  It seemed a lot
    simpler just changing the definition of ATTRIBUTE_UNUSED.

    Perhaps we could even deprecate ARG_UNUSED?

2. gcov-io.c uses __builtin_popcountll and __builtin_clzll.  Older
    GCC's do not have this.  For that matter, how does this even work on
    non-GCC systems?

    I have abstracted the non built-in versions we have for these in
    hwint.c, which seem written for older GCC's and non GCC's.

    I am not a huge fan of the new include file, but I really didn't
    want to duplicate code.  I'm open to suggestions.

3. Derived classes that include a union template die miserably on g++
    3.2.  Thankfully, this works:

	-struct ssa_name_var_hash : typed_noop_remove <union tree_node>
	+struct ssa_name_var_hash : typed_noop_remove <tree_node>

4. Type checking as part of a `for' initializer segfaults on g++ 3.2:

	for (type = TYPE_MAIN_VARIANT (blah); ....)

    The only reasonable thing I could think of, was disabling the tree
    checking code for older compilers.

I really don't want to spend much more time on this, but at the same 
time, I don't want to throw away a day's work, especially if it could 
conceivably help us with (older) non-GCC bootstrap compilers.

The attached patch bootstraps trunk on GCC 3.2 on a Red Hat Linux 8.0 
system (i686) configured with:

	blah/configure --enable-languages=c,c++ --disable-libsanitizer

libsanitizer seems to be a moving target and it currently has issues 
with the RHL8.0 header files (earlier today it had other problems :)).

What are your thoughts on this?
PR other/54324
	* Makefile.in (GCOV_IO_C): New.
	(hwint.o): Depend on hwint-helper.c
	(coverage.o): Depend on $(GCOV_IO_C).
	(gcov.o): Same.
	(gcov-dump.o): Same.
	* basic-block.h (gt_ggc_mx): Fix prototype to work on older
	compilers.
	(gt_pch_nx): Same.
	* gcov-io.c: Include hwint-helper.c.
	(gcov_read_summary): Rename __builtin_popcountll to my_popcount.
	(gcov_histo_index): Rename __builtin_clzll to my_clz_hwi.
	* hwint.c: Move floor_log2, ceil_log2, exact_log2, ctz_hwi,
	clz_hwi, ffs_hwi, and popcount_hwi into...
	* hwint-helper.c: New file.
	* tree-ssa-coalesce.c (struct ssa_name_var_hash): Remove union
	specifier.
	* tree.h: Disable checking code for GCC < 3.4.
	* cp/cp-tree.h: Disable checking code for GCC < 3.4.
	* include/ansidecl.h: Do not set __attribute__ for GCC < 3.4.

Comments

Richard Biener Dec. 12, 2012, 9:33 a.m. UTC | #1
On Tue, 11 Dec 2012, Aldy Hernandez wrote:

> Hi Richard.
> 
> Your last patch for this PR suggested we verify our assumptions wrt a least
> common C++ compiler to build trunk with.  Since I already had the offended
> system at hand (Red Hat Linux 8.0), I decided to investigate a bit further.
> 
> g++ 3.4 builds trunk just fine, but anything prior to this chokes on a variety
> of inputs.  The patch below fixes them all, and gets 4.8 to bootstrap with a
> GCC 3.2 system.
> 
> I don't know how much of this is a fool's errand, and if we want to commit to
> supporting < GCC 3.4, but your patch suggested c++98, and GCC 3.2 claims such.
> 
> The fixed issues are as follows:
> 
> 1. Older G++ cannot understand attributes among arguments:
> 
> 	int foo(int bar __attribute__ ((__unused__)))
> 
>    It looks like we already have ARG_UNUSED for this precise problem,
>    and it is already predicated on !__cplusplus || GCC_VERSION >= 3004.
>    However, we've deviated from using ARG_UNUSED
>    throughout the compiler, and I spent hours changing
>    ATTRIBUTE_UNUSED into ARG_UNUSED until I gave up.  It's EVERYWHERE
>    in the compiler-- all the way into our gen*.c files.  It seemed a lot
>    simpler just changing the definition of ATTRIBUTE_UNUSED.
> 
>    Perhaps we could even deprecate ARG_UNUSED?
> 
> 2. gcov-io.c uses __builtin_popcountll and __builtin_clzll.  Older
>    GCC's do not have this.  For that matter, how does this even work on
>    non-GCC systems?
> 
>    I have abstracted the non built-in versions we have for these in
>    hwint.c, which seem written for older GCC's and non GCC's.
> 
>    I am not a huge fan of the new include file, but I really didn't
>    want to duplicate code.  I'm open to suggestions.
> 
> 3. Derived classes that include a union template die miserably on g++
>    3.2.  Thankfully, this works:
> 
> 	-struct ssa_name_var_hash : typed_noop_remove <union tree_node>
> 	+struct ssa_name_var_hash : typed_noop_remove <tree_node>
> 
> 4. Type checking as part of a `for' initializer segfaults on g++ 3.2:
> 
> 	for (type = TYPE_MAIN_VARIANT (blah); ....)
> 
>    The only reasonable thing I could think of, was disabling the tree
>    checking code for older compilers.
> 
> I really don't want to spend much more time on this, but at the same time, I
> don't want to throw away a day's work, especially if it could conceivably help
> us with (older) non-GCC bootstrap compilers.
> 
> The attached patch bootstraps trunk on GCC 3.2 on a Red Hat Linux 8.0 system
> (i686) configured with:
> 
> 	blah/configure --enable-languages=c,c++ --disable-libsanitizer
> 
> libsanitizer seems to be a moving target and it currently has issues with the
> RHL8.0 header files (earlier today it had other problems :)).
> 
> What are your thoughts on this?

In general I think that trying to support anything before the C++
parser rewrite (thus, 3.4.x) is going to be a nightmare ...

But of course as you show it _is_ possible at the moment at least.
Patches for 1. and 3. I'd call obvious.  For 3. I wonder why we
ever build gcov-io with the host compiler - oh, we include it from
coverage.c ... please file a bug for this, the uses were introduced
recently by Theresa Johnson from google, that's of course a release
blocker anyway.  For 4. I think we should simply document that
you need to build with --disable-stage1-checking (it's one case that
hints at we don't want to support 3.2 - does 3.3 work here?  With
our SLE9 gcc 3.3 hammer branch based compiler I get even some more
ICEs).

Thanks,
Richard.
Steven Bosscher Dec. 12, 2012, 10:21 a.m. UTC | #2
On Wed, Dec 12, 2012 at 6:07 AM, Aldy Hernandez wrote:
> I don't know how much of this is a fool's errand, and if we want to commit
> to supporting < GCC 3.4, but your patch suggested c++98, and GCC 3.2 claims
> such.

GCC 3.2 claims many things, but any GCC that has the old C++ parser
has known non-conformances. IMHO we should only support GCC versions
with the "new" C++ parser, i.e. GCC 3.4 and up.


>    Perhaps we could even deprecate ARG_UNUSED?

+1


> 2. gcov-io.c uses __builtin_popcountll and __builtin_clzll.  Older
>    GCC's do not have this.  For that matter, how does this even work on
>    non-GCC systems?

This'd be a bug.


> I really don't want to spend much more time on this, but at the same time, I
> don't want to throw away a day's work, especially if it could conceivably
> help us with (older) non-GCC bootstrap compilers.

I think the work you've done here is great, but even if you'd fix
these issues, there is very little that can be done to avoid the same
mistakes, or new ones, creeping back in and breaking builds with older
compilers.


> What are your thoughts on this?

At least: Thanks for uncovering the gcov-io.c bug :-)

Ciao!
Steven
Teresa Johnson Dec. 12, 2012, 2:53 p.m. UTC | #3
On Wed, Dec 12, 2012 at 2:21 AM, Steven Bosscher <stevenb.gcc@gmail.com> wrote:
> On Wed, Dec 12, 2012 at 6:07 AM, Aldy Hernandez wrote:
>> I don't know how much of this is a fool's errand, and if we want to commit
>> to supporting < GCC 3.4, but your patch suggested c++98, and GCC 3.2 claims
>> such.
>
> GCC 3.2 claims many things, but any GCC that has the old C++ parser
> has known non-conformances. IMHO we should only support GCC versions
> with the "new" C++ parser, i.e. GCC 3.4 and up.
>
>
>>    Perhaps we could even deprecate ARG_UNUSED?
>
> +1
>
>
>> 2. gcov-io.c uses __builtin_popcountll and __builtin_clzll.  Older
>>    GCC's do not have this.  For that matter, how does this even work on
>>    non-GCC systems?
>
> This'd be a bug.
>
>
>> I really don't want to spend much more time on this, but at the same time, I
>> don't want to throw away a day's work, especially if it could conceivably
>> help us with (older) non-GCC bootstrap compilers.
>
> I think the work you've done here is great, but even if you'd fix
> these issues, there is very little that can be done to avoid the same
> mistakes, or new ones, creeping back in and breaking builds with older
> compilers.
>
>
>> What are your thoughts on this?
>
> At least: Thanks for uncovering the gcov-io.c bug :-)

Yes, thanks for fixing this. The fix looks good to me.

Thanks,
Teresa

>
> Ciao!
> Steven



--
Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413
Richard Biener Dec. 12, 2012, 3:25 p.m. UTC | #4
On Wed, 12 Dec 2012, Teresa Johnson wrote:

> On Wed, Dec 12, 2012 at 2:21 AM, Steven Bosscher <stevenb.gcc@gmail.com> wrote:
> > On Wed, Dec 12, 2012 at 6:07 AM, Aldy Hernandez wrote:
> >> I don't know how much of this is a fool's errand, and if we want to commit
> >> to supporting < GCC 3.4, but your patch suggested c++98, and GCC 3.2 claims
> >> such.
> >
> > GCC 3.2 claims many things, but any GCC that has the old C++ parser
> > has known non-conformances. IMHO we should only support GCC versions
> > with the "new" C++ parser, i.e. GCC 3.4 and up.
> >
> >
> >>    Perhaps we could even deprecate ARG_UNUSED?
> >
> > +1
> >
> >
> >> 2. gcov-io.c uses __builtin_popcountll and __builtin_clzll.  Older
> >>    GCC's do not have this.  For that matter, how does this even work on
> >>    non-GCC systems?
> >
> > This'd be a bug.
> >
> >
> >> I really don't want to spend much more time on this, but at the same time, I
> >> don't want to throw away a day's work, especially if it could conceivably
> >> help us with (older) non-GCC bootstrap compilers.
> >
> > I think the work you've done here is great, but even if you'd fix
> > these issues, there is very little that can be done to avoid the same
> > mistakes, or new ones, creeping back in and breaking builds with older
> > compilers.
> >
> >
> >> What are your thoughts on this?
> >
> > At least: Thanks for uncovering the gcov-io.c bug :-)
> 
> Yes, thanks for fixing this. The fix looks good to me.

In fact it looks ugly ... can't we avoid this code duplication somehow?

Richard.
Teresa Johnson Dec. 12, 2012, 3:34 p.m. UTC | #5
On Wed, Dec 12, 2012 at 7:25 AM, Richard Biener <rguenther@suse.de> wrote:
> On Wed, 12 Dec 2012, Teresa Johnson wrote:
>
>> On Wed, Dec 12, 2012 at 2:21 AM, Steven Bosscher <stevenb.gcc@gmail.com> wrote:
>> > On Wed, Dec 12, 2012 at 6:07 AM, Aldy Hernandez wrote:
>> >> I don't know how much of this is a fool's errand, and if we want to commit
>> >> to supporting < GCC 3.4, but your patch suggested c++98, and GCC 3.2 claims
>> >> such.
>> >
>> > GCC 3.2 claims many things, but any GCC that has the old C++ parser
>> > has known non-conformances. IMHO we should only support GCC versions
>> > with the "new" C++ parser, i.e. GCC 3.4 and up.
>> >
>> >
>> >>    Perhaps we could even deprecate ARG_UNUSED?
>> >
>> > +1
>> >
>> >
>> >> 2. gcov-io.c uses __builtin_popcountll and __builtin_clzll.  Older
>> >>    GCC's do not have this.  For that matter, how does this even work on
>> >>    non-GCC systems?
>> >
>> > This'd be a bug.
>> >
>> >
>> >> I really don't want to spend much more time on this, but at the same time, I
>> >> don't want to throw away a day's work, especially if it could conceivably
>> >> help us with (older) non-GCC bootstrap compilers.
>> >
>> > I think the work you've done here is great, but even if you'd fix
>> > these issues, there is very little that can be done to avoid the same
>> > mistakes, or new ones, creeping back in and breaking builds with older
>> > compilers.
>> >
>> >
>> >> What are your thoughts on this?
>> >
>> > At least: Thanks for uncovering the gcov-io.c bug :-)
>>
>> Yes, thanks for fixing this. The fix looks good to me.
>
> In fact it looks ugly ... can't we avoid this code duplication somehow?

If you prefer, I can simply inline the popcount/clz functionality into
gcov-io.c directly (or at least when not using recent versions of
GCC). But that in fact would be duplicating the code, when I thought
Aldy's solution was trying to avoid that by providing the more general
interfaces.

Teresa

>
> Richard.



--
Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413
diff mbox

Patch

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 9efc2d3..e04e365 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -879,6 +879,7 @@  GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h $(VEC_H) \
 	tree-ssa-alias.h $(INTERNAL_FN_H)
 TRANS_MEM_H = trans-mem.h
 GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
+GCOV_IO_C = gcov-io.c hwint-helper.c
 COVERAGE_H = coverage.h $(GCOV_IO_H)
 DEMANGLE_H = $(srcdir)/../include/demangle.h
 RECOG_H = recog.h
@@ -2700,7 +2701,7 @@  toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    $(TREE_PRETTY_PRINT_H) opts-diagnostic.h $(COMMON_TARGET_H) \
    tsan.h
 
-hwint.o : hwint.c $(CONFIG_H) $(SYSTEM_H) $(DIAGNOSTIC_CORE_H)
+hwint.o : hwint.c $(CONFIG_H) $(SYSTEM_H) $(DIAGNOSTIC_CORE_H) hwint-helper.c
 
 passes.o : passes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    $(RTL_H) $(FUNCTION_H) $(FLAGS_H) $(INPUT_H) $(INSN_ATTR_H) output.h \
@@ -2945,7 +2946,7 @@  ipa-pure-const.o : ipa-pure-const.c $(CONFIG_H) $(SYSTEM_H) \
 coverage.o : coverage.c $(GCOV_IO_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h \
    $(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) \
    $(FUNCTION_H) $(BASIC_BLOCK_H) toplev.h $(DIAGNOSTIC_CORE_H) $(GGC_H) langhooks.h $(COVERAGE_H) \
-   tree-iterator.h $(CGRAPH_H) gcov-io.c $(TM_P_H) \
+   tree-iterator.h $(CGRAPH_H) $(GCOV_IO_C) $(TM_P_H) \
    $(DIAGNOSTIC_CORE_H) intl.h gt-coverage.h $(TARGET_H) $(HASH_TABLE_H)
 cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h $(TM_H) $(RTL_H) \
    $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(RECOG_H) \
@@ -4041,9 +4042,9 @@  s-iov: build/gcov-iov$(build_exeext) $(BASEVER) $(DEVPHASE)
 	$(SHELL) $(srcdir)/../move-if-change tmp-gcov-iov.h gcov-iov.h
 	$(STAMP) s-iov
 
-gcov.o: gcov.c gcov-io.c $(GCOV_IO_H) intl.h $(SYSTEM_H) coretypes.h $(TM_H) \
+gcov.o: gcov.c $(GCOV_IO_C) $(GCOV_IO_H) intl.h $(SYSTEM_H) coretypes.h $(TM_H) \
    $(CONFIG_H) version.h $(DIAGNOSTIC_H)
-gcov-dump.o: gcov-dump.c gcov-io.c $(GCOV_IO_H) $(SYSTEM_H) coretypes.h \
+gcov-dump.o: gcov-dump.c $(GCOV_IO_C) $(GCOV_IO_H) $(SYSTEM_H) coretypes.h \
    $(TM_H) $(CONFIG_H) version.h intl.h $(DIAGNOSTIC_H)
 
 GCOV_OBJS = gcov.o
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 03ba0ce..8262a99 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -63,9 +63,9 @@  struct GTY((user)) edge_def {
 
 
 /* Garbage collection and PCH support for edge_def.  */
-extern void gt_ggc_mx (edge_def *e);
-extern void gt_pch_nx (edge_def *e);
-extern void gt_pch_nx (edge_def *e, gt_pointer_operator, void *);
+extern void gt_ggc_mx (edge_def *& e);
+extern void gt_pch_nx (edge_def *& e);
+extern void gt_pch_nx (edge_def *& e, gt_pointer_operator, void *);
 
 /* Masks for edge.flags.  */
 #define DEF_EDGE_FLAG(NAME,IDX) EDGE_##NAME = 1 << IDX ,
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 465fa0f..b9fce12 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -223,7 +223,7 @@  c-common.h, not after.
 #define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) \
   TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM)
 
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
 #define THUNK_FUNCTION_CHECK(NODE) __extension__			\
 ({  __typeof (NODE) const __t = (NODE);					\
     if (TREE_CODE (__t) != FUNCTION_DECL || !__t->decl_common.lang_specific \
@@ -1437,7 +1437,7 @@  struct GTY((variable_size)) lang_type {
   } GTY((desc ("%h.h.is_lang_type_class"))) u;
 };
 
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
 
 #define LANG_TYPE_CLASS_CHECK(NODE) __extension__		\
 ({  struct lang_type *lt = TYPE_LANG_SPECIFIC (NODE);		\
@@ -2019,7 +2019,7 @@  struct GTY((variable_size)) lang_decl {
 #define STRIP_TEMPLATE(NODE) \
   (TREE_CODE (NODE) == TEMPLATE_DECL ? DECL_TEMPLATE_RESULT (NODE) : NODE)
 
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
 
 #define LANG_DECL_MIN_CHECK(NODE) __extension__			\
 ({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE);		\
diff --git a/gcc/gcov-io.c b/gcc/gcov-io.c
index f45c32c..ec73aec 100644
--- a/gcc/gcov-io.c
+++ b/gcc/gcov-io.c
@@ -517,6 +517,17 @@  gcov_read_string (void)
 }
 #endif
 
+#if GCC_VERSION < 3004
+#define HWINT_STATIC(TYPE) static TYPE ATTRIBUTE_UNUSED
+#define HWINT_PREFIX(NAME) my_##NAME
+#include "hwint-helper.c"
+#undef HWINT_STATIC
+#undef HWINT_PREFIX
+#else
+#  define my_popcount_hwi __builtin_popcountll
+#  define my_clz_hwi __builtin_clzll
+#endif
+
 GCOV_LINKAGE void
 gcov_read_summary (struct gcov_summary *summary)
 {
@@ -538,7 +549,7 @@  gcov_read_summary (struct gcov_summary *summary)
       for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
         {
           histo_bitvector[bv_ix] = gcov_read_unsigned ();
-          h_cnt += __builtin_popcountll (histo_bitvector[bv_ix]);
+          h_cnt += my_popcount_hwi (histo_bitvector[bv_ix]);
         }
       bv_ix = 0;
       h_ix = 0;
@@ -642,7 +653,7 @@  gcov_histo_index (gcov_type value)
 
   /* Find the place of the most-significant bit set.  */
   if (v > 0)
-    r = 63 - __builtin_clzll (v);
+    r = 63 - my_clz_hwi (v);
 
   /* If at most the 2 least significant bits are set (value is
      0 - 3) then that value is our index into the lowest set of
diff --git a/gcc/hwint-helper.c b/gcc/hwint-helper.c
new file mode 100644
index 0000000..2ece45a
--- /dev/null
+++ b/gcc/hwint-helper.c
@@ -0,0 +1,130 @@ 
+/* Supporting bit functions for older versions of GCC, and non-GCC
+   bootstrap compilers.
+
+   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2012 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#if GCC_VERSION < 3004
+
+/* The functions clz_hwi, ctz_hwi, ffs_hwi, floor_log2, ceil_log2,
+   and exact_log2 are defined as inline functions in hwint.h
+   if GCC_VERSION >= 3004.
+   The definitions here are used for older versions of GCC and
+   non-GCC bootstrap compilers.  */
+
+/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
+   If X is 0, return -1.  */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (floor_log2) (unsigned HOST_WIDE_INT x)
+{
+  int t = 0;
+
+  if (x == 0)
+    return -1;
+
+  if (HOST_BITS_PER_WIDE_INT > 64)
+    if (x >= (unsigned HOST_WIDE_INT) 1 << (t + 64))
+      t += 64;
+  if (HOST_BITS_PER_WIDE_INT > 32)
+    if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 32))
+      t += 32;
+  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 16))
+    t += 16;
+  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 8))
+    t += 8;
+  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 4))
+    t += 4;
+  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 2))
+    t += 2;
+  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 1))
+    t += 1;
+
+  return t;
+}
+
+/* Given X, an unsigned number, return the largest Y such that 2**Y >= X.  */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (ceil_log2) (unsigned HOST_WIDE_INT x)
+{
+  return HWINT_PREFIX (floor_log2) (x - 1) + 1;
+}
+
+/* Return the logarithm of X, base 2, considering X unsigned,
+   if X is a power of 2.  Otherwise, returns -1.  */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (exact_log2) (unsigned HOST_WIDE_INT x)
+{
+  if (x != (x & -x))
+    return -1;
+  return HWINT_PREFIX (floor_log2) (x);
+}
+
+/* Given X, an unsigned number, return the number of least significant bits
+   that are zero.  When X == 0, the result is the word size.  */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (ctz_hwi) (unsigned HOST_WIDE_INT x)
+{
+  return x ? HWINT_PREFIX (floor_log2) (x & -x) : HOST_BITS_PER_WIDE_INT;
+}
+
+/* Similarly for most significant bits.  */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (clz_hwi) (unsigned HOST_WIDE_INT x)
+{
+  return HOST_BITS_PER_WIDE_INT - 1 - HWINT_PREFIX (floor_log2) (x);
+}
+
+/* Similar to ctz_hwi, except that the least significant bit is numbered
+   starting from 1, and X == 0 yields 0.  */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (ffs_hwi) (unsigned HOST_WIDE_INT x)
+{
+  return 1 + HWINT_PREFIX (floor_log2) (x & -x);
+}
+
+/* Return the number of set bits in X.  */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (popcount_hwi) (unsigned HOST_WIDE_INT x)
+{
+  int i, ret = 0;
+  size_t bits = sizeof (x) * CHAR_BIT;
+
+  for (i = 0; i < bits; i += 1)
+    {
+      ret += x & 1;
+      x >>= 1;
+    }
+
+  return ret;
+}
+
+#endif /* GCC_VERSION < 3004 */
diff --git a/gcc/hwint.c b/gcc/hwint.c
index b7bcfa5..07447e1 100644
--- a/gcc/hwint.c
+++ b/gcc/hwint.c
@@ -23,108 +23,11 @@  along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "diagnostic-core.h"
 
-#if GCC_VERSION < 3004
-
-/* The functions clz_hwi, ctz_hwi, ffs_hwi, floor_log2, ceil_log2,
-   and exact_log2 are defined as inline functions in hwint.h
-   if GCC_VERSION >= 3004.
-   The definitions here are used for older versions of GCC and
-   non-GCC bootstrap compilers.  */
-
-/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
-   If X is 0, return -1.  */
-
-int
-floor_log2 (unsigned HOST_WIDE_INT x)
-{
-  int t = 0;
-
-  if (x == 0)
-    return -1;
-
-  if (HOST_BITS_PER_WIDE_INT > 64)
-    if (x >= (unsigned HOST_WIDE_INT) 1 << (t + 64))
-      t += 64;
-  if (HOST_BITS_PER_WIDE_INT > 32)
-    if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 32))
-      t += 32;
-  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 16))
-    t += 16;
-  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 8))
-    t += 8;
-  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 4))
-    t += 4;
-  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 2))
-    t += 2;
-  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 1))
-    t += 1;
-
-  return t;
-}
-
-/* Given X, an unsigned number, return the largest Y such that 2**Y >= X.  */
-
-int
-ceil_log2 (unsigned HOST_WIDE_INT x)
-{
-  return floor_log2 (x - 1) + 1;
-}
-
-/* Return the logarithm of X, base 2, considering X unsigned,
-   if X is a power of 2.  Otherwise, returns -1.  */
-
-int
-exact_log2 (unsigned HOST_WIDE_INT x)
-{
-  if (x != (x & -x))
-    return -1;
-  return floor_log2 (x);
-}
-
-/* Given X, an unsigned number, return the number of least significant bits
-   that are zero.  When X == 0, the result is the word size.  */
-
-int
-ctz_hwi (unsigned HOST_WIDE_INT x)
-{
-  return x ? floor_log2 (x & -x) : HOST_BITS_PER_WIDE_INT;
-}
-
-/* Similarly for most significant bits.  */
-
-int
-clz_hwi (unsigned HOST_WIDE_INT x)
-{
-  return HOST_BITS_PER_WIDE_INT - 1 - floor_log2(x);
-}
-
-/* Similar to ctz_hwi, except that the least significant bit is numbered
-   starting from 1, and X == 0 yields 0.  */
-
-int
-ffs_hwi (unsigned HOST_WIDE_INT x)
-{
-  return 1 + floor_log2 (x & -x);
-}
-
-/* Return the number of set bits in X.  */
-
-int
-popcount_hwi (unsigned HOST_WIDE_INT x)
-{
-  int i, ret = 0;
-  size_t bits = sizeof (x) * CHAR_BIT;
-
-  for (i = 0; i < bits; i += 1)
-    {
-      ret += x & 1;
-      x >>= 1;
-    }
-
-  return ret;
-}
-
-#endif /* GCC_VERSION < 3004 */
+#define HWINT_STATIC(TYPE) TYPE
+#define HWINT_PREFIX(NAME) NAME
+#include "hwint-helper.c"
+#undef HWINT_STATIC
+#undef HWINT_PREFIX
 
 /* Compute the absolute value of X.  */
 
diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c
index ce04fdf..47eba97 100644
--- a/gcc/tree-ssa-coalesce.c
+++ b/gcc/tree-ssa-coalesce.c
@@ -1259,7 +1259,7 @@  coalesce_partitions (var_map map, ssa_conflicts_p graph, coalesce_list_p cl,
 
 /* Hashtable support for storing SSA names hashed by their SSA_NAME_VAR.  */
 
-struct ssa_name_var_hash : typed_noop_remove <union tree_node>
+struct ssa_name_var_hash : typed_noop_remove <tree_node>
 {
   typedef union tree_node value_type;
   typedef union tree_node compare_type;
diff --git a/gcc/tree.h b/gcc/tree.h
index 9f17253..ec5cf94 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -743,7 +743,7 @@  enum tree_node_structure_enum {
 
 /* When checking is enabled, errors will be generated if a tree node
    is accessed incorrectly. The macros die with a fatal error.  */
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
 
 #define TREE_CHECK(T, CODE) \
 (tree_check ((T), __FILE__, __LINE__, __FUNCTION__, (CODE)))
@@ -3662,7 +3662,7 @@  union GTY ((ptr_alias (union lang_tree_node),
   struct tree_target_option GTY ((tag ("TS_TARGET_OPTION"))) target_option;
 };
 
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
 
 inline tree
 tree_check (tree __t, const char *__f, int __l, const char *__g, tree_code __c)
@@ -4094,7 +4094,7 @@  tree_operand_length (const_tree node)
     return TREE_CODE_LENGTH (TREE_CODE (node));
 }
 
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
 
 /* Special checks for TREE_OPERANDs.  */
 inline tree *
diff --git a/include/ansidecl.h b/include/ansidecl.h
index 23d85bf..e67123d 100644
--- a/include/ansidecl.h
+++ b/include/ansidecl.h
@@ -280,7 +280,11 @@  So instead we use the macro below and test it against specific values.  */
 #endif
 
 #ifndef ATTRIBUTE_UNUSED
-#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#if GCC_VERSION >= 3004
+#  define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#else
+#define ATTRIBUTE_UNUSED
+#endif
 #endif /* ATTRIBUTE_UNUSED */
 
 /* Before GCC 3.4, the C++ frontend couldn't parse attributes placed after the