This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: locating unsigned type for non-standard precision


Richard Guenther wrote:
> On Tue, Apr 24, 2012 at 7:24 PM, Georg-Johann Lay <avr@gjlay.de> wrote:
>> Richard Guenther wrote:
>>
>>>> I've run into another issue supporting a 20-bit integer for which I'd
>>>> appreciate a hint.  With this code:
>>>>
>>>>   typedef long int __attribute__((__a20__)) int20_t;
>>>>   int20_t xi;
>>>>   int20_t addit () { xi += 0x54321L; }
>>>>
>>>> xi ends up in mode PSImode, which is a MODE_PARTIAL_INT with 20 bits of
>>>> precision and 32-bit width.
>>>>
>>>> convert() notices that, because the constant in the add expression is
>>>> SImode, there's an SImode add being truncated to a PSImode result, and
>>>> pushes the truncation down into the operands.
>>>>
>>>> The problem is this ends up in convert_to_integer, which detects that the
>>>> signed operation might overflow so calls unsigned_type_for() to get the
>>>> unsigned variant.
>>>>
>>>> Unfortunately, this ends up in c_common_type_for_size(), which knows nothing
>>>> about PSImode, and returns an unsigned type with 32 bits of precision when
>>>> asked for one with 20 bits of precision.
>>> That's expected - this function returns a type that is suitable for holding all
>>> values, not a type that has necessarily matching precision.  If the caller
>>> wants such type it needs to verify what the function returned.  Which seems
>>> to me to be the correct fix for this (premature) optimization in
>>> convert_to_integer.
>>>
>>> Richard.
>>>
>>>>   The expression is rewritten with
>>>> the 32-bit constant integer recast to the 32-bit unsigned type (instead
>>>> of the 20-bit one it might have used), and infinite recursion results.
>> This is already filed as
>>
>> http://gcc.gnu.org/PR51527
>>
>> It works with 4.8 trunk but crashes with 4.7.
>> Did not yet track what changes made it work with 4.8, though.
>> Unfortunately, noone remembers :-(
>>
>> http://gcc.gnu.org/ml/gcc/2012-03/msg00440.html
> 
> I have done changes in this area, trying to remove the type_for_size langhook.
> 
> Richard.

One apparent change is tree.c:signed_or_unsigned_type_for

that changed from 4.7:

tree
signed_or_unsigned_type_for (int unsignedp, tree type)
{
  tree t = type;
  if (POINTER_TYPE_P (type))
    {
      /* If the pointer points to the normal address space, use the
	 size_type_node.  Otherwise use an appropriate size for the pointer
	 based on the named address space it points to.  */
      if (!TYPE_ADDR_SPACE (TREE_TYPE (t)))
	t = size_type_node;
      else
	return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp);
    }

  if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp)
    return t;

  return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp);
}

to 4.8:

tree
signed_or_unsigned_type_for (int unsignedp, tree type)
{
  if (TREE_CODE (type) == INTEGER_TYPE && TYPE_UNSIGNED (type) == unsignedp)
    return type;

  if (!INTEGRAL_TYPE_P (type)
      && !POINTER_TYPE_P (type))
    return NULL_TREE;

  return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
}

at 2012-03-12

http://gcc.gnu.org/viewcvs?view=revision&revision=185226

Is this appropriate to backport?

Or is the preferred solution to override lang_hooks.types.type_for_size in the
backend, if applicable?

Johann

>>>> Is it proper for c_common_type_for_size() to know about partial int modes
>>>> and return the best one available?  Is there a hook that would allow me to
>>>> do this customized in my back-end?  Or is there another way to get
>>>> unsigned_type_for() to return the "right" type for an unusual integer
>>>> precision?
>>>>
>>>> Thanks.
>>>>
>>>> Peter


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]