|
View:
New views
13 Messages
—
Rating Filter:
Alert me
|
|
|
locating unsigned type for non-standard precisionI'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 precisionOn 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 precisionOn 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 precisionRichard 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 precisionOn 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 precisionRichard 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 precisionGeorg-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 precisionOn 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 precisionRichard 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 precisionOn 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 precisionRichard 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 precisionOn 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 precisionOn 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 |
| Free embeddable forum powered by Nabble | Forum Help |