From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28246 invoked by alias); 5 Oct 2011 20:28:44 -0000 Received: (qmail 28235 invoked by uid 22791); 5 Oct 2011 20:28:42 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,T_TO_NO_BRKTS_FREEMAIL 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; Wed, 05 Oct 2011 20:28:21 +0000 Received: by wwf10 with SMTP id 10so2747870wwf.8 for ; Wed, 05 Oct 2011 13:28:19 -0700 (PDT) MIME-Version: 1.0 Received: by 10.227.8.213 with SMTP id i21mr3607534wbi.80.1317846499735; Wed, 05 Oct 2011 13:28:19 -0700 (PDT) Received: by 10.180.106.100 with HTTP; Wed, 5 Oct 2011 13:28:19 -0700 (PDT) In-Reply-To: References: Date: Thu, 06 Oct 2011 08:25:00 -0000 Message-ID: Subject: Re: Option to make unsigned->signed conversion always well-defined? From: Ulf Magnusson To: gcc@gcc.gnu.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable 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/msg00080.txt.bz2 On Wed, Oct 5, 2011 at 10:11 PM, Ulf Magnusson wrote: > Hi, > > 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) { > =A0 =A0const unsigned int sum =3D (int8_t)a + (int8_t)b; > =A0 =A0return (int8_t)sum !=3D 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. > > /Ulf > Is *((int8_t*)&sum) safe (assuming little endian)? Unfortunately that seems to generate worse code. On X86 it generates the following (GCC 4.5.2): 00000050 <_Z9overflow4jj>: 50: 83 ec 10 sub $0x10,%esp 53: 0f be 54 24 18 movsbl 0x18(%esp),%edx 58: 0f be 44 24 14 movsbl 0x14(%esp),%eax 5d: 8d 04 02 lea (%edx,%eax,1),%eax 60: 0f be d0 movsbl %al,%edx 63: 39 d0 cmp %edx,%eax 65: 0f 95 c0 setne %al 68: 83 c4 10 add $0x10,%esp 6b: c3 ret With the straight (int8_t) cast you get 50: 0f be 54 24 08 movsbl 0x8(%esp),%edx 55: 0f be 44 24 04 movsbl 0x4(%esp),%eax 5a: 8d 04 02 lea (%edx,%eax,1),%eax 5d: 0f be d0 movsbl %al,%edx 60: 39 c2 cmp %eax,%edx 62: 0f 95 c0 setne %al 65: c3 ret What's with the extra add/sub of ESP? /Ulf