diff mbox

[1/4] change specific int128 -> generic intN

Message ID 201406242332.s5ONWOZn012836@greed.delorie.com
State New
Headers show

Commit Message

DJ Delorie June 24, 2014, 11:32 p.m. UTC
Part 1 of 4, split from the full patch.  The purpose of this set of
changes is to remove assumptions in GCC about type sizes.  Previous to
this patch, GCC assumed that all types were powers-of-two in size, and
used naive math accordingly.

Old:
	POINTER_SIZE / BITS_PER_UNIT
	TYPE_SIZE
	GET_MODE_BITSIZE

New:
	POINTER_SIZE_UNITS  (ceil, not floor)
	TYPE_PRECISION
	GET_MODE_PRECISION


gcc/
	* cppbuiltin.c (define_builtin_macros_for_type_sizes): Round
	pointer size up to a power of two.
	* defaults.h (DWARF2_ADDR_SIZE): Round up.
	(POINTER_SIZE_UNITS): New, rounded up value.
	* dwarf2asm.c (size_of_encoded_value): Use it.
	(dw2_output_indirect_constant_1): Likewise.
	* expmed.c (init_expmed_one_conv): We now know the sizes of
	partial int modes.
	* loop-iv.c (iv_number_of_iterations): Use precision, not size.
	* optabs.c (expand_float): Use precision, not size.
	(expand_fix): Likewise.
	* simplify-rtx (simplify_unary_operation_1): Likewise.
	* tree-dfa.c (get_ref_base_and_extent): Likewise.
	* varasm.c (assemble_addr_to_section): Round up pointer sizes.
	(default_assemble_integer) Likewise.
	(dump_tm_clone_pairs): Likewise.
	* tree-core.c: Adjust comment.

gcc/lto/
	* lto-object.c (lto_obj_begin_section): Do not assume pointers are
	powers-of-two in size.

gcc/c-family/
	* c-cppbuiltin.c (cpp_atomic_builtins): Round pointer sizes up.
	(type_suffix): Use type precision, not specific types.

Comments

Eric Botcazou June 27, 2014, 11:20 a.m. UTC | #1
> gcc/
> 	* cppbuiltin.c (define_builtin_macros_for_type_sizes): Round
> 	pointer size up to a power of two.
> 	* defaults.h (DWARF2_ADDR_SIZE): Round up.
> 	(POINTER_SIZE_UNITS): New, rounded up value.
> 	* dwarf2asm.c (size_of_encoded_value): Use it.
> 	(dw2_output_indirect_constant_1): Likewise.
> 	* expmed.c (init_expmed_one_conv): We now know the sizes of
> 	partial int modes.
> 	* loop-iv.c (iv_number_of_iterations): Use precision, not size.
> 	* optabs.c (expand_float): Use precision, not size.
> 	(expand_fix): Likewise.
> 	* simplify-rtx (simplify_unary_operation_1): Likewise.
> 	* tree-dfa.c (get_ref_base_and_extent): Likewise.
> 	* varasm.c (assemble_addr_to_section): Round up pointer sizes.
> 	(default_assemble_integer) Likewise.
> 	(dump_tm_clone_pairs): Likewise.
> 	* tree-core.c: Adjust comment.

No stor-layout.c listed here but...

> Index: gcc/stor-layout.c
> ===================================================================
> --- gcc/stor-layout.c	(revision 211858)
> +++ gcc/stor-layout.c	(working copy)
> @@ -2123,13 +2142,13 @@ layout_type (tree type)
> 
>      case BOOLEAN_TYPE:
>      case INTEGER_TYPE:
>      case ENUMERAL_TYPE:
>        SET_TYPE_MODE (type,
>  		     smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT));
> -      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
> +      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE
> (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE
> (type))); break;

This doesn't look correct, you might end up with types smaller than their 
modes and breaking the TYPE_SIZE/TYPE_SIZE_UNIT relationship.

