From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 9EBD3385843E; Wed, 6 Apr 2022 09:46:28 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9EBD3385843E From: "jakub at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug tree-optimization/24021] VRP does not work with floating points Date: Wed, 06 Apr 2022 09:46:27 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: tree-optimization X-Bugzilla-Version: 4.1.0 X-Bugzilla-Keywords: missed-optimization X-Bugzilla-Severity: enhancement X-Bugzilla-Who: jakub at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: aldyh at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 06 Apr 2022 09:46:28 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D24021 --- Comment #21 from Jakub Jelinek --- (In reply to Aldy Hernandez from comment #20) > (In reply to Andrew Macleod from comment #19) > > We can use the original testcase as the litmus test for basic support i= f we > > compile it with > >=20 > > -O2 -fno-tree-fre -fno-tree-dominator-opts > >=20 > > The unroller will unroll the loop and the VRP2 pass will be presented w= ith: > >=20 > > [local count: 97603129]: > > i_1 =3D 1.1000000149011611438876201418679556809365749359130859375e-1; > > i_17 =3D i_1 + 1.00000001490116119384765625e-1; > > i_22 =3D i_17 + 1.00000001490116119384765625e-1; > > i_27 =3D i_22 + 1.00000001490116119384765625e-1; > > i_32 =3D i_27 + 1.00000001490116119384765625e-1; > > i_37 =3D i_32 + 1.00000001490116119384765625e-1; > > i_42 =3D i_37 + 1.00000001490116119384765625e-1; > > i_47 =3D i_42 + 1.00000001490116119384765625e-1; > > i_52 =3D i_47 + 1.00000001490116119384765625e-1; > > if (i_52 =3D=3D 0.0) > > goto ; [50.00%] > > else > > goto ; [50.00%] > >=20 > > [local count: 48801565]: > >=20 > > [local count: 97603129]: > > # lastPoint_12 =3D PHI > > return lastPoint_12; > >=20 > > Which is we can track floating point ranges in VRP and simplification, > > recognize that i_52 !=3D 0.0 and VRP2 should be able to resolve this to= =20 > >=20 > > return 2.0e+0; >=20 > We can definitely get this with the current work. All that's missing is = the > snippet implementing the PLUS_EXPR operator. A simple implementation (wi= th > likely the NAN bits wrong :)) follows: >=20 > diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc > index d1c7a3b571b..cba7166ad2b 100644 > --- a/gcc/range-op-float.cc > +++ b/gcc/range-op-float.cc > @@ -1055,6 +1055,54 @@ foperator_mult::fold_range (frange &r, tree type, > return true; > } >=20=20 > +class foperator_plus : public range_operator > +{ > + using range_operator::fold_range; > +public: > + virtual bool fold_range (frange &r, tree type, > + const frange &lh, > + const frange &rh, > + relation_kind rel =3D VREL_NONE) const override; > +} fop_plus; > + > +bool > +foperator_plus::fold_range (frange &r, tree type, > + const frange &lh, > + const frange &rh, > + relation_kind) const > +{ > + if (empty_range_varying (r, type, lh, rh)) > + return true; > + > + if (lh.get_prop (FRANGE_PROP_NAN) > + || rh.get_prop (FRANGE_PROP_NAN)) > + { > + r.set_varying (type); > + return true; > + } > + > + enum tree_code code_lb, code_ub; > + tree lh_lb =3D lh.lower_bound (&code_lb); > + tree lh_ub =3D lh.upper_bound (&code_ub); > + tree rh_lb =3D rh.lower_bound (); > + tree rh_ub =3D rh.upper_bound (); > + > + REAL_VALUE_TYPE res_lb, res_ub; > + real_arithmetic (&res_lb, PLUS_EXPR, > + TREE_REAL_CST_PTR (lh_lb), > + TREE_REAL_CST_PTR (rh_lb)); > + real_arithmetic (&res_ub, PLUS_EXPR, > + TREE_REAL_CST_PTR (lh_ub), > + TREE_REAL_CST_PTR (rh_ub)); > + > + r.set (code_lb, > + build_real (type, res_lb), > + build_real (type, res_ub), > + code_ub); > + return true; > +} This doesn't take flag_rounding_math or not always exactly precise floating point computations into account. It is also missing real_convert after real_arithmetics that performs at lea= st some of the rounding (and perhaps the inexact return value from real_arithm= etic should be taken into account). Without flag_rounding_math and on non-MODE_COMPOSITE_P the basic arithmetics will be probably exact most of the time, except perhaps for denormals which= are sometimes flushed to zero. But as soon as one jumps to even sqrt and other math functions, one needs to allow some epsilon up for upper bound and down= for lower bound, similarly for the basic ops with inexact and flag_rounding_mat= h. For MODE_COMPOSITE_P, our emulation doesn't match what is done at runtime, = so we need to be more forgiving.=