Message ID | alpine.LSU.2.11.1412020949490.5894@zhemvz.fhfr.qr |
---|---|
State | New |
Headers | show |
On Tue, 2 Dec 2014, Richard Biener wrote: > > I'm not sure if these forms of division actually occur in places where > > this could cause a problem, but it does look like Ada may enable you to > > generate ROUND_DIV_EXPR. > > Hmm. I thought I was following what extract_muldiv_1 does (but of course > that function is quite hard to follow). I don't claim existing optimizations are correct for all these forms of division. In fact even wide-int doesn't handle ROUND_DIV_EXPR correctly (round to nearest, ties away from 0) - at a glance, without testing, ROUND_MOD_EXPR has the same bug (wi::ges_p (wi::abs (remainder), wi::lrshift (wi::abs (y), 1)) is not the right condition for rounding away). The following Ada testcase test_round_div.adb will generate a ROUND_DIV_EXPR which is executed correctly at -O0, but fails at -O3. (The separate division function seems necessary to stop the front end from doing its own constant folding, though there may for all I know be more idiomatic Ada ways of doing that.) procedure Test_Round_Div is type Fixed is delta 1.0 range -2147483648.0 .. 2147483647.0; A : Fixed := 1.0; B : Fixed := 3.0; C : Integer; function Divide (X, Y : Fixed) return Integer is begin return Integer (X / Y); end; begin C := Divide (A, B); if C /= 0 then raise Program_Error; end if; end Test_Round_Div;
On Tue, 2 Dec 2014, Joseph Myers wrote: > (y), 1)) is not the right condition for rounding away). The following Ada > testcase test_round_div.adb will generate a ROUND_DIV_EXPR which is I should add that I'm not sure if Ada requires correct rounding for fixed-point division converted to integer like this, or, if not, whether GNU Ada nevertheless guarantees it; it's simply a case that does generate such a ROUND_DIV_EXPR and so can be used to test how ROUND_DIV_EXPR behaves (in the absence of built-in functions).
Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 218258) +++ gcc/match.pd (working copy) @@ -129,8 +129,9 @@ (define_operator_list inverted_tcc_compa && TYPE_UNSIGNED (type)) (trunc_div @0 @1))) -/* Combine two successive divisions. */ -(for div (trunc_div ceil_div floor_div round_div exact_div) +/* Combine two successive divisions. Note that combining ceil_div + and floor_div is trickier and combining round_div even more so. */ +(for div (trunc_div exact_div) (simplify (div (div @0 INTEGER_CST@1) INTEGER_CST@2) (with {