RFA: partially hookize *_TYPE_SIZE
diff mbox

Message ID 20101129222332.knwuu1g4gk8c8c4w-nzlynne@webmail.spamcop.net
State New
Headers show

Commit Message

Joern Rennecke Nov. 30, 2010, 3:23 a.m. UTC
This hookizes *_TYPE_SIZE for frontends and tree optimizers, as discussed
in PR46677.

I've called the hook definitions using the old macros legacy_*_type_size
so that they won't need to be renamed in the transition when we get a
new default definition for more hook-centric port programming, but some
ports still use the old style.
The exception to that is default_ada_long_type_size, because without
ADA_LONG_TYPE_SIZE defined, it will already return
targetm.integer_type_size (itk_long), which is believed to be a sensible
default.
integer_type_kind is now used in target.h, which is used by some files
which do not include tree.h, e.g. bt-load.h .  Hence I hoved that enum
into coretypes.h .

There were more places than anticipated where the _TYPE_SIZE macros
could not be readily replaced with a TYPE_PRECISION:
- Anywhere where the value might be used before initialization of
   the frontend types, or during them.  I reckoned this should include
   all of ada/gcc-interface/targtyps.c, because that is an abstraction
   layer with no particular stated time when it will be used - or not be
   used.
- Where frontend types and C types might be different, and the point is
   to refer to the C types.
- Optimizers exploit that "int" in C is supposed to be something reasonably
   fast.  It would be desirable to have a better way to tell such types,
   but at the moment we don't, and trying to solve all problems at once will
   not get us anywhere.

ADA_LONG_TYPE_SIZE could in principle fitted between itk_long and
tik_long_long, put putting this type there might confuse the C-family front
ends, so I made it a separate hook.
Regarding WCHAR_TYPE_SIZE, it appears this is used to define a constant
in ttypes.ads.  We can use GET_IDENTIFIER to find the type from WCHAR_TYPE
only after all the C types have been initialized, so I don't think that
would be safe in this context.  So i made this into a separate hook, too.
A possible alternative would be to change WCHAR_TYPE to have an
integer_type_kind value, but that would be quite a big change in itself;
we could always retrofit that as a cleanup if we want to.

bootstrapped & regtested on i686-pc-linux-gnu

cross-tested for:
alpha-linux-gnu hppa-linux-gnu mips-elf sh-elf arc-elf ia64-elf  
mmix-knuth-mmixware sparc-elf arm-eabi iq2000-elf mn10300-elf spu-elf  
avr-elf lm32-elf moxie-elf v850-elf bfin-elf m32c-elf pdp11-aout  
vax-linux-gnu cris-elf m32r-elf picochip-elf xstormy16-elf crx-elf  
m68hc11-elf ppc-elf xtensa-elf fr30-elf m68k-elf rx-elf frv-elf  
mcore-elf s390-linux-gnu h8300-elf mep-elf score-elf microblaze-elf

ada bootstrapped & regtested on x86_64-linux-gnu
2010-11-29  Joern Rennecke  <amylaar@spamcop.net>

	PR other/46677
gcc:
	* targhooks.c (legacy_bool_type_size): New function.
	(legacy_wchar_type_size, legacy_integer_type_size): Likewise.
	(default_ada_long_type_size, legacy_float_type_size): Likewise.
	* targhooks.h (legacy_bool_type_size): Declare.
	(legacy_wchar_type_size, legacy_integer_type_size): Likewise.
	(default_ada_long_type_size, legacy_float_type_size): Likewise.
	* target.def (bool_type_size, wchar_type_size: New hooks.
	(integer_type_size, ada_long_type_size, float_type_size): Likewise.
	* tree.h (enum integer_type_kind): Move from here...
	* coretypes.h ... to here.
	* target.h (enum float_type_kind): New enum.
	* tree-ssa-loop-ivopts.c (add_standard_iv_candidates):
	Use targetm.integer_type_size.  Loop over integer kinds.
	* tree-data-ref.c: Include target.h
	(estimated_loop_iterations_tree): Use targetm.integer_type_size.
	* Makefile.in (tree-data-ref.o): Depend on $(TARGET_H) .
gcc/c-family.c:
	* c-common.c (c_common_to_target_charset):
	Use TYPE_PRECISION (char_type_node).
gcc/java:
	* decl.c (java_init_decl_processing): Use targetm.integer_type_size.
	* expr.c (expand_java_return): Likewise.
gcc/ada:
	* gcc-interface/decl.c (gnat_to_gnu_entity):
	Use targetm.float_type_size and targetm.integer_type_size.
	(make_type_from_size): Use targetm.integer_type_size.
	* gcc-interface/targtyps.c: Include target.h .
	[!ADA_LONG_TYPE_SIZE] (ADA_LONG_TYPE_SIZE): Don't define.
	[!WIDEST_HARDWARE_FP_SIZE] (LONG_DOUBLE_TYPE_SIZE): Likewise.
	(get_target_char_size): Use targetm.integer_type_size.
	(get_target_wchar_t_size): Use targetm.integer_type_size and
	targetm.wchar_type_size.
	(get_target_short_size): Use targetm.integer_type_size.
	(get_target_int_size, get_target_long_size): Likewise.
	(get_target_long_long_size): Likewise.
	(get_target_float_size): Use targetm.float_type_size.
	(get_target_double_size, get_target_long_double_size): Likewise.
	(get_target_maximum_default_alignment): Use targetm.integer_type_size.
	* gcc-interface/trans.c: Include target.h .
	(gigi): Use targetm.float_type_size.
	(build_binary_op_trapv): Use targetm.integer_type_size.
	* gcc-interface/Make-lang.in (ada/targtyps.o): Depend on $(TARGET_H).
	(ada/trans.o): Likewise.
gcc/fortran:
	* trans-types.c (gfc_init_kinds): Use targetm.integer_type_size.
	(gfc_build_int_type): Likewise.
	(gfc_build_uint_type): Use TYPE_PRECISION on the type nodes checked.
	(gfc_build_real_type): Use targetm.float_type_size.
	(gfc_build_logical_type): Use targetm.bool_type_size.
	[0] (c_size_t_size): Delete.
	* f95-lang.c [!CHAR_TYPE_SIZE] (CHAR_TYPE_SIZE): Don't define.
	[!INT_TYPE_SIZE] (INT_TYPE_SIZE): Likewise.
	* trans-intrinsic.c (build_round_expr): Use TYPE_PRECISION
	on *_integer_type_node to find out these type's sizes.
	(gfc_conv_intrinsic_leadz, gfc_conv_intrinsic_trailz): Likewise.
	(gfc_conv_intrinsic_popcnt_poppar): Likewise.

Comments

Joseph Myers Nov. 30, 2010, 11:33 a.m. UTC | #1
On Mon, 29 Nov 2010, Joern Rennecke wrote:

> This hookizes *_TYPE_SIZE for frontends and tree optimizers, as discussed
> in PR46677.

This is partial in the sense that not all uses are converted (note that 
I'm counting uses in headers such as config/glibc-stdint.h as well, and 
uses in target code including libgcc/config/libbid/bid_gcc_intrinsics.h) 
and so it is not possible to start converting targets to define the hooks 
instead of the macros.  (A comment to make things clear for anyone who 
might want to start the actual conversions of targets, not an objection.)

(Also partial in that it doesn't have hooks for decimal floating-point 
types or fixed-point types, but that's certainly not a problem.  For 
decimal floating-point types there are no non-default definitions of the 
macros and they are used only in one place so that conversion will be 
pretty trivial.)

I'm not convinced it makes sense to be partial in this way for 
BOOL_TYPE_SIZE (a single non-default definition) and ADA_LONG_TYPE_SIZE 
(two non-default definitions) rather than just doing the complete 
conversions for those macros and poisoning them.

> Regarding WCHAR_TYPE_SIZE, it appears this is used to define a constant
> in ttypes.ads.  We can use GET_IDENTIFIER to find the type from WCHAR_TYPE
> only after all the C types have been initialized, so I don't think that
> would be safe in this context.  So i made this into a separate hook, too.

I already said this should not be a hook.  The Fortran front end already 
has support for decoding strings in the form that appear in macros such as 
WCHAR_TYPE: get_typenode_from_name.  You could easily make that return an 
integer_type_kind instead and move it out of the Fortran front end.

> A possible alternative would be to change WCHAR_TYPE to have an
> integer_type_kind value, but that would be quite a big change in itself;

I think that should be separate, a preliminary step before converting all 
the *_TYPE macros to hooks.  First they should be changed to have 
integer_type_kind values, then they should be changed to hooks taking 
suitable enum values and returning suitable enum values.  Maybe one hook 
for size_t and ptrdiff_t, one for wchar_t and wint_t, one for sig_atomic_t 
and one for the stdint.h types.

> +int
> +legacy_integer_type_size (enum integer_type_kind kind)
> +{
> +  switch (kind)
> +    {
> +    case itk_char: case itk_signed_char: case itk_unsigned_char:
> +      return CHAR_TYPE_SIZE;
> +    case itk_short: case itk_unsigned_short:
> +      return SHORT_TYPE_SIZE;
> +    case itk_int: case itk_unsigned_int:
> +      return INT_TYPE_SIZE;
> +    case itk_long: case itk_unsigned_long:
> +      return LONG_TYPE_SIZE;
> +    case itk_long_long: case itk_unsigned_long_long:
> +      return LONG_LONG_TYPE_SIZE;
> +    case itk_int128: case itk_unsigned_int128:
> +      return 128;

I think we should define the hook interface so that only one argument is 
valid for each present macro.  Thus there should be no possibility for 
targets to give char and signed char different sizes, for example, because 
only itk_char should ever be passed for all the character types.
Richard Biener Nov. 30, 2010, 11:41 a.m. UTC | #2
On Tue, Nov 30, 2010 at 12:33 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Mon, 29 Nov 2010, Joern Rennecke wrote:
>
>> This hookizes *_TYPE_SIZE for frontends and tree optimizers, as discussed
>> in PR46677.
>
> This is partial in the sense that not all uses are converted (note that
> I'm counting uses in headers such as config/glibc-stdint.h as well, and
> uses in target code including libgcc/config/libbid/bid_gcc_intrinsics.h)
> and so it is not possible to start converting targets to define the hooks
> instead of the macros.  (A comment to make things clear for anyone who
> might want to start the actual conversions of targets, not an objection.)
>
> (Also partial in that it doesn't have hooks for decimal floating-point
> types or fixed-point types, but that's certainly not a problem.  For
> decimal floating-point types there are no non-default definitions of the
> macros and they are used only in one place so that conversion will be
> pretty trivial.)
>
> I'm not convinced it makes sense to be partial in this way for
> BOOL_TYPE_SIZE (a single non-default definition) and ADA_LONG_TYPE_SIZE
> (two non-default definitions) rather than just doing the complete
> conversions for those macros and poisoning them.

Btw, I think these partial conversions are not appropriate for stage3
and if accepted for stage1 you should commit yourself to do a
transition that at least allows converting targets (thus, I don't like
your incremental patches at all).

Richard.
Joern Rennecke Nov. 30, 2010, 7:02 p.m. UTC | #3
Quoting "Joseph S. Myers" <joseph@codesourcery.com>:

> I'm not convinced it makes sense to be partial in this way for
> BOOL_TYPE_SIZE (a single non-default definition) and ADA_LONG_TYPE_SIZE
> (two non-default definitions) rather than just doing the complete
> conversions for those macros and poisoning them.

My motivation for doing partial conversions is not just saving on target
port changes - although that is useful at a stage when there is no clear
consensus yet what the target ports are supposed to look like - but also
to break the dependency between untying the front-ends / tree optimizers
and hookizing frequently used macros in middle-end and rtl optimizers,
which has the potential to make the compiler significantly slower.
I see that this is not actually an issue with BOOL_TYPE_SIZE /  
ADA_LONG_TYPE_SIZE.

OTOH ADA_LONG_TYPE_SIZE is just a way of telling that on some targets,
Ada's "long" type corresponds to C's "long long", so if we go with
using integer_type_kind macros/hooks as discussed below, it seems to be
more natural to replace ADA_LONG_TYPE_SIZE with an ada_long_type hook  
that yeuilds an integer_type_kind value.
yielding ADA_LONG_TYPE macro first, and then

So if we have a consensus that these should be
made functional hooks returning int, defined as
TARGET_BOOL_TYPE_SIZE / TARGET_ADA_LONG_TYPE_SIZE , and used as
targetm.bool_type_size () / targetm.ada_long_type_size () ,
I can prepare a patch to fully hookize them.

>> Regarding WCHAR_TYPE_SIZE, it appears this is used to define a constant
>> in ttypes.ads.  We can use GET_IDENTIFIER to find the type from WCHAR_TYPE
>> only after all the C types have been initialized, so I don't think that
>> would be safe in this context.  So i made this into a separate hook, too.
>
> I already said this should not be a hook.  The Fortran front end already
> has support for decoding strings in the form that appear in macros such as
> WCHAR_TYPE: get_typenode_from_name.  You could easily make that return an
> integer_type_kind instead and move it out of the Fortran front end.

That get_typenode_from_name seems to be a hack to make the best out of a bad
situation - having information to select one element from a small fixed set
encoded in string form.

>> A possible alternative would be to change WCHAR_TYPE to have an
>> integer_type_kind value, but that would be quite a big change in itself;
>
> I think that should be separate, a preliminary step before converting all
> the *_TYPE macros to hooks.  First they should be changed to have
> integer_type_kind values, then they should be changed to hooks taking
> suitable enum values and returning suitable enum values.  Maybe one hook
> for size_t and ptrdiff_t, one for wchar_t and wint_t, one for sig_atomic_t
> and one for the stdint.h types.

Sounds more like a plan.
The optimizers could also make use of int_fast*_t .

So something like (with GPL and GFDL license):

DEFHOOK
(size_type,
"If @var{diff_type} is false, return the @code{integer_type_kind} value for\
  @code{size_type}; if @var{diff_type} is true, return the\
  @code{integer_type_kind} value for @code{ptrdiff_t}.",
  integer_type_kind, (bool diff_type),
  default_size_type)

DEFHOOK
(wchar_type,
  "If @var{int_type} is false, return the @code{integer_type_kind} value for\
  @code{wchar_t}; if @var{int_type} is true, return the  
@code{integer_type_kind}\ value for @code{wint_t}.",
  integer_type_kind, (bool int_type),
  default_wchar_type)

DEFHOOK
(sig_atomic_type,
  "Return the @code{integer_type_kind} value for @code{sig_atomic_t}.",
  integer_type_kind, (void),
  default_sig_atomic_type)

/* In target.h:
    enum stdint_type_purpose
    {
      stdint_tp_exact, stdint_tp_least, stdint_tp_fast,
      stdint_tp_max, stdint_tp_pointer
    };  */
DEFHOOK
(stdint_type,
"Return the @code{integer_type_kind} value for a stdint.h type. \
  @var{byte_power} is an integer int the range 0..3 so that 8 << @{byte_power}\
  is the number of bits requested for the type. \
  If @var{unsigned_p} is true, an unsigned type is requested, otherwise a\
  signed one. \
  @var{purpose} specifies if the size is to be exact, the smallest fitting\
  size is wanted, the fastest, the largest, or one to hold a void pointer. \
  If @var{purpose} is @code{stdint_tp_max} or @code{stdint_tp_pointer},\
  the caller should specify var@{byte_power} as 0,\
  and the callee should use gcc_assert to verify that it is. \
  If the type does not exist, @code{itk_none} is returned.",
  integer_type_kind,
  (int byte_power, bool unsigned_p, stdint_type_purpose purpose),
  default_stdint_type)


[integer_type_size hook]
> I think we should define the hook interface so that only one argument is
> valid for each present macro.  Thus there should be no possibility for
> targets to give char and signed char different sizes, for example, because
> only itk_char should ever be passed for all the character types.

However, when staying with enum integer_size_kind, that would make it
impossible to loop over the enum values, as seen in my patch for
tree-ssa-loop-ivopts.c:add_standard_iv_candidates.
So could I use a separate enum, like enum integer_size_kind with isk_* values?
However, then there would have to be a way to translate integer_type_kind
to integer_size_kind, e.g. a const array used as a translation table.

Another approach would be to handle the full range of enum integer_kind_value,
and have some ENABLE_CHECKING code when the compiler starts, and after options
are changed, to verify that the values are consistent.
Joseph Myers Nov. 30, 2010, 9:24 p.m. UTC | #4
On Tue, 30 Nov 2010, Joern Rennecke wrote:

> OTOH ADA_LONG_TYPE_SIZE is just a way of telling that on some targets,
> Ada's "long" type corresponds to C's "long long", so if we go with
> using integer_type_kind macros/hooks as discussed below, it seems to be
> more natural to replace ADA_LONG_TYPE_SIZE with an ada_long_type hook that
> yeuilds an integer_type_kind value.
> yielding ADA_LONG_TYPE macro first, and then

No, I think returning sizes (as int) is right for these hooks.

> > > Regarding WCHAR_TYPE_SIZE, it appears this is used to define a constant
> > > in ttypes.ads.  We can use GET_IDENTIFIER to find the type from WCHAR_TYPE
> > > only after all the C types have been initialized, so I don't think that
> > > would be safe in this context.  So i made this into a separate hook, too.
> > 
> > I already said this should not be a hook.  The Fortran front end already
> > has support for decoding strings in the form that appear in macros such as
> > WCHAR_TYPE: get_typenode_from_name.  You could easily make that return an
> > integer_type_kind instead and move it out of the Fortran front end.
> 
> That get_typenode_from_name seems to be a hack to make the best out of a bad
> situation - having information to select one element from a small fixed set
> encoded in string form.

Correct.  But I think reusing that machinery would be better than adding a 
new target hook for something that should logically use the information in 
WCHAR_TYPE rather than its own hook.

> The optimizers could also make use of int_fast*_t .

Sounds like a bad idea to me.  In practice these types reflect an 
arbitrary decision by library maintainers that is then used across all 
target architectures for a given library, and the optimizers should use 
information that actually relates to the architecture rather than the 
library.

> So something like (with GPL and GFDL license):
> 
> DEFHOOK
> (size_type,
> "If @var{diff_type} is false, return the @code{integer_type_kind} value for\
> @code{size_type}; if @var{diff_type} is true, return the\
> @code{integer_type_kind} value for @code{ptrdiff_t}.",
> integer_type_kind, (bool diff_type),
> default_size_type)
> 
> DEFHOOK
> (wchar_type,
> "If @var{int_type} is false, return the @code{integer_type_kind} value for\
> @code{wchar_t}; if @var{int_type} is true, return the
> @code{integer_type_kind}\ value for @code{wint_t}.",
> integer_type_kind, (bool int_type),
> default_wchar_type)

I think it's better just to pass enum tree_index values to these hooks, so 
it's immediately obvious from a call what it means rather than needing to 
know which case is "true" and which is "false".

> /* In target.h:
>   enum stdint_type_purpose
>   {
>     stdint_tp_exact, stdint_tp_least, stdint_tp_fast,
>     stdint_tp_max, stdint_tp_pointer
>   };  */
> DEFHOOK
> (stdint_type,
> "Return the @code{integer_type_kind} value for a stdint.h type. \
> @var{byte_power} is an integer int the range 0..3 so that 8 << @{byte_power}\
> is the number of bits requested for the type. \
> If @var{unsigned_p} is true, an unsigned type is requested, otherwise a\
> signed one. \
> @var{purpose} specifies if the size is to be exact, the smallest fitting\
> size is wanted, the fastest, the largest, or one to hold a void pointer. \
> If @var{purpose} is @code{stdint_tp_max} or @code{stdint_tp_pointer},\
> the caller should specify var@{byte_power} as 0,\
> and the callee should use gcc_assert to verify that it is. \
> If the type does not exist, @code{itk_none} is returned.",
> integer_type_kind,
> (int byte_power, bool unsigned_p, stdint_type_purpose purpose),
> default_stdint_type)

This is massively over-complicated.  It would make sense if the types used 
by libraries actually reflected some logical scheme, but they don't, so 
functions such as glibc_stdint_type (implementing the logic in 
glibc-stdint.h) or newlib_stdint_type (newlib-stdint.h) or 
solaris_stdint_type will most naturally use switch statements handling 
each type separately.  And so simply defining a new enum for all the 
stdint.h types, and passing it to the hook, seems best.

> [integer_type_size hook]
> > I think we should define the hook interface so that only one argument is
> > valid for each present macro.  Thus there should be no possibility for
> > targets to give char and signed char different sizes, for example, because
> > only itk_char should ever be passed for all the character types.
> 
> However, when staying with enum integer_size_kind, that would make it
> impossible to loop over the enum values, as seen in my patch for
> tree-ssa-loop-ivopts.c:add_standard_iv_candidates.

Optimizers should not be looping over these values; the type sizes should 
just be a front-end / ABI matter.  The particular type sizes chosen for 
standard C types should be irrelevant to the optimizers.  The optimizers 
may have a use for asking what sizes are available on a target, or 
available and reasonably efficient.  But so far as this isn't already 
possible by looping over machine modes, any hook for that purpose should 
be clearly separate from the hooks that define the C ABI.  (And in Stage 3 
changing this sort of optimizer logic seems rather risky; hookization 
patches at this stage should be essentially janitorial cleanups that 
clearly do not change semantics, such that if they break anything the 
breakage is expected to be obvious rather than subtle.  So keeping the 
optimizers using target int and filing a bug for that inappropriate use of 
ABI-related types seems better than introducing some new logic.)
Joern Rennecke Nov. 30, 2010, 9:44 p.m. UTC | #5
Quoting "Joseph S. Myers" <joseph@codesourcery.com>:

> On Tue, 30 Nov 2010, Joern Rennecke wrote:

>> DEFHOOK
>> (size_type,
>> "If @var{diff_type} is false, return the @code{integer_type_kind} value for\
>> @code{size_type}; if @var{diff_type} is true, return the\
>> @code{integer_type_kind} value for @code{ptrdiff_t}.",
>> integer_type_kind, (bool diff_type),
>> default_size_type)
>>
>> DEFHOOK
>> (wchar_type,
>> "If @var{int_type} is false, return the @code{integer_type_kind} value for\
>> @code{wchar_t}; if @var{int_type} is true, return the
>> @code{integer_type_kind}\ value for @code{wint_t}.",
>> integer_type_kind, (bool int_type),
>> default_wchar_type)
>
> I think it's better just to pass enum tree_index values to these hooks, so
> it's immediately obvious from a call what it means rather than needing to
> know which case is "true" and which is "false".

I see your point.  The name of the parameter is not evident at the call site.
I suppose the best way to handle the enum tree_index dependency
(not all users of target.h use tree.h) is to declare these hooks to take an
int argument.
Joseph Myers Nov. 30, 2010, 9:50 p.m. UTC | #6
On Tue, 30 Nov 2010, Joern Rennecke wrote:

> I see your point.  The name of the parameter is not evident at the call site.
> I suppose the best way to handle the enum tree_index dependency
> (not all users of target.h use tree.h) is to declare these hooks to take an
> int argument.

You could alternatively create separate enums for each hook for greater 
type safety.
Joern Rennecke Nov. 30, 2010, 10:34 p.m. UTC | #7
Quoting "Joseph S. Myers" <joseph@codesourcery.com>:

> On Tue, 30 Nov 2010, Joern Rennecke wrote:
>
>> I see your point.  The name of the parameter is not evident at the   
>> call site.
>> I suppose the best way to handle the enum tree_index dependency
>> (not all users of target.h use tree.h) is to declare these hooks to take an
>> int argument.
>
> You could alternatively create separate enums for each hook for greater
> type safety.

Yes.  Unfortunately, the enum literals are prone to name clash, and it
doesn't get simpler to avoid these when lots of random different enums
use different naming schemes.
Using bool seemed like an easy way out, till you pointed out the flaw
with that...

So I suppose we could have something like this in target.h :

/* enums to describe types in target hooks.
    integer_type_kind is defined in coretypes.h  */
enum th_wchar_type
{
   th_wt_wchar_t, th_wt_wint_t
};

enum th_size_type
{
   th_st_size_type, th_st_ptrdiff_t
};

enum th_float_type
{
   th_ft_float, th_ft_double, th_ft_widest_hard_fp, th_ft_long_double
};

enum th_stdint
{
   th_si_int8_t,
...
};
Joseph Myers Nov. 30, 2010, 11:12 p.m. UTC | #8
On Tue, 30 Nov 2010, Joern Rennecke wrote:

> So I suppose we could have something like this in target.h :
> 
> /* enums to describe types in target hooks.
>   integer_type_kind is defined in coretypes.h  */
> enum th_wchar_type
[...]

Seems reasonable to me.

Patch
diff mbox

Index: targhooks.c
===================================================================
--- targhooks.c	(revision 167230)
+++ targhooks.c	(working copy)
@@ -438,6 +438,69 @@  targhook_float_words_big_endian (void)
   return !!FLOAT_WORDS_BIG_ENDIAN;
 }
 
+int
+legacy_bool_type_size (void)
+{
+  return BOOL_TYPE_SIZE;
+}
+
+int
+legacy_wchar_type_size (void)
+{
+  return WCHAR_TYPE_SIZE;
+}
+
+int
+legacy_integer_type_size (enum integer_type_kind kind)
+{
+  switch (kind)
+    {
+    case itk_char: case itk_signed_char: case itk_unsigned_char:
+      return CHAR_TYPE_SIZE;
+    case itk_short: case itk_unsigned_short:
+      return SHORT_TYPE_SIZE;
+    case itk_int: case itk_unsigned_int:
+      return INT_TYPE_SIZE;
+    case itk_long: case itk_unsigned_long:
+      return LONG_TYPE_SIZE;
+    case itk_long_long: case itk_unsigned_long_long:
+      return LONG_LONG_TYPE_SIZE;
+    case itk_int128: case itk_unsigned_int128:
+      return 128;
+    case itk_none: default:
+      gcc_unreachable ();
+    }
+}
+
+int
+default_ada_long_type_size (void)
+{
+#ifdef ADA_LONG_TYPE_SIZE
+  return ADA_LONG_TYPE_SIZE;
+#else
+  /* If we don't have a specific size for Ada's equivalent of `long', use that
+     of C.  */
+  return targetm.integer_type_size (itk_long);
+#endif
+}
+
+int
+legacy_float_type_size (enum float_type_kind kind)
+{
+  switch (kind)
+    {
+    case ftk_float: return FLOAT_TYPE_SIZE;
+    case ftk_double: return DOUBLE_TYPE_SIZE;
+    case ftk_widest_hard_fp:
+#ifdef WIDEST_HARDWARE_FP_SIZE
+      return WIDEST_HARDWARE_FP_SIZE;
+#endif /* WIDEST_HARDWARE_FP_SIZE */
+      /* Fall through.  */
+    case ftk_long_double: return LONG_DOUBLE_TYPE_SIZE;
+    default: gcc_unreachable ();
+    }
+}
+
 /* True if the target supports decimal floating point.  */
 
 bool
Index: targhooks.h
===================================================================
--- targhooks.h	(revision 167230)
+++ targhooks.h	(working copy)
@@ -71,6 +71,11 @@  extern bool default_scalar_mode_supporte
 extern bool targhook_words_big_endian (void);
 extern bool targhook_float_words_big_endian (void);
 extern bool default_decimal_float_supported_p (void);
+extern int legacy_bool_type_size (void);
+extern int legacy_wchar_type_size (void);
+extern int legacy_integer_type_size (enum integer_type_kind);
+extern int default_ada_long_type_size (void);
+extern int legacy_float_type_size (enum float_type_kind);
 extern bool default_fixed_point_supported_p (void);
 
 extern const char * default_invalid_within_doloop (const_rtx);
Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 167230)
+++ c-family/c-common.c	(working copy)
@@ -8407,8 +8407,11 @@  c_common_to_target_charset (HOST_WIDE_IN
   uc = cpp_host_to_exec_charset (parse_in, uc);
 
   if (flag_signed_char)
-    return ((HOST_WIDE_INT)uc) << (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE)
-			       >> (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE);
+    {
+      unsigned shift = HOST_BITS_PER_WIDE_INT - TYPE_PRECISION (char_type_node);
+
+      return ((HOST_WIDE_INT)uc) << shift >> shift;
+    }
   else
     return uc;
 }
Index: java/decl.c
===================================================================
--- java/decl.c	(revision 167230)
+++ java/decl.c	(working copy)
@@ -610,7 +610,8 @@  java_init_decl_processing (void)
   set_sizetype (size_type_node);
 
   /* Define these next since types below may used them.  */
-  integer_type_node = java_type_for_size (INT_TYPE_SIZE, 0);
+  integer_type_node
+    = java_type_for_size (targetm.integer_type_size (itk_int), 0);
   integer_zero_node = build_int_cst (NULL_TREE, 0);
   integer_one_node = build_int_cst (NULL_TREE, 1);
   integer_two_node = build_int_cst (NULL_TREE, 2);
Index: java/expr.c
===================================================================
--- java/expr.c	(revision 167230)
+++ java/expr.c	(working copy)
@@ -1276,9 +1276,9 @@  expand_java_return (tree type)
 
       /* Handle the situation where the native integer type is smaller
 	 than the JVM integer. It can happen for many cross compilers.
-	 The whole if expression just goes away if INT_TYPE_SIZE < 32
-	 is false. */
-      if (INT_TYPE_SIZE < 32
+	 The whole if expression just goes away if
+	 targetm.integer_type_size (itk_int) < 32 is false. */
+      if (targetm.integer_type_size (itk_int) < 32
 	  && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (res)))
 	      < GET_MODE_SIZE (TYPE_MODE (type))))
 	retval = build1(NOP_EXPR, TREE_TYPE(res), retval);
Index: target.def
===================================================================
--- target.def	(revision 167230)
+++ target.def	(working copy)
@@ -1178,6 +1178,38 @@  HOOK_VECTOR_END (vectorize)
  bool, (void),
  targhook_float_words_big_endian)
 
+/* Wrappers for type sizes.  */
+
+DEFHOOK_UNDOC
+(bool_type_size,
+ "",
+ int, (void),
+ legacy_bool_type_size)
+
+DEFHOOK_UNDOC
+(wchar_type_size,
+ "",
+ int, (void),
+ legacy_wchar_type_size)
+
+DEFHOOK_UNDOC
+(integer_type_size,
+ "",
+ int, (enum integer_type_kind),
+ legacy_integer_type_size)
+
+DEFHOOK_UNDOC
+(ada_long_type_size,
+ "",
+ int, (void),
+ default_ada_long_type_size)
+
+DEFHOOK_UNDOC
+(float_type_size,
+ "",
+ int, (enum float_type_kind),
+ legacy_float_type_size)
+
 /* True if the target supports decimal floating point.  */
 DEFHOOK
 (decimal_float_supported_p,
Index: tree.h
===================================================================
--- tree.h	(revision 167230)
+++ tree.h	(working copy)
@@ -3876,30 +3876,6 @@  #define MAIN_NAME_P(NODE) \
 #define current_target_pragma		global_trees[TI_CURRENT_TARGET_PRAGMA]
 #define current_optimize_pragma		global_trees[TI_CURRENT_OPTIMIZE_PRAGMA]
 
-/* An enumeration of the standard C integer types.  These must be
-   ordered so that shorter types appear before longer ones, and so
-   that signed types appear before unsigned ones, for the correct
-   functioning of interpret_integer() in c-lex.c.  */
-enum integer_type_kind
-{
-  itk_char,
-  itk_signed_char,
-  itk_unsigned_char,
-  itk_short,
-  itk_unsigned_short,
-  itk_int,
-  itk_unsigned_int,
-  itk_long,
-  itk_unsigned_long,
-  itk_long_long,
-  itk_unsigned_long_long,
-  itk_int128,
-  itk_unsigned_int128,
-  itk_none
-};
-
-typedef enum integer_type_kind integer_type_kind;
-
 /* The standard C integer types.  Use integer_type_kind to index into
    this array.  */
 extern GTY(()) tree integer_types[itk_none];
Index: target.h
===================================================================
--- target.h	(revision 167230)
+++ target.h	(working copy)
@@ -163,6 +163,14 @@  struct default_options
   int value;
 };
 
