This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Division Optimization in match and simplify
- From: "Hurugalawadi, Naveen" <Naveen dot Hurugalawadi at caviumnetworks dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Cc: Richard Biener <richard dot guenther at gmail dot com>, "marc dot glisse at inria dot fr" <marc dot glisse at inria dot fr>
- Date: Wed, 4 Nov 2015 05:28:28 +0000
- Subject: Division Optimization in match and simplify
- Authentication-results: sourceware.org; auth=none
- Authentication-results: spf=none (sender IP is ) smtp dot mailfrom=Naveen dot Hurugalawadi at caviumnetworks dot com;
- Spamdiagnosticmetadata: NSPM
- Spamdiagnosticoutput: 1:23
Hi,
Please find attached the patch that moves some division optimizations
from fold-const using match and simplify.
Please review the patch and let me know if any modifications are required.
Regression tested the patch on X86 without any issues.
Thanks,
Naveen
ChangeLog
2015-11-04 Naveen H.S <Naveen.Hurugalawadi@caviumnetworks.com>
* fold-const.c (fold_binary_loc) : Move Convert A/B/C to A/(B*C)
to match.pd.
Move Convert A/(B/C) to (A/B)*C to match.pd.
Move Convert C1/(X*C2) into (C1/C2)/X to match.pd.
Move Optimize (X & (-A)) / A where A is a power of 2, to
X >> log2(A) to match.pd.
* match.pd (rdiv (convert? (rdiv @0 @1)) (convert? @2)):
New simplifier.
(rdiv (convert? @0) (convert? (rdiv @1 @2))): New simplifier.
(trunc_div (bit_and (convert? @0) @1) INTEGER_CST@2): New simplifier.
(rdiv (REAL_CST@0) (mult (convert? @1) REAL_CST@2)): New simplifier.
diff --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..04f384c 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -247,6 +247,34 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (!HONOR_SNANS (type))
(negate @0)))
+/* 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)))))
+
+/* Convert A/(B/C) to (A/B)*C */
+(simplify
+ (rdiv (convert? @0) (convert? (rdiv @1 @2)))
+ (if (flag_reciprocal_math
+ && tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && tree_nop_conversion_p (type, TREE_TYPE (@2)))
+ (mult (convert (rdiv @0 @1)) (convert @2))))
+
+/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */
+(simplify
+ (trunc_div (bit_and (convert? @0) @1) INTEGER_CST@2)
+ (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); }
+ (if (sum && integer_zerop (sum))
+ (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 +492,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 (convert? @1) REAL_CST@2))
+ (if (flag_reciprocal_math)
+ (with
+ { tree tem = const_binop (RDIV_EXPR, type, @0, @2); }
+ (if (tem && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+ (rdiv { tem; } @1)))))
+
/* Simplify ~X & X as zero. */
(simplify
(bit_and:c (convert? @0) (convert? (bit_not @0)))