WARNING: This server is unstable and will be retired in the next days. If you want to keep this forum available, please request immediately a migration on the Nabble Support forum. Forums that don't receive any migration request will be deleted forever.

locating unsigned type for non-standard precision

View: New views
13 Messages — Rating Filter:   Alert me  

locating unsigned type for non-standard precision

by Peter Bigot-4 :: Rate this Message:

| View Threaded | Show Only this Message

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.  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.

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

Re: locating unsigned type for non-standard precision

by Richard Guenther-2 :: Rate this Message:

| View Threaded | Show Only this Message

On Tue, Apr 24, 2012 at 3:50 PM, Peter Bigot <bigotp@...> 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.
>
> 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

Re: locating unsigned type for non-standard precision

by Peter Bigot-4 :: Rate this Message:

| View Threaded | Show Only this Message

On Tue, Apr 24, 2012 at 9:01 AM, Richard Guenther
<richard.guenther@...> wrote:

> On Tue, Apr 24, 2012 at 3:50 PM, Peter Bigot <bigotp@...> 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.

Thanks; I'll fix it that way and file a bug report to track it.

Peter

Re: locating unsigned type for non-standard precision

by Georg-Johann Lay-2 :: Rate this Message:

| View Threaded | Show Only this Message

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

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


Re: locating unsigned type for non-standard precision

by Richard Guenther-2 :: Rate this Message:

| View Threaded | Show Only this Message

On Tue, Apr 24, 2012 at 7:24 PM, Georg-Johann Lay <avr@...> 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.

> 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
>

Re: locating unsigned type for non-standard precision

by Georg-Johann Lay-2 :: Rate this Message:

| View Threaded | Show Only this Message

Richard Guenther wrote:

> On Tue, Apr 24, 2012 at 7:24 PM, Georg-Johann Lay <avr@...> 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

Re: locating unsigned type for non-standard precision

by Georg-Johann Lay-2 :: Rate this Message:

| View Threaded | Show Only this Message

Georg-Johann Lay wrote:

> Richard Guenther wrote:
>> On Tue, Apr 24, 2012 at 7:24 PM, Georg-Johann Lay <avr@...> 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?

Now I have this piece of code that works for 4.7.

I don't like it much, but if there are no plans to otherwise fix PR51527,
I'd make a patch and propose it as target-specific work-around.

/* Some auxiliary stuff for the AVR-specific built-in 24-bit scalar integer
   types __int24 and __uint24 to be used in `avr_init_builtins'.  */

static GTY(()) tree avr_int24_type;
static GTY(()) tree avr_uint24_type;


/* Implement `LANG_HOOKS_TYPE_FOR_SIZE'.  */
/* To avoid infinite recursion in `convert_to_integer' as
   reported in PR c/51527.  */

static tree (*avr_default_type_for_size)(unsigned int, int);

static tree
avr_type_for_size (unsigned int bits, int unsignedp)
{
  if (bits == 24)
    return unsignedp ? avr_uint24_type : avr_int24_type;

  return avr_default_type_for_size (bits, unsignedp);
}


static void
avr_init_builtin_int24 (void)
{
  avr_int24_type  = make_signed_type (GET_MODE_BITSIZE (PSImode));
  avr_uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));

  lang_hooks.types.register_builtin_type (avr_int24_type, "__int24");
  lang_hooks.types.register_builtin_type (avr_uint24_type, "__uint24");

  /* Hook-in to avoid infinite recursion in `convert_to_integer' as
     reported in PR c/51527.  */

  avr_default_type_for_size = lang_hooks.types.type_for_size;
  lang_hooks.types.type_for_size = avr_type_for_size;
}


A proper, target-independent fix would be great because it is the right place
and because Peter has the same problem.

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

Re: locating unsigned type for non-standard precision

by Richard Guenther-2 :: Rate this Message:

| View Threaded | Show Only this Message

On Wed, Apr 25, 2012 at 7:34 PM, Georg-Johann Lay <avr@...> wrote:

> Georg-Johann Lay wrote:
>> Richard Guenther wrote:
>>> On Tue, Apr 24, 2012 at 7:24 PM, Georg-Johann Lay <avr@...> 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?

No, it's not.

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

Neither.  It is a "lang"-hook, not a target-hook after all.

I already told you what the right fix is - the callers of
type_for_size have to cater
for the returned type to be of different precision.  Btw, I already see it does

                /* But now perhaps TYPEX is as wide as INPREC.
                   In that case, do nothing special here.
                   (Otherwise would recurse infinitely in convert.  */
                if (TYPE_PRECISION (typex) != inprec)

Richard.

