From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3036 invoked by alias); 30 Nov 2012 09:56:19 -0000 Received: (qmail 2969 invoked by uid 48); 30 Nov 2012 09:56:03 -0000 From: "jakub at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug regression/55451] [4.8 regression] FAIL: gcc.dg/fixed-point/unary.c Date: Fri, 30 Nov 2012 09:56:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: regression X-Bugzilla-Keywords: wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: jakub at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated Content-Type: text/plain; charset="UTF-8" MIME-Version: 1.0 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2012-11/txt/msg02975.txt.bz2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55451 --- Comment #2 from Jakub Jelinek 2012-11-30 09:56:02 UTC --- I can't reproduce it with a cross-compiler, for me it optimizes into : _2 = VIEW_CONVERT_EXPR(a_5(D)); if (_2 == -2147483648) goto ; else goto ; : z_3 = -_2; : # z_6 = PHI <2147483647(2), z_3(3)> _4 = VIEW_CONVERT_EXPR(z_6); return _4; but perhaps it is related to HWI size. That said, the bug is clearly on the fixed-point.c side: SQtype c; SItype x, y, z; memcpy (&y, &a, 4); x = 0; z = x - y; if (((x ^ y) >> (31 + 0)) & 1) { if (((z ^ x) >> (31 + 0)) & 1) { z = 1; z = z << (31 + 0); if (x >= 0) z--; } } memcpy (&c, &z, 4); return c; If this routine is called with bits 0x80000000, then z = x - y; triggers undefined signed overflow, and afterwards testing (very weirdo very fancy way) for the most negative value (which is the only one that triggers undefined signed overflow) is already way too late. Note there is another undefined signed overflow later on, z-- where z was previously the most negative signed integer. So, completely untested: --- libgcc/fixed-bit.c 2011-11-04 07:49:37.000000000 +0100 +++ libgcc/fixed-bit.c 2012-11-30 10:52:45.559780132 +0100 @@ -569,16 +569,11 @@ FIXED_SSNEG (FIXED_C_TYPE a) INT_C_TYPE x, y, z; memcpy (&y, &a, FIXED_SIZE); x = 0; - z = x - y; + z = x - (UINT_C_TYPE) y; if (((x ^ y) >> I_F_BITS) & 1) { if (((z ^ x) >> I_F_BITS) & 1) - { - z = 1; - z = z << I_F_BITS; - if (x >= 0) - z--; - } + z = (((UINT_C_TYPE) 1) << I_F_BITS) - 1; } #if HAVE_PADDING_BITS z = z << PADDING_BITS; could fix those two undefined behaviors. That said, the existence of the x variable which is set to 0, then xored with various things and tested if it is >= 0, seems very nonsensical obfuscation to me. Why not drop x altogether, and just use z = - (UINT_C_TYPE) y; and y >> I_F_BITS resp. z >> I_F_BITS?