Re: Division Optimization in match and simplify
(I didn't read everything) +/* Convert (A/B)/C to A/(B*C) */ +(simplify + (rdiv (convert? (rdiv @0 @1)) (convert? @2)) + (if (flag_reciprocal_math + && tree_nop_conversion_p (type, TREE_TYPE (@0)) + && tree_nop_conversion_p (type, TREE_TYPE (@2))) + (rdiv (convert @0) (convert (mult @1 @2) I thought we were mostly using the 'convert?' and tree_nop_conversion_p on integers, but I could be wrong. For floats, it seems limited to cases where long double has the same size as double? In any case, the 'convert?' on @2 seems strange, either useless or not sufficient. + (rdiv (REAL_CST@0) (mult (convert? @1) REAL_CST@2)) Here again, the 'convert?' seems useless, (mult @1 REAL_CST@2) would match just as well. +(simplify + (trunc_div (bit_and (convert? @0) @1) INTEGER_CST@2) That would probably also work for exact_div. Again, I don't see the point of this 'convert?'. + (if (!TYPE_UNSIGNED (type) && integer_pow2p (@2) + && tree_int_cst_sgn (@2) > 0 + && tree_nop_conversion_p (type, TREE_TYPE (@0))) + (with + { tree sum = fold_binary (PLUS_EXPR, TREE_TYPE (@2), @2, @1); } Don't you want to require that @1 is INTEGER_CST? And then you could use const_binop, or even wi::add. + (if (sum && integer_zerop (sum)) +(rshift (convert @0) { build_int_cst (integer_type_node, + wi::exact_log2 (@2)); }) -- Marc Glisse
Re: Division Optimization in match and simplify
Hi, Thanks for the review and comments. >> I thought we were mostly using the 'convert?' >> and tree_nop_conversion_p on integers Done. Cleared all instances of convert which are not required. However, I am still confused about the use of "convert" in match and simplify. >> So all patterns looking at arg[01] are handling nop-conversions on their >> outermost operands while those looking at op[01] do not. These patterns are looking at arg[01] rather than op[01] ? Am really sorry, If I am repeating the same thing over and over. >> That would probably also work for exact_div. Done. >> Don't you want to require that @1 is INTEGER_CST? And then you could use >> const_binop, or even wi::add. Done. The fold-const part did not specify it as INTEGER_CST. Although it was obvious from the PLUS_EXPR. However, just wanted to retain as per fold-const. Please find attached the modified patch with all review comments addressed. Regression tested on X86_64 without any extra failures. Thanks, Naveendiff --git a/gcc/fold-const.c b/gcc/fold-const.c index ee9b349..88dbbdd 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -10163,54 +10163,9 @@ fold_binary_loc (location_t loc, return fold_build2_loc (loc, RDIV_EXPR, type, negate_expr (arg0), TREE_OPERAND (arg1, 0)); - - /* Convert A/B/C to A/(B*C). */ - if (flag_reciprocal_math - && TREE_CODE (arg0) == RDIV_EXPR) - return fold_build2_loc (loc, RDIV_EXPR, type, TREE_OPERAND (arg0, 0), - fold_build2_loc (loc, MULT_EXPR, type, - TREE_OPERAND (arg0, 1), arg1)); - - /* Convert A/(B/C) to (A/B)*C. */ - if (flag_reciprocal_math - && TREE_CODE (arg1) == RDIV_EXPR) - return fold_build2_loc (loc, MULT_EXPR, type, - fold_build2_loc (loc, RDIV_EXPR, type, arg0, - TREE_OPERAND (arg1, 0)), - TREE_OPERAND (arg1, 1)); - - /* Convert C1/(X*C2) into (C1/C2)/X. */ - if (flag_reciprocal_math - && TREE_CODE (arg1) == MULT_EXPR - && TREE_CODE (arg0) == REAL_CST - && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST) - { - tree tem = const_binop (RDIV_EXPR, arg0, - TREE_OPERAND (arg1, 1)); - if (tem) - return fold_build2_loc (loc, RDIV_EXPR, type, tem, -TREE_OPERAND (arg1, 0)); - } - return NULL_TREE; case TRUNC_DIV_EXPR: - /* Optimize (X & (-A)) / A where A is a power of 2, - to X >> log2(A) */ - if (TREE_CODE (arg0) == BIT_AND_EXPR - && !TYPE_UNSIGNED (type) && TREE_CODE (arg1) == INTEGER_CST - && integer_pow2p (arg1) && tree_int_cst_sgn (arg1) > 0) - { - tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (arg1), - arg1, TREE_OPERAND (arg0, 1)); - if (sum && integer_zerop (sum)) { - tree pow2 = build_int_cst (integer_type_node, - wi::exact_log2 (arg1)); - return fold_build2_loc (loc, RSHIFT_EXPR, type, -TREE_OPERAND (arg0, 0), pow2); - } - } - /* Fall through */ case FLOOR_DIV_EXPR: diff --git a/gcc/match.pd b/gcc/match.pd index f6c5c07..020f575 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -247,6 +247,27 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (!HONOR_SNANS (type)) (negate @0))) +/* Convert (A/B)/C to A/(B*C) */ +(simplify + (rdiv (rdiv @0 @1) @2) + (if (flag_reciprocal_math) + (rdiv @0 (mult @1 @2 + +/* Convert A/(B/C) to (A/B)*C */ +(simplify + (rdiv @0 (rdiv @1 @2)) + (if (flag_reciprocal_math) + (mult (rdiv @0 @1) @2))) + +/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */ +(for div (exact_div trunc_div) + (simplify + (div (bit_and @0 INTEGER_CST@1) INTEGER_CST@2) + (if (!TYPE_UNSIGNED (type) && integer_pow2p (@2) + && tree_int_cst_sgn (@2) > 0 + && wi::add (@2, @1) == 0) + (rshift @0 { build_int_cst (integer_type_node, wi::exact_log2 (@2)); } + /* If ARG1 is a constant, we can convert this to a multiply by the reciprocal. This does not have the same rounding properties, so only do this if -freciprocal-math. We can actually @@ -464,6 +485,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (tem) (rdiv { tem; } @1) +/* Convert C1/(X*C2) into (C1/C2)/X */ +(simplify + (rdiv (REAL_CST@0) (mult @1 REAL_CST@2)) + (if (flag_reciprocal_math) + (with +{ tree tem = const_binop (RDIV_EXPR, type, @0, @2); } +(if (tem) + (rdiv { tem; } @1) + /* Simplify ~X & X as zero. */ (simplify (bit_and:c (convert? @0) (convert? (bit_not @0)))
Re: Division Optimization in match and simplify
On Wed, 4 Nov 2015, Hurugalawadi, Naveen wrote: I thought we were mostly using the 'convert?' and tree_nop_conversion_p on integers Done. Cleared all instances of convert which are not required. However, I am still confused about the use of "convert" in match and simplify. It could be that I am wrong, you'll have to wait for Richard's comments anyway. The one place where a convert could be useful is: (div (convert? (bit_and @0 INTEGER_CST@1)) INTEGER_CST@2) but I didn't check if we want it (it would probably at least require (convert @0) instead of plain @0 in the result so the division and the shift are done with the same signedness). So all patterns looking at arg[01] are handling nop-conversions on their outermost operands while those looking at op[01] do not. These patterns are looking at arg[01] rather than op[01] ? Might be a case where it doesn't really matter which one you look at, and the easiest one in fold-const may not be the same as in match.pd. +/* Convert (A/B)/C to A/(B*C) */ +(simplify + (rdiv (rdiv @0 @1) @2) + (if (flag_reciprocal_math) I would indent this line the same as the one above. + (rdiv @0 (mult @1 @2 + +/* Convert A/(B/C) to (A/B)*C */ +(simplify + (rdiv @0 (rdiv @1 @2)) + (if (flag_reciprocal_math) + (mult (rdiv @0 @1) @2))) I believe you might want a :s on the inner rdiv (?). Note that you can factor out the test on flag_reciprocal_math so you write it only once for 2 patterns. I don't really remember what the tests !TYPE_UNSIGNED (type) and tree_int_cst_sgn are for in the other pattern, but since you are only moving the transformation... -- Marc Glisse
Re: Division Optimization in match and simplify
On Wed, Nov 4, 2015 at 12:18 PM, Marc Glisse wrote: > On Wed, 4 Nov 2015, Hurugalawadi, Naveen wrote: > I thought we were mostly using the 'convert?' and tree_nop_conversion_p on integers Yes, on floats they shouldn't be used. >> >> Done. Cleared all instances of convert which are not required. >> However, I am still confused about the use of "convert" in match >> and simplify. > > > It could be that I am wrong, you'll have to wait for Richard's comments > anyway. The one place where a convert could be useful is: > (div (convert? (bit_and @0 INTEGER_CST@1)) INTEGER_CST@2) > but I didn't check if we want it (it would probably at least require > (convert @0) instead of plain @0 in the result so the division and the shift > are done with the same signedness). > So all patterns looking at arg[01] are handling nop-conversions on their outermost operands while those looking at op[01] do not. >> >> >> These patterns are looking at arg[01] rather than op[01] ? > > > Might be a case where it doesn't really matter which one you look at, and > the easiest one in fold-const may not be the same as in match.pd. > > +/* Convert (A/B)/C to A/(B*C) */ > +(simplify > + (rdiv (rdiv @0 @1) @2) > + (if (flag_reciprocal_math) > > I would indent this line the same as the one above. Yep. > + (rdiv @0 (mult @1 @2 > + > +/* Convert A/(B/C) to (A/B)*C */ > +(simplify > + (rdiv @0 (rdiv @1 @2)) > + (if (flag_reciprocal_math) > + (mult (rdiv @0 @1) @2))) > > I believe you might want a :s on the inner rdiv (?). > Note that you can factor out the test on flag_reciprocal_math so you write > it only once for 2 patterns. Please use :s on both inner rdiv in both patterns. With that the two patterns are ok. +/* Convert C1/(X*C2) into (C1/C2)/X */ +(simplify + (rdiv (REAL_CST@0) (mult @1 REAL_CST@2)) Omit the parens around REAL_CST@0 + (if (flag_reciprocal_math) + (with +{ tree tem = const_binop (RDIV_EXPR, type, @0, @2); } +(if (tem) + (rdiv { tem; } @1) with that the pattern is ok. > > I don't really remember what the tests !TYPE_UNSIGNED (type) and > tree_int_cst_sgn are for in the other pattern, but since you are only moving > the transformation... +/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */ +(for div (exact_div trunc_div) + (simplify + (div (bit_and @0 INTEGER_CST@1) INTEGER_CST@2) + (if (!TYPE_UNSIGNED (type) && integer_pow2p (@2) + && tree_int_cst_sgn (@2) > 0 + && wi::add (@2, @1) == 0) + (rshift @0 { build_int_cst (integer_type_node, wi::exact_log2 (@2)); } the TYPE_UNSIGNED test is because right shift of negative values is undefined, so is a shift with a negative value. I believe we can safely handle conversions here just like fold-const.c does with (div (convert? (bit_and @0 INTEGER_CST@1) INTEGER_CST@2) (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) ... With that the pattern looks ok to me. Richard. > > -- > Marc Glisse
Re: Division Optimization in match and simplify
On Wed, 4 Nov 2015, Richard Biener wrote: I don't really remember what the tests !TYPE_UNSIGNED (type) and tree_int_cst_sgn are for in the other pattern, but since you are only moving the transformation... +/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */ +(for div (exact_div trunc_div) + (simplify + (div (bit_and @0 INTEGER_CST@1) INTEGER_CST@2) + (if (!TYPE_UNSIGNED (type) && integer_pow2p (@2) + && tree_int_cst_sgn (@2) > 0 + && wi::add (@2, @1) == 0) + (rshift @0 { build_int_cst (integer_type_node, wi::exact_log2 (@2)); } the TYPE_UNSIGNED test is because right shift of negative values is undefined, tree.def: "Shift means logical shift if done on an unsigned type, arithmetic shift if done on a signed type." To me, this implies that right shift of negative values is well-defined inside gcc. Also, the test allows *only signed types*, not unsigned. so is a shift with a negative value. I believe we can safely handle conversions here just like fold-const.c does with (div (convert? (bit_and @0 INTEGER_CST@1) INTEGER_CST@2) (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) ... With that the pattern looks ok to me. As long as it comes with (convert @0) in the result... I think the fold-const.c pattern is lucky that (int)(x&-4u) gets folded to (int)x&-4, or it might ICE for ((int)(x&-4u))/4. -- Marc Glisse
Re: Division Optimization in match and simplify
On Wed, Nov 4, 2015 at 1:45 PM, Marc Glisse wrote: > On Wed, 4 Nov 2015, Richard Biener wrote: > >>> I don't really remember what the tests !TYPE_UNSIGNED (type) and >>> tree_int_cst_sgn are for in the other pattern, but since you are only >>> moving >>> the transformation... >> >> >> +/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */ >> +(for div (exact_div trunc_div) >> + (simplify >> + (div (bit_and @0 INTEGER_CST@1) INTEGER_CST@2) >> + (if (!TYPE_UNSIGNED (type) && integer_pow2p (@2) >> + && tree_int_cst_sgn (@2) > 0 >> + && wi::add (@2, @1) == 0) >> + (rshift @0 { build_int_cst (integer_type_node, wi::exact_log2 (@2)); >> } >> >> the TYPE_UNSIGNED test is because right shift of negative values is >> undefined, > > > tree.def: "Shift means logical shift if done on an unsigned type, arithmetic > shift if done on a signed type." > To me, this implies that right shift of negative values is well-defined > inside gcc. Ah, it was _left_ shift of negative values that ubsan complains about. > Also, the test allows *only signed types*, not unsigned. Doh. Ok, so maybe that's because the tree_int_cst_sgn test would "not work" otherwise (just use tree_int_cst_sign_bit (@2) == 0). > >> so is a shift with a negative value. I believe we can safely handle >> conversions here >> just like fold-const.c does with >> >> (div (convert? (bit_and @0 INTEGER_CST@1) INTEGER_CST@2) >> (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) >> ... >> >> With that the pattern looks ok to me. > > > As long as it comes with (convert @0) in the result... I think the > fold-const.c pattern is lucky that (int)(x&-4u) gets folded to > (int)x&-4, or it might ICE for ((int)(x&-4u))/4. I think the types match ok but I might have looked too quickly (again). Richard. > -- > Marc Glisse
Re: Division Optimization in match and simplify
Hi, Please find attached the modified patch as per review comments. >> use :s on both inner rdiv in both patterns. With that the two patterns are >> ok. Done. >> Omit the parens around REAL_CST@0 Done. Regression tested on X86_64. Thanks, Naveendiff --git a/gcc/fold-const.c b/gcc/fold-const.c index ee9b349..88dbbdd 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -10163,54 +10163,9 @@ fold_binary_loc (location_t loc, return fold_build2_loc (loc, RDIV_EXPR, type, negate_expr (arg0), TREE_OPERAND (arg1, 0)); - - /* Convert A/B/C to A/(B*C). */ - if (flag_reciprocal_math - && TREE_CODE (arg0) == RDIV_EXPR) - return fold_build2_loc (loc, RDIV_EXPR, type, TREE_OPERAND (arg0, 0), - fold_build2_loc (loc, MULT_EXPR, type, - TREE_OPERAND (arg0, 1), arg1)); - - /* Convert A/(B/C) to (A/B)*C. */ - if (flag_reciprocal_math - && TREE_CODE (arg1) == RDIV_EXPR) - return fold_build2_loc (loc, MULT_EXPR, type, - fold_build2_loc (loc, RDIV_EXPR, type, arg0, - TREE_OPERAND (arg1, 0)), - TREE_OPERAND (arg1, 1)); - - /* Convert C1/(X*C2) into (C1/C2)/X. */ - if (flag_reciprocal_math - && TREE_CODE (arg1) == MULT_EXPR - && TREE_CODE (arg0) == REAL_CST - && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST) - { - tree tem = const_binop (RDIV_EXPR, arg0, - TREE_OPERAND (arg1, 1)); - if (tem) - return fold_build2_loc (loc, RDIV_EXPR, type, tem, -TREE_OPERAND (arg1, 0)); - } - return NULL_TREE; case TRUNC_DIV_EXPR: - /* Optimize (X & (-A)) / A where A is a power of 2, - to X >> log2(A) */ - if (TREE_CODE (arg0) == BIT_AND_EXPR - && !TYPE_UNSIGNED (type) && TREE_CODE (arg1) == INTEGER_CST - && integer_pow2p (arg1) && tree_int_cst_sgn (arg1) > 0) - { - tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (arg1), - arg1, TREE_OPERAND (arg0, 1)); - if (sum && integer_zerop (sum)) { - tree pow2 = build_int_cst (integer_type_node, - wi::exact_log2 (arg1)); - return fold_build2_loc (loc, RSHIFT_EXPR, type, -TREE_OPERAND (arg0, 0), pow2); - } - } - /* Fall through */ case FLOOR_DIV_EXPR: diff --git a/gcc/match.pd b/gcc/match.pd index f6c5c07..d11ad79 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -247,6 +247,27 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (!HONOR_SNANS (type)) (negate @0))) +(if (flag_reciprocal_math) + /* Convert (A/B)/C to A/(B*C) */ + (simplify + (rdiv (rdiv:s @0 @1) @2) + (rdiv @0 (mult @1 @2))) + + /* Convert A/(B/C) to (A/B)*C */ + (simplify + (rdiv @0 (rdiv:s @1 @2)) + (mult (rdiv @0 @1) @2))) + +/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */ +(for div (exact_div trunc_div) + (simplify + (div (convert? (bit_and @0 INTEGER_CST@1)) INTEGER_CST@2) + (if (integer_pow2p (@2) + && tree_int_cst_sign_bit (@2) == 0 + && wi::add (@2, @1) == 0 + && tree_nop_conversion_p (type, TREE_TYPE (@0))) + (rshift (convert @0) { build_int_cst (integer_type_node, wi::exact_log2 (@2)); } + /* If ARG1 is a constant, we can convert this to a multiply by the reciprocal. This does not have the same rounding properties, so only do this if -freciprocal-math. We can actually @@ -464,6 +485,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (tem) (rdiv { tem; } @1) +/* Convert C1/(X*C2) into (C1/C2)/X */ +(simplify + (rdiv REAL_CST@0 (mult @1 REAL_CST@2)) + (if (flag_reciprocal_math) + (with +{ tree tem = const_binop (RDIV_EXPR, type, @0, @2); } +(if (tem) + (rdiv { tem; } @1) + /* Simplify ~X & X as zero. */ (simplify (bit_and:c (convert? @0) (convert? (bit_not @0)))
Re: Division Optimization in match and simplify
+/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */ +(for div (exact_div trunc_div) Actually, it probably works for all integer divisions (floor_div, etc) since it is exact and thus does not depend on the rounding. (sorry for giving the comments small piece by small piece, I write them as I think of them...) + (simplify + (div (convert? (bit_and @0 INTEGER_CST@1)) INTEGER_CST@2) + (if (integer_pow2p (@2) + && tree_int_cst_sign_bit (@2) == 0 I think the previous test tree_int_cst_sgn > 0 was better: for unsigned, it is ok if that bit is set, it is only for signed that we want to avoid -1/-1 which gives 1 (while a shift by 31 would give -1, except that wi::exact_log2 might return -1 so we would end up with a negative shift). (actually, we could generate (unsigned)x>>31 in that case, but let's forget it for now) + && wi::add (@2, @1) == 0 + && tree_nop_conversion_p (type, TREE_TYPE (@0))) + (rshift (convert @0) { build_int_cst (integer_type_node, wi::exact_log2 (@2)); } (does this fit in 80 cols?) Note that if we port the following to match.pd from wherever it currently is, the 'convert?' becomes much less useful on this transformation (simplify (convert (bit_and:s @0 INTEGER_CST@1)) (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) (bit_and (convert @0) (convert @1 -- Marc Glisse
Re: Division Optimization in match and simplify
Hi, On Wed, 4 Nov 2015, Richard Biener wrote: > Ah, it was _left_ shift of negative values that ubsan complains about. Note that this is only for the frontend definition of shifts. I don't see why gimple shouldn't define it to the only sensible definition there is, which also happens to be the one that all CPUs in the world implement (well, those using two-complement representation at least). Ciao, Michael.
Re: Division Optimization in match and simplify
On November 5, 2015 2:40:30 PM GMT+01:00, Michael Matz wrote: >Hi, > >On Wed, 4 Nov 2015, Richard Biener wrote: > >> Ah, it was _left_ shift of negative values that ubsan complains >about. > >Note that this is only for the frontend definition of shifts. I don't >see >why gimple shouldn't define it to the only sensible definition there >is, >which also happens to be the one that all CPUs in the world implement >(well, those using two-complement representation at least). Yeah, but front ends and back end are not separated enough to have both. Richard. > >Ciao, >Michael.
Re: Division Optimization in match and simplify
Hi, >> it probably works for all integer divisions (floor_div, etc) >> since it is exact and thus does not depend on the rounding. Please find attached the modified patch as per comments. Thanks, Naveendiff --git a/gcc/fold-const.c b/gcc/fold-const.c index ee9b349..88dbbdd 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -10163,54 +10163,9 @@ fold_binary_loc (location_t loc, return fold_build2_loc (loc, RDIV_EXPR, type, negate_expr (arg0), TREE_OPERAND (arg1, 0)); - - /* Convert A/B/C to A/(B*C). */ - if (flag_reciprocal_math - && TREE_CODE (arg0) == RDIV_EXPR) - return fold_build2_loc (loc, RDIV_EXPR, type, TREE_OPERAND (arg0, 0), - fold_build2_loc (loc, MULT_EXPR, type, - TREE_OPERAND (arg0, 1), arg1)); - - /* Convert A/(B/C) to (A/B)*C. */ - if (flag_reciprocal_math - && TREE_CODE (arg1) == RDIV_EXPR) - return fold_build2_loc (loc, MULT_EXPR, type, - fold_build2_loc (loc, RDIV_EXPR, type, arg0, - TREE_OPERAND (arg1, 0)), - TREE_OPERAND (arg1, 1)); - - /* Convert C1/(X*C2) into (C1/C2)/X. */ - if (flag_reciprocal_math - && TREE_CODE (arg1) == MULT_EXPR - && TREE_CODE (arg0) == REAL_CST - && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST) - { - tree tem = const_binop (RDIV_EXPR, arg0, - TREE_OPERAND (arg1, 1)); - if (tem) - return fold_build2_loc (loc, RDIV_EXPR, type, tem, -TREE_OPERAND (arg1, 0)); - } - return NULL_TREE; case TRUNC_DIV_EXPR: - /* Optimize (X & (-A)) / A where A is a power of 2, - to X >> log2(A) */ - if (TREE_CODE (arg0) == BIT_AND_EXPR - && !TYPE_UNSIGNED (type) && TREE_CODE (arg1) == INTEGER_CST - && integer_pow2p (arg1) && tree_int_cst_sgn (arg1) > 0) - { - tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (arg1), - arg1, TREE_OPERAND (arg0, 1)); - if (sum && integer_zerop (sum)) { - tree pow2 = build_int_cst (integer_type_node, - wi::exact_log2 (arg1)); - return fold_build2_loc (loc, RSHIFT_EXPR, type, -TREE_OPERAND (arg0, 0), pow2); - } - } - /* Fall through */ case FLOOR_DIV_EXPR: diff --git a/gcc/match.pd b/gcc/match.pd index f6c5c07..0e658f7 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -247,6 +247,28 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (!HONOR_SNANS (type)) (negate @0))) +(if (flag_reciprocal_math) + /* Convert (A/B)/C to A/(B*C) */ + (simplify + (rdiv (rdiv:s @0 @1) @2) + (rdiv @0 (mult @1 @2))) + + /* Convert A/(B/C) to (A/B)*C */ + (simplify + (rdiv @0 (rdiv:s @1 @2)) + (mult (rdiv @0 @1) @2))) + +/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */ +(for div (trunc_div ceil_div floor_div round_div exact_div) + (simplify + (div (convert? (bit_and @0 INTEGER_CST@1)) INTEGER_CST@2) + (if (!TYPE_UNSIGNED (type) && integer_pow2p (@2) + && tree_int_cst_sgn (@2) > 0 + && wi::add (@2, @1) == 0 + && tree_nop_conversion_p (type, TREE_TYPE (@0))) + (rshift (convert @0) { build_int_cst (integer_type_node, + wi::exact_log2 (@2)); } + /* If ARG1 is a constant, we can convert this to a multiply by the reciprocal. This does not have the same rounding properties, so only do this if -freciprocal-math. We can actually @@ -464,6 +486,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (tem) (rdiv { tem; } @1) +/* Convert C1/(X*C2) into (C1/C2)/X */ +(simplify + (rdiv REAL_CST@0 (mult @1 REAL_CST@2)) + (if (flag_reciprocal_math) + (with +{ tree tem = const_binop (RDIV_EXPR, type, @0, @2); } +(if (tem) + (rdiv { tem; } @1) + /* Simplify ~X & X as zero. */ (simplify (bit_and:c (convert? @0) (convert? (bit_not @0)))
Re: Division Optimization in match and simplify
+/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */ +(for div (trunc_div ceil_div floor_div round_div exact_div) + (simplify + (div (convert? (bit_and @0 INTEGER_CST@1)) INTEGER_CST@2) + (if (!TYPE_UNSIGNED (type) && integer_pow2p (@2) + && tree_int_cst_sgn (@2) > 0 + && wi::add (@2, @1) == 0 + && tree_nop_conversion_p (type, TREE_TYPE (@0))) + (rshift (convert @0) { build_int_cst (integer_type_node, +wi::exact_log2 (@2)); } Sorry, I must be very unclear when I write :-( I indeed like tree_int_cst_sgn (@2) > 0 better than looking at the sign bit, but I don't know why you re-introduced !TYPE_UNSIGNED (type) at the same time. The whole reason I prefer tree_int_cst_sgn is that it also applies when type is unsigned and @2 is 2^31. -- Marc Glisse