Re: [PATCH] Fix PR15346
On Mon, 1 Dec 2014, Joseph Myers wrote: On Mon, 1 Dec 2014, Richard Biener wrote: +/* Combine two successive divisions. */ +(for div (trunc_div ceil_div floor_div round_div exact_div) This doesn't seem correct for all kinds of division and signedness of arguments. TRUNC_DIV_EXPR (C division) and EXACT_DIV_EXPR should be OK regardless. But for CEIL_DIV_EXPR and FLOOR_DIV_EXPR, in ((a / b) / c) you need c to be positive so that both roundings are in the same direction (consider e.g. 3 FLOOR_DIV -2 FLOOR_DIV -2 == 1, but 3 FLOOR_DIV 4 == 0). And for ROUND_DIV_EXPR, it can be incorrect whatever the signs (e.g. 2 ROUND_DIV 3 ROUND_DIV 2 == 1, but 2 ROUND_DIV 6 == 0). 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). case TRUNC_DIV_EXPR: case CEIL_DIV_EXPR: case FLOOR_DIV_EXPR: case ROUND_DIV_EXPR: case EXACT_DIV_EXPR: ... /* If these are the same operation types, we can associate them assuming no overflow. */ if (tcode == code) { bool overflow_p = false; bool overflow_mul_p; signop sign = TYPE_SIGN (ctype); wide_int mul = wi::mul (op1, c, sign, overflow_mul_p); overflow_p = TREE_OVERFLOW (c) | TREE_OVERFLOW (op1); if (overflow_mul_p ((sign == UNSIGNED tcode != MULT_EXPR) || sign == SIGNED)) overflow_p = true; if (!overflow_p) return fold_build2 (tcode, ctype, fold_convert (ctype, op0), wide_int_to_tree (ctype, mul)); but yeah, I see you are correct. I'll restrict the pattern to TRUNC_DIV_EXPR and EXACT_DIV_EXPR which are the only ones I've ever seen generated from C. I don't know how to generate testcases for the other division opcodes - eventually we should have builtins just for the sake of being able to generate testcases... Committed as obvoious. Thanks, Richard. 2014-12-02 Richard Biener rguent...@suse.de * match.pd: Restrict division combining to trunc_div and exact_div. 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 {
Re: [PATCH] Fix PR15346
On Mon, 1 Dec 2014, Marc Glisse wrote: On Mon, 1 Dec 2014, Richard Biener wrote: The following fixes the oldest bug in my list of assigned PRs, namely combining A / CST / CST' to A / (CST * CST'). extract_muldiv does this in fold-const.c (but it fails to optimize to zero when CST * CST' overflows). Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2014-12-01 Richard Biener rguent...@suse.de PR tree-optimization/15346 * Makefile.in (gimple-match.o-warn): Remove -Wno-unused-parameter, add -Wno-unused-but-set-variable. * match.pd: Combine two successive divisions. * gcc.dg/tree-ssa/forwprop-32.c: New testcase. Index: gcc/match.pd === --- gcc/match.pd(revision 218140) +++ gcc/match.pd(working copy) @@ -129,6 +129,19 @@ (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) + (simplify + (div (div @0 INTEGER_CST@1) INTEGER_CST@2) + (with { +bool overflow_p; +wide_int mul = wi::mul (@1, @2, TYPE_SIGN (type), overflow_p); + } + (if (!overflow_p) +(div @0 { wide_int_to_tree (type, mul); })) + (if (overflow_p) +{ build_zero_cst (type); } + Can't you have something like: INT_MIN / 2 / (INT_MIN / -2) == -1 where 2 * (INT_MIN / -2) overflows? Hmm, right. It should work if overflow_p mul != INT_MIN as far as I can see. I am testing the following. Thanks, Richard. 2014-12-02 Richard Biener rguent...@suse.de * match.pd: When combining divisions exclude the degenerate case involving INT_MIN from overflow handling. * gcc.dg/torture/20141202-1.c: New testcase. Index: gcc/match.pd === --- gcc/match.pd(revision 218260) +++ gcc/match.pd(working copy) @@ -140,7 +140,9 @@ (define_operator_list inverted_tcc_compa } (if (!overflow_p) (div @0 { wide_int_to_tree (type, mul); })) - (if (overflow_p) + (if (overflow_p + (TYPE_UNSIGNED (type) + || mul != wi::min_value (TYPE_PRECISION (type), SIGNED))) { build_zero_cst (type); } /* Optimize A / A to 1.0 if we don't care about Index: gcc/testsuite/gcc.dg/torture/20141202-1.c === --- gcc/testsuite/gcc.dg/torture/20141202-1.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/20141202-1.c (working copy) @@ -0,0 +1,15 @@ +/* { dg-do run } */ + +extern void abort (void); + +int foo (int x) +{ + return (x / 2) / ((-__INT_MAX__ - 1) / -2); +} + +int main() +{ + if (foo (- __INT_MAX__ - 1) != -1) +abort (); + return 0; +}
Re: [PATCH] Fix PR15346
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; -- Joseph S. Myers jos...@codesourcery.com
Re: [PATCH] Fix PR15346
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). -- Joseph S. Myers jos...@codesourcery.com
[PATCH] Fix PR15346
The following fixes the oldest bug in my list of assigned PRs, namely combining A / CST / CST' to A / (CST * CST'). extract_muldiv does this in fold-const.c (but it fails to optimize to zero when CST * CST' overflows). Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2014-12-01 Richard Biener rguent...@suse.de PR tree-optimization/15346 * Makefile.in (gimple-match.o-warn): Remove -Wno-unused-parameter, add -Wno-unused-but-set-variable. * match.pd: Combine two successive divisions. * gcc.dg/tree-ssa/forwprop-32.c: New testcase. Index: gcc/match.pd === --- gcc/match.pd(revision 218140) +++ gcc/match.pd(working copy) @@ -129,6 +129,19 @@ (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) + (simplify + (div (div @0 INTEGER_CST@1) INTEGER_CST@2) + (with { +bool overflow_p; +wide_int mul = wi::mul (@1, @2, TYPE_SIGN (type), overflow_p); + } + (if (!overflow_p) +(div @0 { wide_int_to_tree (type, mul); })) + (if (overflow_p) +{ build_zero_cst (type); } + /* Optimize A / A to 1.0 if we don't care about NaNs or Infinities. */ (simplify Index: gcc/testsuite/gcc.dg/tree-ssa/forwprop-32.c === --- gcc/testsuite/gcc.dg/tree-ssa/forwprop-32.c (revision 0) +++ gcc/testsuite/gcc.dg/tree-ssa/forwprop-32.c (working copy) @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options -O -fdump-tree-forwprop1 -fdump-tree-ccp1 } */ + +int foo (int x) +{ + int tem = x / 3; + return tem / 5; +} +int bar (int x) +{ + int tem = x / 3; + return tem / (__INT_MAX__ / 2); +} + +/* { dg-final { scan-tree-dump x_.\\(D\\) / 15 forwprop1 } } */ +/* { dg-final { scan-tree-dump return 0; ccp1 } } */ +/* { dg-final { cleanup-tree-dump forwprop1 } } */ +/* { dg-final { cleanup-tree-dump ccp1 } } */ Index: gcc/Makefile.in === --- gcc/Makefile.in (revision 218142) +++ gcc/Makefile.in (working copy) @@ -209,8 +209,8 @@ gengtype-lex.o-warn = -Wno-error libgcov-util.o-warn = -Wno-error libgcov-driver-tool.o-warn = -Wno-error libgcov-merge-tool.o-warn = -Wno-error -gimple-match.o-warn = -Wno-unused-variable -Wno-unused-parameter -generic-match.o-warn = -Wno-unused-variable -Wno-unused-parameter +gimple-match.o-warn = -Wno-unused-variable -Wno-unused-but-set-variable +generic-match.o-warn = -Wno-unused-variable -Wno-unused-but-set-variable # All warnings have to be shut off in stage1 if the compiler used then # isn't gcc; configure determines that. WARN_CFLAGS will be either
Re: [PATCH] Fix PR15346
Richard Biener wrote: * Makefile.in (gimple-match.o-warn): Remove -Wno-unused-parameter, add -Wno-unused-but-set-variable. This seems to cause cc1plus: error: unrecognized command line option -Wno-unused-but-set-variable make[3]: *** [gimple-match.o] Error 1 in stage1 when bootstrapping on SLES 11 (gcc 4.3.4 host compiler). Bye, Ulrich -- Dr. Ulrich Weigand GNU/Linux compilers and toolchain ulrich.weig...@de.ibm.com
Re: [PATCH] Fix PR15346
On Mon, 1 Dec 2014, Ulrich Weigand wrote: Richard Biener wrote: * Makefile.in (gimple-match.o-warn): Remove -Wno-unused-parameter, add -Wno-unused-but-set-variable. This seems to cause cc1plus: error: unrecognized command line option -Wno-unused-but-set-variable make[3]: *** [gimple-match.o] Error 1 in stage1 when bootstrapping on SLES 11 (gcc 4.3.4 host compiler). Oh. Hmm, so I guess build/gengtype-lex.o-warn = -Wno-error gengtype-lex.o-warn = -Wno-error and friends are also incorrect for host compilers that do not know -Wno-error? Which means we need configure checks and substitutes for all -Wno-X we use. 4.3 has -Wunused so I can just replace -Wno-unused-variable -Wno-unused-but-set-variable with -Wno-unused as a quick fix for you. Will do that now (I didn't want to use -Wno-error because that makes the compile quite uselessly verbose and fails to diagnose real issues). Thanks for the report, Richard.
Re: [PATCH] Fix PR15346
On Mon, Dec 01, 2014 at 04:10:35PM +0100, Richard Biener wrote: On Mon, 1 Dec 2014, Ulrich Weigand wrote: Richard Biener wrote: * Makefile.in (gimple-match.o-warn): Remove -Wno-unused-parameter, add -Wno-unused-but-set-variable. This seems to cause cc1plus: error: unrecognized command line option -Wno-unused-but-set-variable make[3]: *** [gimple-match.o] Error 1 in stage1 when bootstrapping on SLES 11 (gcc 4.3.4 host compiler). Oh. Hmm, so I guess build/gengtype-lex.o-warn = -Wno-error gengtype-lex.o-warn = -Wno-error and friends are also incorrect for host compilers that do not know -Wno-error? Which means we need configure checks and substitutes for all -Wno-X we use. 4.3 has -Wunused so I can just replace -Wno-unused-variable -Wno-unused-but-set-variable with -Wno-unused as a quick fix for you. Will do that now (I didn't want to use -Wno-error because that makes the compile quite uselessly verbose and fails to diagnose real issues). No, -Wno-error or -Wno-unused in there is just fine. $($(@D)-warn) and $($@-warn) are only added to GCC_WARN_C{,XX}FLAGS vars and those are added only if the compiler is GCC. Jakub
Re: [PATCH] Fix PR15346
On Mon, 1 Dec 2014, Richard Biener wrote: The following fixes the oldest bug in my list of assigned PRs, namely combining A / CST / CST' to A / (CST * CST'). extract_muldiv does this in fold-const.c (but it fails to optimize to zero when CST * CST' overflows). Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2014-12-01 Richard Biener rguent...@suse.de PR tree-optimization/15346 * Makefile.in (gimple-match.o-warn): Remove -Wno-unused-parameter, add -Wno-unused-but-set-variable. * match.pd: Combine two successive divisions. * gcc.dg/tree-ssa/forwprop-32.c: New testcase. Index: gcc/match.pd === --- gcc/match.pd(revision 218140) +++ gcc/match.pd(working copy) @@ -129,6 +129,19 @@ (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) + (simplify + (div (div @0 INTEGER_CST@1) INTEGER_CST@2) + (with { +bool overflow_p; +wide_int mul = wi::mul (@1, @2, TYPE_SIGN (type), overflow_p); + } + (if (!overflow_p) +(div @0 { wide_int_to_tree (type, mul); })) + (if (overflow_p) +{ build_zero_cst (type); } + Can't you have something like: INT_MIN / 2 / (INT_MIN / -2) == -1 where 2 * (INT_MIN / -2) overflows? -- Marc Glisse
Re: [PATCH] Fix PR15346
On Mon, 1 Dec 2014, Richard Biener wrote: +/* Combine two successive divisions. */ +(for div (trunc_div ceil_div floor_div round_div exact_div) This doesn't seem correct for all kinds of division and signedness of arguments. TRUNC_DIV_EXPR (C division) and EXACT_DIV_EXPR should be OK regardless. But for CEIL_DIV_EXPR and FLOOR_DIV_EXPR, in ((a / b) / c) you need c to be positive so that both roundings are in the same direction (consider e.g. 3 FLOOR_DIV -2 FLOOR_DIV -2 == 1, but 3 FLOOR_DIV 4 == 0). And for ROUND_DIV_EXPR, it can be incorrect whatever the signs (e.g. 2 ROUND_DIV 3 ROUND_DIV 2 == 1, but 2 ROUND_DIV 6 == 0). 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. -- Joseph S. Myers jos...@codesourcery.com