From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by sourceware.org (Postfix) with ESMTP id AF6AA3861034 for ; Thu, 3 Sep 2020 18:25:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org AF6AA3861034 Received: from mail-qt1-f200.google.com (mail-qt1-f200.google.com [209.85.160.200]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-342-CQyAePA5N_iFCEtSC0fdpw-1; Thu, 03 Sep 2020 14:25:25 -0400 X-MC-Unique: CQyAePA5N_iFCEtSC0fdpw-1 Received: by mail-qt1-f200.google.com with SMTP id g1so2669250qtc.22 for ; Thu, 03 Sep 2020 11:25:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=LEP0VpBZRahzti2dud3Tas+1bSqwpDZbhA/ZNyUwNkc=; b=NQDSrN3EcCK7TdIkYkmhhbDGiRLiZi5xF7Ef2qsJhXok25sY8wkaAeWasOZowYyaGt 7NLaS2Q32Om2B3gal+nynUmQuqAphxJIGuYOgQR268tPZ364UWNPJ452dDVWn+S7e9/Q TIyXpX1q0cxrDo4XytKKyD3UYczYgwmQT6WynVNm2BfZeFu11ukQ4bZHNuZBLG7zBGrY UZJ/FkaHzqW3UwSELLRPCaxh2iKySNglU72uUhmuK9Nny17IEDmpIYfjGsjfudkxea0N NUN9Hsm+qwuJUDX12zDYRd/a99bhTVsGD1p/Br5n/A7UWpPwrNBWRrnMps13xQreeNVK XmPA== X-Gm-Message-State: AOAM532WA2p/mje9WbevN3ozGT7yiUuFbqDZM1ZTdCPUJwr4G5H3Qx5c UpONTGyIyiqCTkhCKoyOr8LPKc0L7Y8NIiXg44fieWUpu9D5FdwoT+VpORw5a0PMDXS6olsRGLc R2/iuQeC4z7Fw8bP1nA== X-Received: by 2002:a37:7c2:: with SMTP id 185mr4176586qkh.304.1599157524563; Thu, 03 Sep 2020 11:25:24 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyMrXRMvQxC0uz9LMq8URuSt1ALsVw5+2Ndx83rPe5QE55A7l9X1P4VT6q6I2y6m+8cKa2F0w== X-Received: by 2002:a37:7c2:: with SMTP id 185mr4176554qkh.304.1599157524095; Thu, 03 Sep 2020 11:25:24 -0700 (PDT) Received: from [192.168.1.148] (209-6-216-142.s141.c3-0.smr-cbr1.sbo-smr.ma.cable.rcncustomer.com. [209.6.216.142]) by smtp.gmail.com with ESMTPSA id k185sm2692540qkd.94.2020.09.03.11.25.23 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 03 Sep 2020 11:25:23 -0700 (PDT) Subject: Re: [PATCH] c++: Disable -frounding-math during manifestly constant evaluation [PR96862] To: gcc-patches@gcc.gnu.org Cc: Jakub Jelinek References: <20200901074946.GV18149@tucnak> From: Jason Merrill Message-ID: Date: Thu, 3 Sep 2020 14:25:22 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.6.0 MIME-Version: 1.0 In-Reply-To: X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=iso-8859-15; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, BODY_8BITS, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Sep 2020 18:25:32 -0000 On 9/2/20 6:43 PM, Marc Glisse wrote: > On Wed, 2 Sep 2020, Jason Merrill via Gcc-patches wrote: > >> On 9/1/20 6:13 AM, Marc Glisse wrote: >>> On Tue, 1 Sep 2020, Jakub Jelinek via Gcc-patches wrote: >>> >>>> As discussed in the PR, fold-const.c punts on floating point constant >>>> evaluation if the result is inexact and -frounding-math is turned on. >>>>      /* Don't constant fold this floating point >>>> operation if the >>>>         result may dependent upon the run-time >>>> rounding mode and >>>>         flag_rounding_math is set, or if GCC's >>>> software emulation >>>>         is unable to accurately represent the >>>> result.  */ >>>>      if ((flag_rounding_math >>>>           || (MODE_COMPOSITE_P (mode) && >>>> !flag_unsafe_math_optimizations)) >>>>          && (inexact || !real_identical >>>> (&result, &value))) >>>>        return NULL_TREE; >>>> Jonathan said that we should be evaluating them anyway, e.g. >>>> conceptually >>>> as if they are done with the default rounding mode before user had a >>>> chance >>>> to change that, and e.g. in C in initializers it is also ignored. >>>> In fact, fold-const.c for C initializers turns off various other >>>> options: >>>> >>>> /* Perform constant folding and related simplification of initializer >>>>   expression EXPR.  These behave identically to "fold_buildN" >>>> but ignore >>>>   potential run-time traps and exceptions that fold must >>>> preserve.  */ >>>> >>>> #define START_FOLD_INIT \ >>>>  int saved_signaling_nans = flag_signaling_nans;\ >>>>  int saved_trapping_math = flag_trapping_math;\ >>>>  int saved_rounding_math = flag_rounding_math;\ >>>>  int saved_trapv = flag_trapv;\ >>>>  int saved_folding_initializer = folding_initializer;\ >>>>  flag_signaling_nans = 0;\ >>>>  flag_trapping_math = 0;\ >>>>  flag_rounding_math = 0;\ >>>>  flag_trapv = 0;\ >>>>  folding_initializer = 1; >>>> >>>> #define END_FOLD_INIT \ >>>>  flag_signaling_nans = saved_signaling_nans;\ >>>>  flag_trapping_math = saved_trapping_math;\ >>>>  flag_rounding_math = saved_rounding_math;\ >>>>  flag_trapv = saved_trapv;\ >>>>  folding_initializer = saved_folding_initializer; >>>> >>>> So, shall cxx_eval_outermost_constant_expr instead turn off all those >>>> options (then warning_sentinel wouldn't be the right thing to use, >>>> but given >>>> the 8 or how many return stmts in cxx_eval_outermost_constant_expr, >>>> we'd >>>> need a RAII class for this.  Not sure about the >>>> folding_initializer, that >>>> one is affecting complex multiplication and division constant >>>> evaluation >>>> somehow. >>> >>> I don't think we need to turn off flag_signaling_nans or flag_trapv. >>> I think we want to turn off flag_trapping_math so we can fold 1./0 to >>> inf (still in a context where folding is mandatory). Setting >>> folding_initializer seems consistent with that, enabling infinite >>> results in complex folding (it also forces folding of >>> __builtin_constant_p, which may be redundant with >>> force_folding_builtin_constant_p). >> >> C++ says that division by zero has undefined behavior, and that an >> expression with undefined behavior is not constant, so we shouldn't >> fold 1./0 to inf anyway.  The same is true of other trapping >> operations.  So clearing flag_signaling_nans, flag_trapping_math, and >> flag_trapv seems wrong for C++. And folding_initializer seems to be >> used for the same sort of thing. > > So we should actually force flag_trapping_math to true during constexpr > evaluation? And folding_initializer to false, and never mind trapv but > maybe disable wrapv? > > #include > constexpr double a = std::numeric_limits::infinity(); > constexpr double b = a + a; > constexpr double c = a - a; > constexpr double d = 1. / a; > constexpr double e = 1. / d; > > clang rejects c and e. MSVC rejects e. Intel warns on c. > > Gcc rejects only e, and accepts the whole thing if I pass > -fno-trapping-math. At the November 2016 C++ meeting the numerics study group (SG6) said about core issue 2168, "arithmetic operations (not conversions) that produce infinity are not allowed in a constant expression. Just using std::numeric_limits::infinity() is ok, but you can't add 0 to it." But the issue is still open. Some later discussion disputes that this is the right choice, but there were voices on both sides and the discussion didn't come to a conclusion. https://lists.isocpp.org/core/2018/02/3974.php It seems that clang used to reject expressions that produced infinities (as per SG6 above), but that was changed last year to treat the range of floating point types as including infinity, so that a floating point operation is never considered overflowing. https://reviews.llvm.org/D63793 C11 says, "The minimum range of representable values for a floating type is the most negative finite floating-point number representable in that type through the most positive finite floating-point number representable in that type. In addition, if negative infinity is representable in a type, the range of that type is extended to all negative real numbers; likewise, if positive infinity is representable in a type, the range of that type is extended to all positive real numbers." The clang change seems consistent with C11. And given that C++ inherits from C11, it would make sense to adopt the associated floating point model as well. > Almost any FP operation is possibly trapping, 1./3. sets FE_INEXACT just > as 1./0. sets FE_DIVBYZERO. But the standard says > > char array[1 + int(1 + 0.2 - 0.1 - 0.1)]; // Must be evaluated during > translation > > So it doesn't seem like it cares about that? Division by zero is the > only one that gets weirdly special-cased... Yes, division by zero is still explicitly undefined behavior ("If the second operand of / or % is zero the behavior is undefined."). So I guess cxx_eval_binary_expression should check this before calling fold_binary_loc. I suspect that the unfortunate thing here is that constexpr generally declared undefined behavior to mean non-constant, and we didn't notice that this use of "undefined behavior" needed to be changed to accommodate implementations that gave it well-defined behavior. Hopefully CWG/SG6 discussion now will be more fruitful. Jason