> @@ -2516,16 +2535,33 @@ initialize_sizetypes (void)
>      precision = LONG_TYPE_SIZE;
>    else if (strcmp (SIZETYPE, "long long unsigned int") == 0)
>      precision = LONG_LONG_TYPE_SIZE;
>    else if (strcmp (SIZETYPE, "short unsigned int") == 0)
>      precision = SHORT_TYPE_SIZE;
>    else
>     gcc_unreachable ();
> 
>    bprecision
> -    = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
> +    = MIN (precision, MAX_FIXED_MODE_SIZE);
>    bprecision
>      = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
>    if (bprecision > HOST_BITS_PER_DOUBLE_INT)
>      bprecision = HOST_BITS_PER_DOUBLE_INT;
> 
>    /* Create stubs for sizetype and bitsizetype so we can create constants. 

Why are you reducing the precision here?
DJ Delorie June 27, 2014, 9:04 p.m. UTC | #2
> No stor-layout.c listed here but...

I knew I'd miss at least one in the split-up...

> > Index: gcc/stor-layout.c
> > ===================================================================
> > --- gcc/stor-layout.c	(revision 211858)
> > +++ gcc/stor-layout.c	(working copy)
> > @@ -2123,13 +2142,13 @@ layout_type (tree type)
> > 
> >      case BOOLEAN_TYPE:
> >      case INTEGER_TYPE:
> >      case ENUMERAL_TYPE:
> >        SET_TYPE_MODE (type,
> >  		     smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT));
> > -      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
> > +      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE
> > (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE
> > (type))); break;
> 
> This doesn't look correct, you might end up with types smaller than their 
> modes and breaking the TYPE_SIZE/TYPE_SIZE_UNIT relationship.

The whole point of using _PRECISION is to have the size be exactly the
same as the mode (bitsize is bigger than the mode for partial-int
modes).  TYPE_SIZE_UNIT should be its storage size, right?  If the
type is not a multiple of BITS_PER_UNIT, the actual size and
stored-in-memory size are going to be different.

The problem in the old code is that BITSIZE is not the size in bits of
the type, it's the size in bytes times BITS_PER_UNIT.  This meant that
all partial-int modes would be converted into their non-partial modes
eventually.  Most of my patch is about avoiding that.

If you still disagree, let's first figure out what the right
relationship between TYPE_SIZE and TYPE_SIZE_UNIT is, for types that
aren't a multiple of BITS_PER_UNIT.

> > @@ -2516,16 +2535,33 @@ initialize_sizetypes (void)
> >      precision = LONG_TYPE_SIZE;
> >    else if (strcmp (SIZETYPE, "long long unsigned int") == 0)
> >      precision = LONG_LONG_TYPE_SIZE;
> >    else if (strcmp (SIZETYPE, "short unsigned int") == 0)
> >      precision = SHORT_TYPE_SIZE;
> >    else
> >     gcc_unreachable ();
> > 
> >    bprecision
> > -    = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
> > +    = MIN (precision, MAX_FIXED_MODE_SIZE);
> >    bprecision
> >      = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
> >    if (bprecision > HOST_BITS_PER_DOUBLE_INT)
> >      bprecision = HOST_BITS_PER_DOUBLE_INT;
> > 
> >    /* Create stubs for sizetype and bitsizetype so we can create constants. 
> 
> Why are you reducing the precision here?

I'm not reducing it, I'm removing a case where it's rounded up.
Rounding up a 20-bit PSImode gives you SImode eventually.
Joseph Myers June 27, 2014, 9:38 p.m. UTC | #3
On Fri, 27 Jun 2014, DJ Delorie wrote:

> If you still disagree, let's first figure out what the right
> relationship between TYPE_SIZE and TYPE_SIZE_UNIT is, for types that
> aren't a multiple of BITS_PER_UNIT.

My suggestion: TYPE_SIZE should always be TYPE_SIZE_UNIT times 
BITS_PER_UNIT, so including any padding bits (and so should not exist, 
really - it's an extra pointer bulking up lots of trees with redundant 
information), while TYPE_PRECISION is what gives the number of value / 
sign bits.  If you're allocating bit-fields, TYPE_PRECISION will say how 
many bits to use; if you're allocating registers (which might not always 
correspond neatly to multiples of BITS_PER_UNIT), TYPE_MODE is what's 
relevant; otherwise, you're allocating whole bytes in memory and can use 
TYPE_SIZE_UNIT.
DJ Delorie June 27, 2014, 9:49 p.m. UTC | #4
Are you proposing we remove TYPE_SIZE completely?
Joseph Myers June 27, 2014, 9:57 p.m. UTC | #5
On Fri, 27 Jun 2014, DJ Delorie wrote:

> Are you proposing we remove TYPE_SIZE completely?

Yes; I think that makes sense, unless someone produces a clearer 
definition of what TYPE_SIZE means that isn't redundant.

If you find a particular use of TYPE_SIZE is using a size that isn't 
correct for your type whose precision is not a multiple of BITS_PER_UNIT, 
then in my model the correct fix is to change that use of TYPE_SIZE rather 
than to change the value of TYPE_SIZE for that type - and such a change 
(to use TYPE_PRECISION, maybe) would also be incremental progress towards 
eliminating TYPE_SIZE.
DJ Delorie June 27, 2014, 11:30 p.m. UTC | #6
> Yes; I think that makes sense, unless someone produces a clearer 
> definition of what TYPE_SIZE means that isn't redundant.

Does TYPE_SIZE have a different meaning than TYPE_PRECISION
for non-integer types?  Floats, vectors, complex?
DJ Delorie July 1, 2014, 2:23 a.m. UTC | #7
> If you find a particular use of TYPE_SIZE is using a size that isn't
> correct for your type whose precision is not a multiple of
> BITS_PER_UNIT, then in my model the correct fix is to change that
> use of TYPE_SIZE rather than to change the value of TYPE_SIZE for
> that type - and such a change (to use TYPE_PRECISION, maybe) would
> also be incremental progress towards eliminating TYPE_SIZE.

What about DECL_SIZE ?  It's set from TYPE_SIZE but there is no
DECL_PRECISION.

Also, TYPE_PRECISION is an integer, where TYPE_SIZE is a tree.
They're not universally swappable code-wise.

And I noticed that sizetype and bitsizetype are not really any
different any more either, why have both?
Eric Botcazou July 2, 2014, 8:15 a.m. UTC | #8
> The whole point of using _PRECISION is to have the size be exactly the
> same as the mode (bitsize is bigger than the mode for partial-int
> modes).  TYPE_SIZE_UNIT should be its storage size, right?  If the
> type is not a multiple of BITS_PER_UNIT, the actual size and
> stored-in-memory size are going to be different.

But you cannot use the PRECISION of a mode to set a size, since the SIZE of 
the mode can be used by the machine to access the object in that mode, so 
you'll end up with types whose TYPE_SIZE is smaller than the access size.

You need to use TYPE_PRECISION here.

> The problem in the old code is that BITSIZE is not the size in bits of
> the type, it's the size in bytes times BITS_PER_UNIT.  This meant that
> all partial-int modes would be converted into their non-partial modes
> eventually.  Most of my patch is about avoiding that.

Yes, BITSIZE is the size rounded up to BITS_PER_UNIT, but why is that a 
problem exactly?  Do you have modes whose size is not multiple of the unit?

> I'm not reducing it, I'm removing a case where it's rounded up.
> Rounding up a 20-bit PSImode gives you SImode eventually.

Yes, you are reducing it, the precision of bitsize must be at least that of 
sizetype + BITS_PER_UNIT_LOG + 1.
DJ Delorie July 2, 2014, 2:57 p.m. UTC | #9
> Do you have modes whose size is not multiple of the unit?

Yes.  That's exactly the problem I'm trying to solve here.  I'm making
partial int modes have real corresponding types, and they can be any
bit size, with target PS*modes to match.  The MSP430, for example, has
20-bit modes, 20-bit operands, and __int20.  Rounding up to byte sizes
forces everything into an emulated SImode which makes code size huge
and performance much worse.

Thus, in these cases, TYPE_SIZE and TYPE_SIZE_UNIT no longer have a
"* BITS_PER_UNIT" mathematical relationship.
Eric Botcazou July 3, 2014, 3:51 p.m. UTC | #10
> Yes.  That's exactly the problem I'm trying to solve here.  I'm making
> partial int modes have real corresponding types, and they can be any
> bit size, with target PS*modes to match.  The MSP430, for example, has
> 20-bit modes, 20-bit operands, and __int20.  Rounding up to byte sizes
> forces everything into an emulated SImode which makes code size huge
> and performance much worse.

And the hardware really loads 20 bits and not 24 bits?  If so, I think you 
might want to consider changing the unit to 4 bits instead of 8 bits.  If no,
the mode is padded and has 24-bit size so why is setting TYPE_PRECISION to 20 
not sufficient to achieve what you want?

> Thus, in these cases, TYPE_SIZE and TYPE_SIZE_UNIT no longer have a
> "* BITS_PER_UNIT" mathematical relationship.

I'm skeptical this can work, it's pretty fundamental.
DJ Delorie July 3, 2014, 4:12 p.m. UTC | #11
> And the hardware really loads 20 bits and not 24 bits?  If so, I
> think you might want to consider changing the unit to 4 bits instead
> of 8 bits.  If no, the mode is padded and has 24-bit size so why is
> setting TYPE_PRECISION to 20 not sufficient to achieve what you
> want?

The hardware transfers data in and out of byte-oriented memory in
TYPE_SIZE_UNITS chunks.  Once in a hardware register, all operations
are either 8, 16, or 20 bits (TYPE_SIZE) in size.  So yes, values are
padded in memory, but no, they are not padded in registers.

Setting TYPE_PRECISION is mostly useless, because most of gcc assumes
it's the same as TYPE_SIZE and ignores it.  Heck, most of gcc is
oblivious to the idea that types might not be powers-of-two in size.
GCC doesn't even bother with a DECL_PRECISION.

> > Thus, in these cases, TYPE_SIZE and TYPE_SIZE_UNIT no longer have
> > a "* BITS_PER_UNIT" mathematical relationship.
> 
> I'm skeptical this can work, it's pretty fundamental.

It seems to work just fine in testing, and I'm trying to make it
non-fundamental.
Bernd Schmidt July 3, 2014, 4:29 p.m. UTC | #12
On 07/03/2014 06:12 PM, DJ Delorie wrote:
> The hardware transfers data in and out of byte-oriented memory in
> TYPE_SIZE_UNITS chunks.  Once in a hardware register, all operations
> are either 8, 16, or 20 bits (TYPE_SIZE) in size.  So yes, values are
> padded in memory, but no, they are not padded in registers.
>
> Setting TYPE_PRECISION is mostly useless, because most of gcc assumes
> it's the same as TYPE_SIZE and ignores it.

That's what'll need fixing then. I doubt there are too many places that 
require changing.

Also, the above seems inaccurate:
$ grep  TYPE_PREC *.c|wc -l
633
$ grep  TYPE_SIZE *.c|wc -l
551

>  Heck, most of gcc is
> oblivious to the idea that types might not be powers-of-two in size.
> GCC doesn't even bother with a DECL_PRECISION.

Sure - why would you even need one?

>>> Thus, in these cases, TYPE_SIZE and TYPE_SIZE_UNIT no longer have
>>> a "* BITS_PER_UNIT" mathematical relationship.
>>
>> I'm skeptical this can work, it's pretty fundamental.
>
> It seems to work just fine in testing, and I'm trying to make it
> non-fundamental.

I also think this is not a very good idea.


Bernd
DJ Delorie July 3, 2014, 8:01 p.m. UTC | #13
> That's what'll need fixing then.

Can I change TYPE_SIZE to TYPE_SIZE_WITH_PADDING then?  Because it's
not reflecting the type's size any more.  Why do we have to round up a
type's size anyway?  That's a pointless assumption *unless* you're
allocating memory space for it, and in that case, you want
TYPE_SIZE_UNITS anyway.

> I doubt there are too many places that require changing.

I don't doubt it, because I've been fighting these assumptions for
years.

> > Heck, most of gcc is oblivious to the idea that types might not be
> > powers-of-two in size.  GCC doesn't even bother with a
> > DECL_PRECISION.
> 
> Sure - why would you even need one?

Why do we need to have DECL_SIZE_UNITS (the size of the type, rounded
up to whole number of bytes) and DECL_SIZE (the size of the type,
rounded up to whole number of bytes), yet not have something that says
how big the decl *really is* ?

A pointer on MSP430 is 20 bits.  All the general registers are 20
bits.  Not 16, and not 24.  20.  There's nothing in a decl that says
"I'm 20 bits" and inevitably it ends up being SImode instead of
PSImode.

> > It seems to work just fine in testing, and I'm trying to make it
> > non-fundamental.
> 
> I also think this is not a very good idea.

Then please provide a "very good idea" for how to teach gcc about true
20-bit types in a system with 8-bit memory and 16-bit words.
Eric Botcazou July 4, 2014, 9:43 a.m. UTC | #14
> Setting TYPE_PRECISION is mostly useless, because most of gcc assumes
> it's the same as TYPE_SIZE and ignores it.

Then you need to change that and not TYPE_SIZE.

> It seems to work just fine in testing, and I'm trying to make it
> non-fundamental.

I'm very skeptical...  In any case, having a type whose TYPE_SIZE is smaller 
than the size of its MODE is a lie which will bite you back at some point.
Eric Botcazou July 4, 2014, 9:48 a.m. UTC | #15
> I don't doubt it, because I've been fighting these assumptions for years.

The fight needs to be resumed/sped up, that's clearly the right thing to do.

> Then please provide a "very good idea" for how to teach gcc about true
> 20-bit types in a system with 8-bit memory and 16-bit words.

TYPE_PRECISION was designed precisely for this purpose.
DJ Delorie July 7, 2014, 6:01 a.m. UTC | #16
> I'm very skeptical...  In any case, having a type whose TYPE_SIZE is smaller 
> than the size of its MODE is a lie which will bite you back at some point.

Except gcc now knows the size of partial int modes.  In this case,
PSImode is 20 bits and TYPE_SIZE is 20 bits, so they match.

The code was biting me when TYPE_SIZE was bigger than PSImode, and the
code kept choosing SImode instead.
Eric Botcazou July 10, 2014, 8:30 a.m. UTC | #17
> Except gcc now knows the size of partial int modes.  In this case,
> PSImode is 20 bits and TYPE_SIZE is 20 bits, so they match.

I don't understand.  The problematic change is

> -      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
> +      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE
> (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE
> (type))); break;

which means that the precision of the mode is used to set the size of the 
type, which very likely means that the size of the mode is larger.  So the 
size of the mode will be larger than the size of the type, which is a lie.

> The code was biting me when TYPE_SIZE was bigger than PSImode, and the
> code kept choosing SImode instead.

IMO you're papering over the real issue, which appears to be the choice of the 
mode.  Why does the code choose PSImode instead of SImode, if the type and the 
mode have the same precision (20) and size (24)?
DJ Delorie July 10, 2014, 4:34 p.m. UTC | #18
> which means that the precision of the mode is used to set the size
> of the type, which very likely means that the size of the mode is
> larger.  So the size of the mode will be larger than the size of the
> type, which is a lie.

For partial int modes, the precision and size are the same, and
normally not a power of two.  The assumption that "PSImode is the same
size as SImode" is no longer valid.

> > The code was biting me when TYPE_SIZE was bigger than PSImode, and
> > the code kept choosing SImode instead.
> 
> IMO you're papering over the real issue, which appears to be the
> choice of the mode.  Why does the code choose PSImode instead of
> SImode, if the type and the mode have the same precision (20) and
> size (24)?

PSImode is 20 bits, fits in a 20 bit register, and uses 20 bit operations.

SImode is 32 bits, fits in two 16 bit registers, and uses 32 bit operations.

If a type is 17-20 bits, PSImode is chosen.  If it's 21 bits or
larger, SImode is chosen.  If it's 16 or fewer bits, HImode is chosen.

If you look at part 2 of the patch, you'll see lots of code that
implements this logic, although the change to specify the sizes of
partial int modes has been in for a while.
Eric Botcazou July 11, 2014, 9:04 a.m. UTC | #19
> PSImode is 20 bits, fits in a 20 bit register, and uses 20 bit operations.

Then why do you need this change?

> -      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
> +      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE
> (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE
> (type))); break;

What are GET_MODE_BITSIZE and GET_MODE_PRECISION for PSImode?

> If a type is 17-20 bits, PSImode is chosen.  If it's 21 bits or
> larger, SImode is chosen.  If it's 16 or fewer bits, HImode is chosen.

Size or precision?  That's the crux of the matter.
DJ Delorie July 11, 2014, 4:30 p.m. UTC | #20
> > PSImode is 20 bits, fits in a 20 bit register, and uses 20 bit operations.
> 
> Then why do you need this change?

Because parts of the gcc code use the byte size instead of the bit
size, or round up, or assume powers-of-two sizes.

> > -      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
> > +      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE
> > (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE
> > (type))); break;
> 
> What are GET_MODE_BITSIZE and GET_MODE_PRECISION for PSImode?

It *should* be 20 and 20 for msp430.  But GET_MODE_BITSIZE returns 32,
because it's a macro that does GET_MODE_SIZE * BITS_PER_UNIT, so it
cannot return 20.

> > If a type is 17-20 bits, PSImode is chosen.  If it's 21 bits or
> > larger, SImode is chosen.  If it's 16 or fewer bits, HImode is chosen.
> 
> Size or precision?  That's the crux of the matter.

GCC typically uses size for "fits in a" tests.
Eric Botcazou July 12, 2014, 9:13 a.m. UTC | #21
> > What are GET_MODE_BITSIZE and GET_MODE_PRECISION for PSImode?
> 
> It *should* be 20 and 20 for msp430.  But GET_MODE_BITSIZE returns 32,
> because it's a macro that does GET_MODE_SIZE * BITS_PER_UNIT, so it
> cannot return 20.

No, it should not be 20, mode sizes are multiple of the unit, you're mixing 
precision and size.  I doubt the hardware accesses 20 bits, more probably 24 
or 32 bits, so the mode size cannot be 20 bits.

> GCC typically uses size for "fits in a" tests.

Then change them to use the precision when this matters, the wide-int folks 
have already changed them in a few places but that's probably not sufficient.
diff mbox

Patch

Index: gcc/dwarf2asm.c
===================================================================
--- gcc/dwarf2asm.c	(revision 211858)
+++ gcc/dwarf2asm.c	(working copy)
@@ -387,13 +387,13 @@  size_of_encoded_value (int encoding)
   if (encoding == DW_EH_PE_omit)
     return 0;
 
   switch (encoding & 0x07)
     {
     case DW_EH_PE_absptr:
-      return POINTER_SIZE / BITS_PER_UNIT;
+      return POINTER_SIZE_UNITS;
     case DW_EH_PE_udata2:
       return 2;
     case DW_EH_PE_udata4:
       return 4;
     case DW_EH_PE_udata8:
       return 8;
@@ -917,13 +917,13 @@  dw2_output_indirect_constant_1 (splay_tr
       if (USE_LINKONCE_INDIRECT)
 	DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
     }
 
   sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
   assemble_variable (decl, 1, 1, 1);
-  assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+  assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
 
   return 0;
 }
 
 /* Emit the constants queued through dw2_force_const_mem.  */
 
Index: gcc/cppbuiltin.c
===================================================================
--- gcc/cppbuiltin.c	(revision 211858)
+++ gcc/cppbuiltin.c	(working copy)
@@ -172,13 +172,13 @@  define_builtin_macros_for_type_sizes (cp
                          ? "__ORDER_BIG_ENDIAN__"
                          : "__ORDER_LITTLE_ENDIAN__"));
 
   /* ptr_type_node can't be used here since ptr_mode is only set when
      toplev calls backend_init which is not done with -E switch.  */
   cpp_define_formatted (pfile, "__SIZEOF_POINTER__=%d",
-			POINTER_SIZE / BITS_PER_UNIT);
+			1 << ceil_log2 ((POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT));
 }
 
 
 /* Define macros builtins common to all language performing CPP
    preprocessing.  */
 void
Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c	(revision 211858)
+++ gcc/c-family/c-cppbuiltin.c	(working copy)
@@ -675,13 +675,13 @@  cpp_atomic_builtins (cpp_reader *pfile)
      to a boolean truth value, let the library work around that.  */
   builtin_define_with_int_value ("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL",
 				 targetm.atomic_test_and_set_trueval);
 
   /* ptr_type_node can't be used here since ptr_mode is only set when
      toplev calls backend_init which is not done with -E  or pch.  */
-  psize = POINTER_SIZE / BITS_PER_UNIT;
+  psize = POINTER_SIZE_UNITS;
   if (psize >= SWAP_LIMIT)
     psize = 0;
   builtin_define_with_int_value ("__GCC_ATOMIC_POINTER_LOCK_FREE", 
 			(have_swap[psize]? 2 : 1));
 }
 
@@ -1227,18 +1269,21 @@  builtin_define_with_hex_fp_value (const 
 static const char *
 type_suffix (tree type)
 {
   static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
   int unsigned_suffix;
   int is_long;
+  int tp = TYPE_PRECISION (type);
 
   if (type == long_long_integer_type_node
-      || type == long_long_unsigned_type_node)
+      || type == long_long_unsigned_type_node
+      || tp > TYPE_PRECISION (long_integer_type_node))
     is_long = 2;
   else if (type == long_integer_type_node
-	   || type == long_unsigned_type_node)
+	   || type == long_unsigned_type_node
+	   || tp > TYPE_PRECISION (integer_type_node))
     is_long = 1;
   else if (type == integer_type_node
 	   || type == unsigned_type_node
 	   || type == short_integer_type_node
 	   || type == short_unsigned_type_node
 	   || type == signed_char_type_node
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	(revision 211858)
+++ gcc/optabs.c	(working copy)
@@ -5178,13 +5178,13 @@  expand_float (rtx to, rtx from, int unsi
     {
       rtx libfunc;
       rtx insns;
       rtx value;
       convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
 
-      if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
+      if (GET_MODE_PRECISION (GET_MODE (from)) < GET_MODE_PRECISION (SImode))
 	from = convert_to_mode (SImode, from, unsignedp);
 
       libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
       gcc_assert (libfunc);
 
       start_sequence ();
@@ -5354,13 +5354,13 @@  expand_fix (rtx to, rtx from, int unsign
 	}
 
   /* We can't do it with an insn, so use a library call.  But first ensure
      that the mode of TO is at least as wide as SImode, since those are the
      only library calls we know about.  */
 
-  if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
+  if (GET_MODE_PRECISION (GET_MODE (to)) < GET_MODE_PRECISION (SImode))
     {
       target = gen_reg_rtx (SImode);
 
       expand_fix (target, from, unsignedp);
     }
   else
Index: gcc/defaults.h
===================================================================
--- gcc/defaults.h	(revision 211858)
+++ gcc/defaults.h	(working copy)
@@ -448,13 +448,13 @@  see the files COPYING3 and COPYING.RUNTI
 /* The size of addresses as they appear in the Dwarf 2 data.
    Some architectures use word addresses to refer to code locations,
    but Dwarf 2 info always uses byte addresses.  On such machines,
    Dwarf 2 addresses need to be larger than the architecture's
    pointers.  */
 #ifndef DWARF2_ADDR_SIZE
-#define DWARF2_ADDR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
+#define DWARF2_ADDR_SIZE ((POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT)
 #endif
 
 /* The size in bytes of a DWARF field indicating an offset or length
    relative to a debug info section, specified to be 4 bytes in the
    DWARF-2 specification.  The SGI/MIPS ABI defines it to be the same
    as PTR_SIZE.  */
@@ -748,12 +748,16 @@  see the files COPYING3 and COPYING.RUNTI
 #endif
 
 /* Width in bits of a pointer.  Mind the value of the macro `Pmode'.  */
 #ifndef POINTER_SIZE
 #define POINTER_SIZE BITS_PER_WORD
 #endif
+#ifndef POINTER_SIZE_UNITS
+#define POINTER_SIZE_UNITS ((POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT)
+#endif
+
 
 #ifndef PIC_OFFSET_TABLE_REGNUM
 #define PIC_OFFSET_TABLE_REGNUM INVALID_REGNUM
 #endif
 
 #ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	(revision 211858)
+++ gcc/stor-layout.c	(working copy)
@@ -2123,13 +2142,13 @@  layout_type (tree type)
 
     case BOOLEAN_TYPE:
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
       SET_TYPE_MODE (type,
 		     smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT));
-      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE (type)));
       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
       break;
 
     case REAL_TYPE:
       SET_TYPE_MODE (type,
 		     mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0));
@@ -2194,13 +2213,13 @@  layout_type (tree type)
       TYPE_USER_ALIGN (type) = 0;
       SET_TYPE_MODE (type, VOIDmode);
       break;
 
     case OFFSET_TYPE:
       TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
-      TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
+      TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE_UNITS);
       /* A pointer might be MODE_PARTIAL_INT,
 	 but ptrdiff_t must be integral.  */
       SET_TYPE_MODE (type, mode_for_size (POINTER_SIZE, MODE_INT, 0));
       TYPE_PRECISION (type) = POINTER_SIZE;
       break;
 
@@ -2224,13 +2243,13 @@  layout_type (tree type)
 	    mode = targetm.addr_space.address_mode (as);
 	  }
 
 	TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
 	TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
 	TYPE_UNSIGNED (type) = 1;
-	TYPE_PRECISION (type) = GET_MODE_BITSIZE (mode);
+	TYPE_PRECISION (type) = GET_MODE_PRECISION (mode);
       }
       break;
 
     case ARRAY_TYPE:
       {
 	tree index = TYPE_DOMAIN (type);
@@ -2516,16 +2535,33 @@  initialize_sizetypes (void)
     precision = LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "long long unsigned int") == 0)
     precision = LONG_LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "short unsigned int") == 0)
     precision = SHORT_TYPE_SIZE;
   else
    gcc_unreachable ();
 
   bprecision
-    = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
+    = MIN (precision, MAX_FIXED_MODE_SIZE);
   bprecision
     = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
   if (bprecision > HOST_BITS_PER_DOUBLE_INT)
     bprecision = HOST_BITS_PER_DOUBLE_INT;
 
   /* Create stubs for sizetype and bitsizetype so we can create constants.  */
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	(revision 211858)
+++ gcc/expmed.c	(working copy)
@@ -115,19 +115,25 @@  static void
 init_expmed_one_conv (struct init_expmed_rtl *all, enum machine_mode to_mode,
 		      enum machine_mode from_mode, bool speed)
 {
   int to_size, from_size;
   rtx which;
 
-  /* We're given no information about the true size of a partial integer,
-     only the size of the "full" integer it requires for storage.  For
-     comparison purposes here, reduce the bit size by one in that case.  */
-  to_size = (GET_MODE_BITSIZE (to_mode)
-	     - (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT));
-  from_size = (GET_MODE_BITSIZE (from_mode)
-	       - (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT));
+  to_size = GET_MODE_PRECISION (to_mode);
+  from_size = GET_MODE_PRECISION (from_mode);
+
+  /* Most partial integers have a precision less than the "full"
+     integer it requires for storage.  In case one doesn't, for
+     comparison purposes here, reduce the bit size by one in that
+     case.  */
+  if (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT
+      && exact_log2 (to_size) != -1)
+    to_size --;
+  if (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT
+      && exact_log2 (from_size) != -1)
+    from_size --;
   
   /* Assume cost of zero-extend and sign-extend is the same.  */
   which = (to_size < from_size ? &all->trunc : &all->zext);
 
   PUT_MODE (&all->reg, from_mode);
   set_convert_cost (to_mode, from_mode, speed, set_src_cost (which, speed));
Index: gcc/tree-dfa.c
===================================================================
--- gcc/tree-dfa.c	(revision 211858)
+++ gcc/tree-dfa.c	(working copy)
@@ -404,13 +404,13 @@  get_ref_base_and_extent (tree exp, HOST_
   else if (!VOID_TYPE_P (TREE_TYPE (exp)))
     {
       enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
       if (mode == BLKmode)
 	size_tree = TYPE_SIZE (TREE_TYPE (exp));
       else
-	bitsize = int (GET_MODE_BITSIZE (mode));
+	bitsize = int (GET_MODE_PRECISION (mode));
     }
   if (size_tree != NULL_TREE
       && TREE_CODE (size_tree) == INTEGER_CST)
     bitsize = wi::to_offset (size_tree);
 
   /* Initially, maxsize is the same as the accessed element size.
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	(revision 211858)
+++ gcc/simplify-rtx.c	(working copy)
@@ -1361,14 +1361,14 @@  simplify_unary_operation_1 (enum rtx_cod
 	}
 
       /* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>).
 	 (sign_extend:M (zero_extend:N <X>)) is (zero_extend:M <X>).  */
       if (GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND)
 	{
-	  gcc_assert (GET_MODE_BITSIZE (mode)
-		      > GET_MODE_BITSIZE (GET_MODE (op)));
+	  gcc_assert (GET_MODE_PRECISION (mode)
+		      > GET_MODE_PRECISION (GET_MODE (op)));
 	  return simplify_gen_unary (GET_CODE (op), mode, XEXP (op, 0),
 				     GET_MODE (XEXP (op, 0)));
 	}
 
       /* (sign_extend:M (ashiftrt:N (ashift <X> (const_int I)) (const_int I)))
 	 is (sign_extend:M (subreg:O <X>)) if there is mode with
Index: gcc/lto/lto-object.c
===================================================================
--- gcc/lto/lto-object.c	(revision 211858)
+++ gcc/lto/lto-object.c	(working copy)
@@ -335,13 +335,13 @@  lto_obj_begin_section (const char *name)
   lo = (struct lto_simple_object *) current_out_file;
   gcc_assert (lo != NULL
 	      && lo->sobj_r == NULL
 	      && lo->sobj_w != NULL
 	      && lo->section == NULL);
 
-  align = exact_log2 (POINTER_SIZE / BITS_PER_UNIT);
+  align = ceil_log2 (POINTER_SIZE_UNITS);
   lo->section = simple_object_write_create_section (lo->sobj_w, name, align,
 						    &errmsg, &err);
   if (lo->section == NULL)
     {
       if (err == 0)
 	fatal_error ("%s", errmsg);
Index: gcc/loop-iv.c
===================================================================
--- gcc/loop-iv.c	(revision 211858)
+++ gcc/loop-iv.c	(working copy)
@@ -2409,13 +2409,13 @@  iv_number_of_iterations (struct loop *lo
 
   if (!canonicalize_iv_subregs (&iv0, &iv1, cond, desc))
     goto fail;
 
   comp_mode = iv0.extend_mode;
   mode = iv0.mode;
-  size = GET_MODE_BITSIZE (mode);
+  size = GET_MODE_PRECISION (mode);
   get_mode_bounds (mode, (cond == LE || cond == LT), comp_mode, &mmin, &mmax);
   mode_mmin = lowpart_subreg (mode, mmin, comp_mode);
   mode_mmax = lowpart_subreg (mode, mmax, comp_mode);
 
   if (!CONST_INT_P (iv0.step) || !CONST_INT_P (iv1.step))
     goto fail;
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	(revision 211858)
+++ gcc/varasm.c	(working copy)
@@ -1466,13 +1466,13 @@  assemble_asm (tree string)
 /* Write the address of the entity given by SYMBOL to SEC.  */
 void
 assemble_addr_to_section (rtx symbol, section *sec)
 {
   switch_to_section (sec);
   assemble_align (POINTER_SIZE);
-  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+  assemble_integer (symbol, (POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT, POINTER_SIZE, 1);
 }
 
 /* Return the numbered .ctors.N (if CONSTRUCTOR_P) or .dtors.N (if
    not) section for PRIORITY.  */
 section *
 get_cdtor_priority_section (int priority, bool constructor_p)
@@ -2619,13 +2619,13 @@  default_assemble_integer (rtx x ATTRIBUT
 			  unsigned int size ATTRIBUTE_UNUSED,
 			  int aligned_p ATTRIBUTE_UNUSED)
 {
   const char *op = integer_asm_op (size, aligned_p);
   /* Avoid GAS bugs for large values.  Specifically negative values whose
      absolute value fits in a bfd_vma, but not in a bfd_signed_vma.  */
-  if (size > UNITS_PER_WORD && size > POINTER_SIZE / BITS_PER_UNIT)
+  if (size > UNITS_PER_WORD && size > POINTER_SIZE_UNITS)
     return false;
   return op && (assemble_integer_with_op (op, x), true);
 }
 
 /* Assemble the integer constant X into an object of SIZE bytes.  ALIGN is
    the alignment of the integer in bits.  Return 1 if we were able to output
@@ -5750,15 +5750,15 @@  dump_tm_clone_pairs (vec<tm_alias_pair> 
 	  switch_to_section (targetm.asm_out.tm_clone_table_section ());
 	  assemble_align (POINTER_SIZE);
 	  switched = true;
 	}
 
       assemble_integer (XEXP (DECL_RTL (src), 0),
-			POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+			POINTER_SIZE_UNITS, POINTER_SIZE, 1);
       assemble_integer (XEXP (DECL_RTL (dst), 0),
-			POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+			POINTER_SIZE_UNITS, POINTER_SIZE, 1);
     }
 }
 
 /* Provide a default for the tm_clone_table section.  */
 
 section *
Index: gcc/tree-core.h
===================================================================
--- gcc/tree-core.h	(revision 211858)
+++ gcc/tree-core.h	(working copy)
@@ -1147,13 +1155,13 @@  enum omp_clause_map_kind
   OMP_CLAUSE_MAP_ALLOC,
   OMP_CLAUSE_MAP_TO,
   OMP_CLAUSE_MAP_FROM,
   OMP_CLAUSE_MAP_TOFROM,
   /* The following kind is an internal only map kind, used for pointer based
      array sections.  OMP_CLAUSE_SIZE for these is not the pointer size,
-     which is implicitly POINTER_SIZE / BITS_PER_UNIT, but the bias.  */
+     which is implicitly POINTER_SIZE_UNITS, but the bias.  */
   OMP_CLAUSE_MAP_POINTER,
   /* Also internal, behaves like OMP_CLAUS_MAP_TO, but additionally any
      OMP_CLAUSE_MAP_POINTER records consecutive after it which have addresses
      falling into that range will not be ignored if OMP_CLAUSE_MAP_TO_PSET
      wasn't mapped already.  */
   OMP_CLAUSE_MAP_TO_PSET,