> Now I have this piece of code that works for 4.7.
>
> I don't like it much, but if there are no plans to otherwise fix PR51527,
> I'd make a patch and propose it as target-specific work-around.
>
> /* Some auxiliary stuff for the AVR-specific built-in 24-bit scalar integer
>   types __int24 and __uint24 to be used in `avr_init_builtins'.  */
>
> static GTY(()) tree avr_int24_type;
> static GTY(()) tree avr_uint24_type;
>
>
> /* Implement `LANG_HOOKS_TYPE_FOR_SIZE'.  */
> /* To avoid infinite recursion in `convert_to_integer' as
>   reported in PR c/51527.  */
>
> static tree (*avr_default_type_for_size)(unsigned int, int);
>
> static tree
> avr_type_for_size (unsigned int bits, int unsignedp)
> {
>  if (bits == 24)
>    return unsignedp ? avr_uint24_type : avr_int24_type;
>
>  return avr_default_type_for_size (bits, unsignedp);
> }
>
>
> static void
> avr_init_builtin_int24 (void)
> {
>  avr_int24_type  = make_signed_type (GET_MODE_BITSIZE (PSImode));
>  avr_uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
>
>  lang_hooks.types.register_builtin_type (avr_int24_type, "__int24");
>  lang_hooks.types.register_builtin_type (avr_uint24_type, "__uint24");
>
>  /* Hook-in to avoid infinite recursion in `convert_to_integer' as
>     reported in PR c/51527.  */
>
>  avr_default_type_for_size = lang_hooks.types.type_for_size;
>  lang_hooks.types.type_for_size = avr_type_for_size;
> }
>
>
> A proper, target-independent fix would be great because it is the right place
> and because Peter has the same problem.
>
> 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

Re: locating unsigned type for non-standard precision

by Georg-Johann Lay-2 :: Rate this Message:

| View Threaded | Show Only this Message

Richard Guenther wrote:

> Georg-Johann Lay wrote:
>> Georg-Johann Lay wrote:
>>> Richard Guenther wrote:
>>>> Georg-Johann Lay wrote:
>>>>> [...]
>>>>>
>>>>> 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 [...] at 2012-03-12
>>>
>>> http://gcc.gnu.org/viewcvs?view=revision&revision=185226
>>>
>>> Is this appropriate to backport?
>
> No, it's not.
>
>>> Or is the preferred solution to override lang_hooks.types.type_for_size in the
>>> backend, if applicable?
>
> Neither.  It is a "lang"-hook, not a target-hook after all.
>
> I already told you what the right fix is - the callers of
> type_for_size have to cater
> for the returned type to be of different precision.  Btw, I already see it does
>
>                 /* But now perhaps TYPEX is as wide as INPREC.
>                    In that case, do nothing special here.
>                    (Otherwise would recurse infinitely in convert.  */
>                 if (TYPE_PRECISION (typex) != inprec)
>
> Richard

Would you help me with the code? It's almost impossible to understand the
convert stuff for a noob. I tried TARGET_CONVERT_TO_TYPE

static tree
avr_convert_to_type (tree type, tree expr)
{
  tree xtype = TREE_TYPE (expr);

  /* convert enters infinite recursion for __int24 -> unsigned long
     convertsions.  */

  if (/* From __int24 ... */
      TREE_CODE (xtype) == INTEGER_TYPE
      && TYPE_PRECISION (xtype) == 24
      && !TYPE_UNSIGNED (xtype)
      /* ... to unsigned long.  */
      && TREE_CODE (type) == INTEGER_TYPE
      && TYPE_PRECISION (type) > 24
      && TYPE_UNSIGNED (type))
    {
      /* Perform an intermediate conversion:
         __int24 -> long -> unsigned long  */

      /* Signed variant of type */
      tree stype = lang_hooks.types.type_for_mode (TYPE_MODE (type), 0);

      expr = convert (stype, expr);
      //      expr = build1 (CONVERT_EXPR, stype, expr);
      expr = build1 (NOP_EXPR, type, expr);

      return expr;
    }

  return NULL_TREE;
}

#undef  TARGET_CONVERT_TO_TYPE
#define TARGET_CONVERT_TO_TYPE avr_convert_to_type


but with no avail. The explicit, intermediate conversion from __int24 to long
does not prevent the infinite recursion.

Johann


Re: locating unsigned type for non-standard precision

by Richard Guenther-2 :: Rate this Message:

| View Threaded | Show Only this Message

On Thu, Apr 26, 2012 at 3:12 PM, Georg-Johann Lay <avr@...> wrote:

> Richard Guenther wrote:
>> Georg-Johann Lay wrote:
>>> Georg-Johann Lay wrote:
>>>> Richard Guenther wrote:
>>>>> Georg-Johann Lay wrote:
>>>>>> [...]
>>>>>>
>>>>>> 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 [...] at 2012-03-12
>>>>
>>>> http://gcc.gnu.org/viewcvs?view=revision&revision=185226
>>>>
>>>> Is this appropriate to backport?
>>
>> No, it's not.
>>
>>>> Or is the preferred solution to override lang_hooks.types.type_for_size in the
>>>> backend, if applicable?
>>
>> Neither.  It is a "lang"-hook, not a target-hook after all.
>>
>> I already told you what the right fix is - the callers of
>> type_for_size have to cater
>> for the returned type to be of different precision.  Btw, I already see it does
>>
>>                 /* But now perhaps TYPEX is as wide as INPREC.
>>                    In that case, do nothing special here.
>>                    (Otherwise would recurse infinitely in convert.  */
>>                 if (TYPE_PRECISION (typex) != inprec)
>>
>> Richard
>
> Would you help me with the code? It's almost impossible to understand the
> convert stuff for a noob. I tried TARGET_CONVERT_TO_TYPE
>
> static tree
> avr_convert_to_type (tree type, tree expr)
> {
>  tree xtype = TREE_TYPE (expr);
>
>  /* convert enters infinite recursion for __int24 -> unsigned long
>     convertsions.  */
>
>  if (/* From __int24 ... */
>      TREE_CODE (xtype) == INTEGER_TYPE
>      && TYPE_PRECISION (xtype) == 24
>      && !TYPE_UNSIGNED (xtype)
>      /* ... to unsigned long.  */
>      && TREE_CODE (type) == INTEGER_TYPE
>      && TYPE_PRECISION (type) > 24
>      && TYPE_UNSIGNED (type))
>    {
>      /* Perform an intermediate conversion:
>         __int24 -> long -> unsigned long  */
>
>      /* Signed variant of type */
>      tree stype = lang_hooks.types.type_for_mode (TYPE_MODE (type), 0);
>
>      expr = convert (stype, expr);
>      //      expr = build1 (CONVERT_EXPR, stype, expr);
>      expr = build1 (NOP_EXPR, type, expr);
>
>      return expr;
>    }
>
>  return NULL_TREE;
> }
>
> #undef  TARGET_CONVERT_TO_TYPE
> #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
>
>
> but with no avail. The explicit, intermediate conversion from __int24 to long
> does not prevent the infinite recursion.

I think the fix would be sth like

Index: gcc/convert.c
===================================================================
--- gcc/convert.c       (revision 186871)
+++ gcc/convert.c       (working copy)
@@ -769,6 +769,7 @@ convert_to_integer (tree type, tree expr
                   (Otherwise would recurse infinitely in convert.  */
                if (TYPE_PRECISION (typex) != inprec)
                  {
+                   tree otypex = typex;
                    /* Don't do unsigned arithmetic where signed was wanted,
                       or vice versa.
                       Exception: if both of the original operands were
@@ -806,10 +807,11 @@ convert_to_integer (tree type, tree expr
                      typex = unsigned_type_for (typex);
                    else
                      typex = signed_type_for (typex);
-                   return convert (type,
-                                   fold_build2 (ex_form, typex,
-                                                convert (typex, arg0),
-                                                convert (typex, arg1)));
+                   if (TYPE_PRECISION (otypex) == TYPE_PRECISION (typex))
+                     return convert (type,
+                                     fold_build2 (ex_form, typex,
+                                                  convert (typex, arg0),
+                                                  convert (typex, arg1)));
                  }
              }
          }


> Johann
>

Re: locating unsigned type for non-standard precision

by Georg-Johann Lay-2 :: Rate this Message:

| View Threaded | Show Only this Message

Richard Guenther wrote:

> [PR c/51527]
>
> I think the fix would be sth like
>
> Index: gcc/convert.c
> ===================================================================
> --- gcc/convert.c       (revision 186871)
> +++ gcc/convert.c       (working copy)
> @@ -769,6 +769,7 @@ convert_to_integer (tree type, tree expr
>                    (Otherwise would recurse infinitely in convert.  */
>                 if (TYPE_PRECISION (typex) != inprec)
>                   {
> +                   tree otypex = typex;
>                     /* Don't do unsigned arithmetic where signed was wanted,
>                        or vice versa.
>                        Exception: if both of the original operands were
> @@ -806,10 +807,11 @@ convert_to_integer (tree type, tree expr
>                       typex = unsigned_type_for (typex);
>                     else
>                       typex = signed_type_for (typex);
> -                   return convert (type,
> -                                   fold_build2 (ex_form, typex,
> -                                                convert (typex, arg0),
> -                                                convert (typex, arg1)));
> +                   if (TYPE_PRECISION (otypex) == TYPE_PRECISION (typex))
> +                     return convert (type,
> +                                     fold_build2 (ex_form, typex,
> +                                                  convert (typex, arg0),
> +                                                  convert (typex, arg1)));
>                   }
>               }
>           }

Thanks for the patch.

I bootstrapped and regression-tested on i686-pc-linux-gnu.

If it's ok with you I'd go ahead and install it.

And maybe Peter could tell if it also fixes the issue on his platform.

Johann

Re: locating unsigned type for non-standard precision

by Richard Guenther-2 :: Rate this Message:

| View Threaded | Show Only this Message

On Fri, Apr 27, 2012 at 11:29 AM, Georg-Johann Lay <avr@...> wrote:

> Richard Guenther wrote:
>> [PR c/51527]
>>
>> I think the fix would be sth like
>>
>> Index: gcc/convert.c
>> ===================================================================
>> --- gcc/convert.c       (revision 186871)
>> +++ gcc/convert.c       (working copy)
>> @@ -769,6 +769,7 @@ convert_to_integer (tree type, tree expr
>>                    (Otherwise would recurse infinitely in convert.  */
>>                 if (TYPE_PRECISION (typex) != inprec)
>>                   {
>> +                   tree otypex = typex;
>>                     /* Don't do unsigned arithmetic where signed was wanted,
>>                        or vice versa.
>>                        Exception: if both of the original operands were
>> @@ -806,10 +807,11 @@ convert_to_integer (tree type, tree expr
>>                       typex = unsigned_type_for (typex);
>>                     else
>>                       typex = signed_type_for (typex);
>> -                   return convert (type,
>> -                                   fold_build2 (ex_form, typex,
>> -                                                convert (typex, arg0),
>> -                                                convert (typex, arg1)));
>> +                   if (TYPE_PRECISION (otypex) == TYPE_PRECISION (typex))
>> +                     return convert (type,
>> +                                     fold_build2 (ex_form, typex,
>> +                                                  convert (typex, arg0),
>> +                                                  convert (typex, arg1)));
>>                   }
>>               }
>>           }
>
> Thanks for the patch.
>
> I bootstrapped and regression-tested on i686-pc-linux-gnu.
>
> If it's ok with you I'd go ahead and install it.
>
> And maybe Peter could tell if it also fixes the issue on his platform.

It's not necessary on the trunk btw, but it's ok for the 4.7 branch.

Thanks,
Richard.

> Johann

Re: locating unsigned type for non-standard precision

by Peter Bigot-4 :: Rate this Message:

| View Threaded | Show Only this Message

On Fri, Apr 27, 2012 at 4:29 AM, Georg-Johann Lay <avr@...> wrote:

> Richard Guenther wrote:
>> [PR c/51527]
>>
>> I think the fix would be sth like
>>
>> Index: gcc/convert.c
>> ===================================================================
>> --- gcc/convert.c       (revision 186871)
>> +++ gcc/convert.c       (working copy)
>> @@ -769,6 +769,7 @@ convert_to_integer (tree type, tree expr
>>                    (Otherwise would recurse infinitely in convert.  */
>>                 if (TYPE_PRECISION (typex) != inprec)
>>                   {
>> +                   tree otypex = typex;
>>                     /* Don't do unsigned arithmetic where signed was wanted,
>>                        or vice versa.
>>                        Exception: if both of the original operands were
>> @@ -806,10 +807,11 @@ convert_to_integer (tree type, tree expr
>>                       typex = unsigned_type_for (typex);
>>                     else
>>                       typex = signed_type_for (typex);
>> -                   return convert (type,
>> -                                   fold_build2 (ex_form, typex,
>> -                                                convert (typex, arg0),
>> -                                                convert (typex, arg1)));
>> +                   if (TYPE_PRECISION (otypex) == TYPE_PRECISION (typex))
>> +                     return convert (type,
>> +                                     fold_build2 (ex_form, typex,
>> +                                                  convert (typex, arg0),
>> +                                                  convert (typex, arg1)));
>>                   }
>>               }
>>           }
>
> Thanks for the patch.
>
> I bootstrapped and regression-tested on i686-pc-linux-gnu.
>
> If it's ok with you I'd go ahead and install it.
>
> And maybe Peter could tell if it also fixes the issue on his platform.

It does (though so did moving the original test down past the last
change to typex).

I've switched mspgcc to use the version you committed.

Peter

>
> Johann