From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16100 invoked by alias); 6 Oct 2011 08:25:40 -0000 Received: (qmail 16088 invoked by uid 22791); 6 Oct 2011 08:25:38 -0000 X-SWARE-Spam-Status: No, hits=-2.5 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail-ww0-f51.google.com (HELO mail-ww0-f51.google.com) (74.125.82.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 06 Oct 2011 08:25:22 +0000 Received: by wwf10 with SMTP id 10so3304512wwf.8 for ; Thu, 06 Oct 2011 01:25:20 -0700 (PDT) MIME-Version: 1.0 Received: by 10.216.189.30 with SMTP id b30mr755828wen.80.1317889520793; Thu, 06 Oct 2011 01:25:20 -0700 (PDT) Received: by 10.180.106.100 with HTTP; Thu, 6 Oct 2011 01:25:20 -0700 (PDT) In-Reply-To: <4E8CE072.8010109@gmail.com> References: <4E8CE072.8010109@gmail.com> Date: Thu, 06 Oct 2011 10:52:00 -0000 Message-ID: Subject: Re: Option to make unsigned->signed conversion always well-defined? From: Ulf Magnusson To: Pedro Pedruzzi Cc: gcc@gcc.gnu.org Content-Type: text/plain; charset=ISO-8859-1 X-IsSubscribed: yes Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org X-SW-Source: 2011-10/txt/msg00083.txt.bz2 On Thu, Oct 6, 2011 at 12:55 AM, Pedro Pedruzzi wrote: > Em 05-10-2011 17:11, Ulf Magnusson escreveu: >> Hi, >> >> I've been experimenting with different methods for emulating the >> signed overflow of an 8-bit CPU. > > You would like to check whether a 8-bit signed addition will overflow or > not, given the two operands. Is that correct? > > As you used the word `emulating', I am assuming that your function will > not run by the mentioned CPU. > No, it'll most likely only run on systems with a wider bitness. > Does this 8-bit CPU use two's complement representation? Yes, and the criterion for signed overflow is "both numbers have the same sign, but the sign of the sum is different". Should have made that more clear. > >> 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; >> } >> >> (The real function would probably be 'inline', of course. Regs are >> stored in overlong variables, hence 'unsigned int'.) >> >> Looking at the spec, it unfortunately seems the behavior of this >> function is undefined, as it relies on signed int addition wrapping, >> and that (int8_t)sum truncates bits. Is there some way to make this >> guaranteed safe with GCC without resorting to inline asm? Locally >> enabling -fwrap takes care of the addition, but that still leaves the >> conversion. > > I believe the cast from unsigned int to int8_t is implementation-defined > for values that can't be represented in int8_t (e.g. 0xff). A kind of > `undefined behavior' as well. > > I tried: > > bool overflow(unsigned int a, unsigned int b) { > const unsigned int sum = a + b; > return ((a & 0x80) == (b & 0x80)) && ((a & 0x80) != (sum & 0x80)); > } > > But it is not as efficient as yours. > > -- > Pedro Pedruzzi > Yeah, I tried similar bit-trickery along the lines of bool overflow(unsigned int a, unsigned int b) { const uint8_t ab = (uint8_t)a; const uint8_t bb = (uint8_t)b; const uint8_t sum = ab + bb; return (ab ^ bb) & ~(ab ^ sum) & 0x80; } , but it doesn't seem to generate very efficient code. /Ulf