+/* enum integer_type_kind is defined in coretypes.h .  */
+
+/* Flaoting point types.  */
+enum float_type_kind
+{
+  ftk_float, ftk_double, ftk_widest_hard_fp, ftk_long_double
+};
+
 /* The target structure.  This holds all the backend hooks.  */
 #define DEFHOOKPOD(NAME, DOC, TYPE, INIT) TYPE NAME;
 #define DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT) TYPE (* NAME) PARAMS;
Index: tree-ssa-loop-ivopts.c
===================================================================
--- tree-ssa-loop-ivopts.c	(revision 167230)
+++ tree-ssa-loop-ivopts.c	(working copy)
@@ -2403,11 +2403,24 @@  add_standard_iv_candidates_for_size (str
 static void
 add_standard_iv_candidates (struct ivopts_data *data)
 {
-  add_standard_iv_candidates_for_size (data, INT_TYPE_SIZE);
+  int i;
+  unsigned last_size;
 
-  /* The same for a double-integer type if it is still fast enough.  */
-  if (BITS_PER_WORD >= INT_TYPE_SIZE * 2)
-    add_standard_iv_candidates_for_size (data, INT_TYPE_SIZE * 2);
+  /* We assume here that types corresponding to itk_int, or larger ones that
+     fit into a word, are reasonably fast.
+     FIXME: there should be a better way to tell useful sizes.
+     Some targets might have fast integers types of smaller and/or larger
+     sizes than this.  */
+  for (last_size = 0, i = itk_int; i != itk_none; i++)
+    {
+      unsigned size = targetm.integer_type_size ((enum integer_type_kind) i);
+
+      if (last_size != 0 && size > BITS_PER_WORD)
+	break;
+      else if (last_size < size)
+	add_standard_iv_candidates_for_size (data, size);
+      last_size = size;
+    }
 }
 
 
Index: ada/gcc-interface/decl.c
===================================================================
--- ada/gcc-interface/decl.c	(revision 167230)
+++ ada/gcc-interface/decl.c	(working copy)
@@ -394,17 +394,18 @@  gnat_to_gnu_entity (Entity_Id gnat_entit
 	  esize = UI_To_Int (Esize (gnat_entity));
 
 	  if (IN (kind, Float_Kind))
-	    max_esize = fp_prec_to_size (LONG_DOUBLE_TYPE_SIZE);
+	    max_esize
+	      = fp_prec_to_size (targetm.float_type_size (ftk_long_double));
 	  else if (IN (kind, Access_Kind))
 	    max_esize = POINTER_SIZE * 2;
 	  else
-	    max_esize = LONG_LONG_TYPE_SIZE;
+	    max_esize = targetm.integer_type_size (itk_long_long);
 
 	  if (esize > max_esize)
 	   esize = max_esize;
 	}
       else
-	esize = LONG_LONG_TYPE_SIZE;
+	esize = targetm.integer_type_size (itk_long_long);
     }
 
   switch (kind)
@@ -7905,7 +7906,7 @@  set_rm_size (Uint uint_size, tree gnu_ty
 static tree
 make_type_from_size (tree type, tree size_tree, bool for_biased)
 {
-  unsigned HOST_WIDE_INT size;
+  unsigned HOST_WIDE_INT size, max;
   bool biased_p;
   tree new_type;
 
@@ -7935,8 +7936,9 @@  make_type_from_size (tree type, tree siz
 	break;
 
       biased_p |= for_biased;
-      if (size > LONG_LONG_TYPE_SIZE)
-	size = LONG_LONG_TYPE_SIZE;
+      max = targetm.integer_type_size (itk_long_long);
+      if (size > max)
+	size = max;
 
       if (TYPE_UNSIGNED (type) || biased_p)
 	new_type = make_unsigned_type (size);
Index: ada/gcc-interface/targtyps.c
===================================================================
--- ada/gcc-interface/targtyps.c	(revision 167230)
+++ ada/gcc-interface/targtyps.c	(working copy)
@@ -31,6 +31,7 @@ 
 #include "tree.h"
 #include "tm.h"
 #include "tm_p.h"
+#include "target.h"
 
 #include "ada.h"
 #include "types.h"
@@ -48,16 +49,6 @@ 
 #include "ada-tree.h"
 #include "gigi.h"
 
-/* If we don't have a specific size for Ada's equivalent of `long', use that
-   of C.  */
-#ifndef ADA_LONG_TYPE_SIZE
-#define ADA_LONG_TYPE_SIZE LONG_TYPE_SIZE
-#endif
-
-#ifndef WIDEST_HARDWARE_FP_SIZE
-#define WIDEST_HARDWARE_FP_SIZE LONG_DOUBLE_TYPE_SIZE
-#endif
-
 /* The following provide a functional interface for the front end Ada code
    to determine the sizes that are used for various C types. */
 
@@ -76,56 +67,57 @@  get_target_bits_per_word (void)
 Pos
 get_target_char_size (void)
 {
-  return CHAR_TYPE_SIZE;
+  return targetm.integer_type_size (itk_char);
 }
 
 Pos
 get_target_wchar_t_size (void)
 {
   /* We never want wide characters less than "short" in Ada.  */
-  return MAX (SHORT_TYPE_SIZE, WCHAR_TYPE_SIZE);
+  return MAX (targetm.integer_type_size (itk_short),
+	      targetm.wchar_type_size ());
 }
 
 Pos
 get_target_short_size (void)
 {
-  return SHORT_TYPE_SIZE;
+  return targetm.integer_type_size (itk_short);
 }
 
 Pos
 get_target_int_size (void)
 {
-  return INT_TYPE_SIZE;
+  return targetm.integer_type_size (itk_int);
 }
 
 Pos
 get_target_long_size (void)
 {
-  return ADA_LONG_TYPE_SIZE;
+  return targetm.ada_long_type_size ();
 }
 
 Pos
 get_target_long_long_size (void)
 {
-  return LONG_LONG_TYPE_SIZE;
+  return targetm.integer_type_size (itk_long_long);
 }
 
 Pos
 get_target_float_size (void)
 {
-  return fp_prec_to_size (FLOAT_TYPE_SIZE);
+  return fp_prec_to_size (targetm.float_type_size (ftk_float));
 }
 
 Pos
 get_target_double_size (void)
 {
-  return fp_prec_to_size (DOUBLE_TYPE_SIZE);
+  return fp_prec_to_size (targetm.float_type_size (ftk_double));
 }
 
 Pos
 get_target_long_double_size (void)
 {
-  return fp_prec_to_size (WIDEST_HARDWARE_FP_SIZE);
+  return fp_prec_to_size (targetm.float_type_size (ftk_widest_hard_fp));
 }
 
 Pos
@@ -166,7 +158,7 @@  get_target_maximum_default_alignment (vo
 #ifdef MALLOC_OBSERVABLE_ALIGNMENT
 #define MALLOC_ALIGNMENT MALLOC_OBSERVABLE_ALIGNMENT
 #else
-#define MALLOC_OBSERVABLE_ALIGNMENT (2 * LONG_TYPE_SIZE)
+#define MALLOC_OBSERVABLE_ALIGNMENT (2 * targetm.integer_type_size (itk_long))
 #define MALLOC_ALIGNMENT \
   MAX (MALLOC_ABI_ALIGNMENT, MALLOC_OBSERVABLE_ALIGNMENT)
 #endif
Index: ada/gcc-interface/Make-lang.in
===================================================================
--- ada/gcc-interface/Make-lang.in	(revision 167230)
+++ ada/gcc-interface/Make-lang.in	(working copy)
@@ -1242,11 +1242,11 @@  ada/targtyps.o : ada/gcc-interface/targt
    coretypes.h $(TM_H) $(TM_P_H) $(TREE_H) ada/gcc-interface/ada.h \
    ada/types.h ada/atree.h ada/elists.h ada/namet.h ada/nlists.h \
    ada/snames.h ada/stringt.h ada/uintp.h ada/urealp.h ada/fe.h ada/sinfo.h \
-   ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h
+   ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h $(TARGET_H)
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
 
 ada/trans.o : ada/gcc-interface/trans.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-   $(TM_H) $(TREE_H) $(FLAGS_H) output.h tree-iterator.h  \
+   $(TM_H) $(TREE_H) $(FLAGS_H) output.h tree-iterator.h $(TARGET_H) \
    $(GIMPLE_H) ada/gcc-interface/ada.h ada/adadecode.h ada/types.h \
    ada/atree.h ada/elists.h ada/namet.h ada/nlists.h ada/snames.h \
    ada/stringt.h ada/uintp.h ada/urealp.h ada/fe.h ada/sinfo.h ada/einfo.h \
Index: ada/gcc-interface/trans.c
===================================================================
--- ada/gcc-interface/trans.c	(revision 167230)
+++ ada/gcc-interface/trans.c	(working copy)
@@ -34,6 +34,7 @@ 
 #include "libfuncs.h"	/* For set_stack_check_libfunc.  */
 #include "tree-iterator.h"
 #include "gimple.h"
+#include "target.h"
 
 #include "ada.h"
 #include "adadecode.h"
@@ -557,7 +558,8 @@  gigi (Node_Id gnat_root, int max_gnat_no
       /* In this case, the builtin floating point types are VAX float,
 	 so make up a type for use.  */
       longest_float_type_node = make_node (REAL_TYPE);
-      TYPE_PRECISION (longest_float_type_node) = LONG_DOUBLE_TYPE_SIZE;
+      TYPE_PRECISION (longest_float_type_node)
+	= targetm.float_type_size (ftk_long_double);
       layout_type (longest_float_type_node);
       record_builtin_type ("longest float type", longest_float_type_node);
     }
@@ -6789,7 +6791,8 @@  build_binary_op_trapv (enum tree_code co
 
       else if (needed_precision <= BITS_PER_WORD
 	       || (code == MULT_EXPR
-		   && needed_precision <= LONG_LONG_TYPE_SIZE))
+		   && (needed_precision
+		       <= targetm.integer_type_size (itk_long_long))))
 	{
 	  tree wide_type = gnat_type_for_size (needed_precision, 0);
 
Index: fortran/trans-types.c
===================================================================
--- fortran/trans-types.c	(revision 167230)
+++ fortran/trans-types.c	(working copy)
@@ -568,7 +568,7 @@  gfc_init_kinds (void)
   /* Choose the integer kind the same size as "void*" for our index kind.  */
   gfc_index_integer_kind = POINTER_SIZE / 8;
   /* Pick a kind the same size as the C "int" type.  */
-  gfc_c_int_kind = INT_TYPE_SIZE / 8;
+  gfc_c_int_kind = targetm.integer_type_size (itk_int) / 8;
 
   /* initialize the C interoperable kinds  */
   init_c_interop_kinds();
@@ -671,15 +671,15 @@  gfc_build_int_type (gfc_integer_info *in
 {
   int mode_precision = info->bit_size;
 
-  if (mode_precision == CHAR_TYPE_SIZE)
+  if (mode_precision == targetm.integer_type_size (itk_char))
     info->c_char = 1;
-  if (mode_precision == SHORT_TYPE_SIZE)
+  if (mode_precision == targetm.integer_type_size (itk_short))
     info->c_short = 1;
-  if (mode_precision == INT_TYPE_SIZE)
+  if (mode_precision == targetm.integer_type_size (itk_int))
     info->c_int = 1;
-  if (mode_precision == LONG_TYPE_SIZE)
+  if (mode_precision == targetm.integer_type_size (itk_long))
     info->c_long = 1;
-  if (mode_precision == LONG_LONG_TYPE_SIZE)
+  if (mode_precision == targetm.integer_type_size (itk_long_long))
     info->c_long_long = 1;
 
   if (TYPE_PRECISION (intQI_type_node) == mode_precision)
@@ -699,15 +699,15 @@  gfc_build_int_type (gfc_integer_info *in
 tree
 gfc_build_uint_type (int size)
 {
-  if (size == CHAR_TYPE_SIZE)
+  if (size == TYPE_PRECISION (unsigned_char_type_node))
     return unsigned_char_type_node;
-  if (size == SHORT_TYPE_SIZE)
+  if (size == TYPE_PRECISION (short_unsigned_type_node))
     return short_unsigned_type_node;
-  if (size == INT_TYPE_SIZE)
+  if (size == TYPE_PRECISION (unsigned_type_node))
     return unsigned_type_node;
-  if (size == LONG_TYPE_SIZE)
+  if (size == TYPE_PRECISION (long_unsigned_type_node))
     return long_unsigned_type_node;
-  if (size == LONG_LONG_TYPE_SIZE)
+  if (size == TYPE_PRECISION (long_long_unsigned_type_node))
     return long_long_unsigned_type_node;
 
   return make_unsigned_type (size);
@@ -720,13 +720,14 @@  gfc_build_real_type (gfc_real_info *info
   int mode_precision = info->mode_precision;
   tree new_type;
 
-  if (mode_precision == FLOAT_TYPE_SIZE)
+  if (mode_precision == targetm.float_type_size (ftk_float))
     info->c_float = 1;
-  if (mode_precision == DOUBLE_TYPE_SIZE)
+  if (mode_precision == targetm.float_type_size (ftk_double))
     info->c_double = 1;
-  if (mode_precision == LONG_DOUBLE_TYPE_SIZE)
+  if (mode_precision == targetm.float_type_size (ftk_long_double))
     info->c_long_double = 1;
-  if (mode_precision != LONG_DOUBLE_TYPE_SIZE && mode_precision == 128)
+  if (mode_precision != targetm.float_type_size (ftk_long_double)
+      && mode_precision == 128)
     {
       info->c_float128 = 1;
       gfc_real16_is_float128 = true;
@@ -771,7 +772,7 @@  gfc_build_logical_type (gfc_logical_info
   int bit_size = info->bit_size;
   tree new_type;
 
-  if (bit_size == BOOL_TYPE_SIZE)
+  if (bit_size == targetm.bool_type_size ())
     {
       info->c_bool = 1;
       return boolean_type_node;
@@ -785,27 +786,6 @@  gfc_build_logical_type (gfc_logical_info
   return new_type;
 }
 
-
-#if 0
-/* Return the bit size of the C "size_t".  */
-
-static unsigned int
-c_size_t_size (void)
-{
-#ifdef SIZE_TYPE  
-  if (strcmp (SIZE_TYPE, "unsigned int") == 0)
-    return INT_TYPE_SIZE;
-  if (strcmp (SIZE_TYPE, "long unsigned int") == 0)
-    return LONG_TYPE_SIZE;
-  if (strcmp (SIZE_TYPE, "short unsigned int") == 0)
-    return SHORT_TYPE_SIZE;
-  gcc_unreachable ();
-#else
-  return LONG_TYPE_SIZE;
-#endif
-}
-#endif
-
 /* Create the backend type nodes. We map them to their
    equivalent C type, at least for now.  We also give
    names to the types here, and we push them in the
Index: fortran/f95-lang.c
===================================================================
--- fortran/f95-lang.c	(revision 167230)
+++ fortran/f95-lang.c	(working copy)
@@ -551,14 +551,6 @@  clear_binding_stack (void)
 }
 
 
-#ifndef CHAR_TYPE_SIZE
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-#endif
-
-#ifndef INT_TYPE_SIZE
-#define INT_TYPE_SIZE BITS_PER_WORD
-#endif
-
 #undef SIZE_TYPE
 #define SIZE_TYPE "long unsigned int"
 
Index: fortran/trans-intrinsic.c
===================================================================
--- fortran/trans-intrinsic.c	(revision 167230)
+++ fortran/trans-intrinsic.c	(working copy)
@@ -385,9 +385,9 @@  build_round_expr (tree arg, tree restype
   /* Depending on the type of the result, choose the long int intrinsic
      (lround family) or long long intrinsic (llround).  We might also
      need to convert the result afterwards.  */
-  if (resprec <= LONG_TYPE_SIZE)
+  if (resprec <= TYPE_PRECISION (long_integer_type_node))
     longlong = false;
-  else if (resprec <= LONG_LONG_TYPE_SIZE)
+  else if (resprec <= TYPE_PRECISION (long_long_integer_type_node))
     longlong = true;
   else
     gcc_unreachable ();
@@ -3555,24 +3555,24 @@  gfc_conv_intrinsic_leadz (gfc_se * se, g
   argsize = TYPE_PRECISION (TREE_TYPE (arg));
 
   /* Which variant of __builtin_clz* should we call?  */
-  if (argsize <= INT_TYPE_SIZE)
+  if (argsize <= TYPE_PRECISION (unsigned_type_node))
     {
       arg_type = unsigned_type_node;
       func = built_in_decls[BUILT_IN_CLZ];
     }
-  else if (argsize <= LONG_TYPE_SIZE)
+  else if (argsize <= TYPE_PRECISION (long_unsigned_type_node))
     {
       arg_type = long_unsigned_type_node;
       func = built_in_decls[BUILT_IN_CLZL];
     }
-  else if (argsize <= LONG_LONG_TYPE_SIZE)
+  else if (argsize <= TYPE_PRECISION (long_long_unsigned_type_node))
     {
       arg_type = long_long_unsigned_type_node;
       func = built_in_decls[BUILT_IN_CLZLL];
     }
   else
     {
-      gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
+      gcc_assert (argsize == 2 * TYPE_PRECISION (long_long_unsigned_type_node));
       arg_type = gfc_build_uint_type (argsize);
       func = NULL_TREE;
     }
@@ -3609,7 +3609,8 @@  gfc_conv_intrinsic_leadz (gfc_se * se, g
 	 is the bit-size of the long long type (64 in this example).  */
       tree ullsize, ullmax, tmp1, tmp2;
 
-      ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
+      ullsize = build_int_cst (result_type,
+			       TYPE_PRECISION (long_long_unsigned_type_node));
       ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
 				long_long_unsigned_type_node,
 				build_int_cst (long_long_unsigned_type_node,
@@ -3674,24 +3675,24 @@  gfc_conv_intrinsic_trailz (gfc_se * se, 
   argsize = TYPE_PRECISION (TREE_TYPE (arg));
 
   /* Which variant of __builtin_ctz* should we call?  */
-  if (argsize <= INT_TYPE_SIZE)
+  if (argsize <= TYPE_PRECISION (unsigned_type_node))
     {
       arg_type = unsigned_type_node;
       func = built_in_decls[BUILT_IN_CTZ];
     }
-  else if (argsize <= LONG_TYPE_SIZE)
+  else if (argsize <= TYPE_PRECISION (long_unsigned_type_node))
     {
       arg_type = long_unsigned_type_node;
       func = built_in_decls[BUILT_IN_CTZL];
     }
-  else if (argsize <= LONG_LONG_TYPE_SIZE)
+  else if (argsize <= TYPE_PRECISION (long_long_unsigned_type_node))
     {
       arg_type = long_long_unsigned_type_node;
       func = built_in_decls[BUILT_IN_CTZLL];
     }
   else
     {
-      gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
+      gcc_assert (argsize == 2 * TYPE_PRECISION (long_long_unsigned_type_node));
       arg_type = gfc_build_uint_type (argsize);
       func = NULL_TREE;
     }
@@ -3723,7 +3724,8 @@  gfc_conv_intrinsic_trailz (gfc_se * se, 
 	 is the bit-size of the long long type (64 in this example).  */
       tree ullsize, ullmax, tmp1, tmp2;
 
-      ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
+      ullsize = build_int_cst (result_type,
+			       TYPE_PRECISION (long_long_unsigned_type_node));
       ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
 				long_long_unsigned_type_node,
 				build_int_cst (long_long_unsigned_type_node, 0));
@@ -3780,17 +3782,17 @@  gfc_conv_intrinsic_popcnt_poppar (gfc_se
   result_type = gfc_get_int_type (gfc_default_integer_kind);
 
   /* Which variant of the builtin should we call?  */
-  if (argsize <= INT_TYPE_SIZE)
+  if (argsize <= TYPE_PRECISION (unsigned_type_node))
     {
       arg_type = unsigned_type_node;
       func = built_in_decls[parity ? BUILT_IN_PARITY : BUILT_IN_POPCOUNT];
     }
-  else if (argsize <= LONG_TYPE_SIZE)
+  else if (argsize <= TYPE_PRECISION (long_unsigned_type_node))
     {
       arg_type = long_unsigned_type_node;
       func = built_in_decls[parity ? BUILT_IN_PARITYL : BUILT_IN_POPCOUNTL];
     }
-  else if (argsize <= LONG_LONG_TYPE_SIZE)
+  else if (argsize <= TYPE_PRECISION (long_long_unsigned_type_node))
     {
       arg_type = long_long_unsigned_type_node;
       func = built_in_decls[parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL];
@@ -3804,7 +3806,7 @@  gfc_conv_intrinsic_popcnt_poppar (gfc_se
 
       /* For now, we only cover the case where argsize is twice as large
 	 as 'long long'.  */
-      gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
+      gcc_assert (argsize == 2 * TYPE_PRECISION (long_long_unsigned_type_node));
 
       func = built_in_decls[parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL];
 
@@ -3818,8 +3820,10 @@  gfc_conv_intrinsic_popcnt_poppar (gfc_se
 				   fold_convert (long_long_unsigned_type_node,
 						 arg));
 
-      arg2 = fold_build2_loc (input_location, RSHIFT_EXPR, utype, arg,
-			      build_int_cst (utype, LONG_LONG_TYPE_SIZE));
+      arg2 = (fold_build2_loc
+	       (input_location, RSHIFT_EXPR, utype, arg,
+		build_int_cst (utype,
+			       TYPE_PRECISION (long_long_unsigned_type_node))));
       call2 = build_call_expr_loc (input_location, func, 1,
 				   fold_convert (long_long_unsigned_type_node,
 						 arg2));
Index: tree-data-ref.c
===================================================================
--- tree-data-ref.c	(revision 167230)
+++ tree-data-ref.c	(working copy)
@@ -92,6 +92,7 @@  Software Foundation; either version 3, o
 #include "tree-scalar-evolution.h"
 #include "tree-pass.h"
 #include "langhooks.h"
+#include "target.h"
 
 static struct datadep_stats
 {
@@ -1635,7 +1636,12 @@  estimated_loop_iterations_tree (struct l
   if (!estimated_loop_iterations (loop, conservative, &nit))
     return chrec_dont_know;
 
-  type = lang_hooks.types.type_for_size (INT_TYPE_SIZE, true);
+  /* FIXME: this seems rather iffy; better choices might be
+     TYPE_PRECISION (int_type_mode) or BITS_PER_WORD.  However, that would
+     not be bug-compatible, and for targets that have multiple fast integer
+     modes, all should be handled; likewise for signedness.  */
+  type = lang_hooks.types.type_for_size (targetm.integer_type_size (itk_int),
+					 true);
   if (!double_int_fits_to_tree_p (type, nit))
     return chrec_dont_know;
 
Index: coretypes.h
===================================================================
--- coretypes.h	(revision 167230)
+++ coretypes.h	(working copy)
@@ -157,6 +157,30 @@  #define gcc_obstack_init(OBSTACK)			\
    in target.h.  */
 typedef int reg_class_t;
 
+/* An enumeration of the standard C integer types.  These must be
+   ordered so that shorter types appear before longer ones, and so
+   that signed types appear before unsigned ones, for the correct
+   functioning of interpret_integer() in c-lex.c.  */
+enum integer_type_kind
+{
+  itk_char,
+  itk_signed_char,
+  itk_unsigned_char,
+  itk_short,
+  itk_unsigned_short,
+  itk_int,
+  itk_unsigned_int,
+  itk_long,
+  itk_unsigned_long,
+  itk_long_long,
+  itk_unsigned_long_long,
+  itk_int128,
+  itk_unsigned_int128,
+  itk_none
+};
+
+typedef enum integer_type_kind integer_type_kind;
+
 #else
 
 struct _dont_use_rtx_here_;
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 167230)
+++ Makefile.in	(working copy)
@@ -2667,7 +2667,7 @@  tree-scalar-evolution.o: tree-scalar-evo
    gt-tree-scalar-evolution.h tree-pretty-print.h gimple-pretty-print.h
 tree-data-ref.o: tree-data-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(GGC_H) $(FLAGS_H) $(TREE_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) \
-   $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \
+   $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) $(TARGET_H) \
    $(TREE_DATA_REF_H) $(TREE_PASS_H) langhooks.h tree-pretty-print.h \
    gimple-pretty-print.h
 sese.o: sese.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \