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

*From*: Ulf Magnusson <ulfalizer at gmail dot com>*To*: Florian Weimer <fw at deneb dot enyo dot de>*Cc*: gcc at gcc dot gnu dot org*Date*: Fri, 7 Oct 2011 19:20:15 +0200*Subject*: Re: Option to make unsigned->signed conversion always well-defined?*References*: <CAFkk2KSn2Us=W2ER396pA+cbgW1HaTJWb-mLPiJVv4Xk0QJYuA@mail.gmail.com> <87sjn5g638.fsf@mid.deneb.enyo.de>

On Thu, Oct 6, 2011 at 11:31 PM, Florian Weimer <fw@deneb.enyo.de> wrote: > * Ulf Magnusson: > >> I've been experimenting with different methods for emulating the >> signed overflow of an 8-bit CPU. The method I've found that seems to >> generate the most efficient code on both ARM and x86 is >> >> bool overflow(unsigned int a, unsigned int b) { >> ? ? const unsigned int sum = (int8_t)a + (int8_t)b; >> ? ? return (int8_t)sum != sum; >> } > > There's a GCC extension which is relevant here: > > | For conversion to a type of width N, the value is reduced modulo 2^N > | to be within range of the type; no signal is raised. > > <http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html#Integers-implementation> > > Using that, you can replace the final "& 0x80" with a signed > comparison to zero, which should be give you the best possible code > (for the generic RISC). ?You only need to hunt down a copy of Hacker's > Delight or find the right bit twiddling by other means. 8-) > Are you thinking of something like this? bool overflow_bit2(unsigned int a, unsigned int b) { const unsigned int ashift = a << 24; const unsigned int bshift = b << 24; const unsigned int sum = a + b; return (int)(~(a ^ b) & (a ^ sum)) < 0; } That version generates 80: 180b adds r3, r1, r0 82: 4041 eors r1, r0 84: ea83 0200 eor.w r2, r3, r0 88: ea22 0001 bic.w r0, r2, r1 8c: 0fc0 lsrs r0, r0, #31 8e: 4770 bx lr Whereas the unshifted version generates 40: 180b adds r3, r1, r0 42: 4041 eors r1, r0 44: ea83 0200 eor.w r2, r3, r0 48: ea22 0001 bic.w r0, r2, r1 4c: f3c0 10c0 ubfx r0, r0, #7, #1 50: 4770 bx lr So maybe a bit better. (I'm no ARM pro, but the compiler does seem to take advantage of the fact that it's testing the real sign bit at least.) Btw, & 0x80000000 generates the same code. /Ulf

**Follow-Ups**:**Re: Option to make unsigned->signed conversion always well-defined?***From:*Florian Weimer

**References**:**Option to make unsigned->signed conversion always well-defined?***From:*Ulf Magnusson

**Re: Option to make unsigned->signed conversion always well-defined?***From:*Florian Weimer

Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|

Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |