From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19542 invoked by alias); 14 May 2014 11:38:53 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 19524 invoked by uid 89); 14 May 2014 11:38:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.8 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 14 May 2014 11:38:51 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s4EBcloK013812 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 14 May 2014 07:38:47 -0400 Received: from tucnak.zalov.cz (ovpn-116-116.ams2.redhat.com [10.36.116.116]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s4EBcho1000441 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 14 May 2014 07:38:46 -0400 Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.14.8/8.14.7) with ESMTP id s4EBcfHx018382; Wed, 14 May 2014 13:38:42 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.14.8/8.14.8/Submit) id s4EBcdGQ018381; Wed, 14 May 2014 13:38:39 +0200 Date: Wed, 14 May 2014 11:38:00 -0000 From: Jakub Jelinek To: "Joseph S. Myers" Cc: Marek Polacek , GCC Patches Subject: Re: [PATCH] Implement -fsanitize=float-cast-overflow Message-ID: <20140514113839.GE10386@tucnak.redhat.com> Reply-To: Jakub Jelinek References: <20140513170801.GG2663@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes X-SW-Source: 2014-05/txt/msg01077.txt.bz2 On Tue, May 13, 2014 at 06:11:15PM +0000, Joseph S. Myers wrote: > > + tree min = TYPE_MIN_VALUE (type); > > + tree max = TYPE_MAX_VALUE (type); > > + /* Add/subtract 1.0 so we can avoid truncating the value of EXPR. */ > > + min = fold_build2 (MINUS_EXPR, expr_type, > > + build_real_from_int_cst (expr_type, min), > > + build_one_cst (expr_type)); > > + max = fold_build2 (PLUS_EXPR, expr_type, > > + build_real_from_int_cst (expr_type, max), > > + build_one_cst (expr_type)); > > It looks to me like this will first round the max value to the > floating-point type, then add 1 to the rounded value and round again. > Which I think is in fact safe at least for IEEE binary floating-point > types, but that isn't immediately obvious. > > Possible issues: > > * Does the folding of the addition occur in all cases for IBM long double? > > * Is this correct for decimal floating point? There, the overflow > condition (value >= max+1) should be using a value of (max+1) rounded > upward rather than to-nearest, if max+1 isn't exactly representable (and > in general it isn't - powers of two 0x1p24 and above aren't representable > in decimal32, 0x1p54 and above in decimal64, 0x1p113 and above in > decimal128, so you just need to find a case where the double-rounding > computation you have produces the wrong value). > > * Likewise, (value <= min-1) for both binary and decimal floating point - > you need to round once, away from 0. For float converted to signed int, > the relevant condition is values < -0x1p31 - 1, i.e. <= 0x1.000002p31f > once you allow for which values are representable as float, which is not > min-1 (min-1 rounds to -0x1p31, but a conversion of that to signed int is > fully defined with no exceptions). So what do you see as the way to handle this properly? I mean, for REAL_MODE_FORMAT (TYPE_MODE (expr_type))->b == 2 supposedly to avoid issues with rounding of the max we could just REAL_VALUE_TYPE maxval = dconst1; SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + TYPE_PRECISION (type) - !TYPE_UNSIGNED (type)); real_convert (&maxval, TYPE_MODE (expr_type), &maxval); max = build_real (expr_type, maxval); or so, then supposedly max is always the smallest representable binary floating point value above or equal to TYPE_MAX_VALUE + 1.0. For the min value, if it is unsigned, then -1.0 is ok for all binary or decimal floats, if it is signed, then supposedly we could do the above with s/max/min/;s/dconst1/dconstm1/; and, after the real_convert do inexact = real_arithmetic (&newminval, MINUS_EXPR, &minval, &dconst1); if !inexact just min = build_real (expr_type, newminval); and be done with it (the question is if for IBM double double this will DTRT for LONG_LONG_MIN, which I think should be that the high double will contain (double) LONG_LONG_MIN and the low double -1.0). For inexact (which should be the same thing as if result of real_arithmetic + real_convert is the same as original minval) we need to subtract more than one, dunno if we should just compute it from the REAL_EXP and precision, or just keep subtracing powers of two until after real_convert it is no longer bitwise identical to original minval. We don't have anything close to real_nextafter nor real_convert variant that can round for arbitrary rounding modes. Any preferences how to implement this? For _Decimal*, no idea unfortunately, perhaps for the first iteration ubsan should ignore decimal to int conversions. Jakub