diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2010-07-22 21:55:32 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2010-07-22 21:55:32 +0000 |
commit | 1a39adaec83f79b303de34234b89c4827af9f313 (patch) | |
tree | ae415a4d497cfe2e676f6d950251b0f94d8a1217 /gcc | |
parent | 9362286d7477401ced3eb0b176071d6ec68ed976 (diff) | |
download | gcc-1a39adaec83f79b303de34234b89c4827af9f313.zip gcc-1a39adaec83f79b303de34234b89c4827af9f313.tar.gz gcc-1a39adaec83f79b303de34234b89c4827af9f313.tar.bz2 |
tree-ssa-math-opts.c (is_widening_mult_rhs_p): New function.
gcc/
* tree-ssa-math-opts.c (is_widening_mult_rhs_p): New function.
(is_widening_mult_p): Likewise.
(convert_to_widen): Use them.
(convert_plusminus_to_widen): Likewise. Handle fixed-point types as
well as integer ones.
From-SVN: r162431
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/tree-ssa-math-opts.c | 186 |
2 files changed, 121 insertions, 73 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1086c1f..c1a4969 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2010-07-22 Richard Sandiford <rdsandiford@googlemail.com> + + * tree-ssa-math-opts.c (is_widening_mult_rhs_p): New function. + (is_widening_mult_p): Likewise. + (convert_to_widen): Use them. + (convert_plusminus_to_widen): Likewise. Handle fixed-point types as + well as integer ones. + 2010-07-22 Steven Bosscher <steven@gcc.gnu.org> * alias.c (true_dependence_1): New function, merged version of diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index fe0b4f4..9b96a60 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -1260,93 +1260,127 @@ struct gimple_opt_pass pass_optimize_bswap = } }; -/* Process a single gimple statement STMT, which has a MULT_EXPR as - its rhs, and try to convert it into a WIDEN_MULT_EXPR. The return - value is true iff we converted the statement. */ +/* Return true if RHS is a suitable operand for a widening multiplication. + There are two cases: + + - RHS makes some value twice as wide. Store that value in *NEW_RHS_OUT + if so, and store its type in *TYPE_OUT. + + - RHS is an integer constant. Store that value in *NEW_RHS_OUT if so, + but leave *TYPE_OUT untouched. */ static bool -convert_mult_to_widen (gimple stmt) +is_widening_mult_rhs_p (tree rhs, tree *type_out, tree *new_rhs_out) +{ + gimple stmt; + tree type, type1, rhs1; + enum tree_code rhs_code; + + if (TREE_CODE (rhs) == SSA_NAME) + { + type = TREE_TYPE (rhs); + stmt = SSA_NAME_DEF_STMT (rhs); + if (!is_gimple_assign (stmt)) + return false; + + rhs_code = gimple_assign_rhs_code (stmt); + if (TREE_CODE (type) == INTEGER_TYPE + ? !CONVERT_EXPR_CODE_P (rhs_code) + : rhs_code != FIXED_CONVERT_EXPR) + return false; + + rhs1 = gimple_assign_rhs1 (stmt); + type1 = TREE_TYPE (rhs1); + if (TREE_CODE (type1) != TREE_CODE (type) + || TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type)) + return false; + + *new_rhs_out = rhs1; + *type_out = type1; + return true; + } + + if (TREE_CODE (rhs) == INTEGER_CST) + { + *new_rhs_out = rhs; + *type_out = NULL; + return true; + } + + return false; +} + +/* Return true if STMT performs a widening multiplication. If so, + store the unwidened types of the operands in *TYPE1_OUT and *TYPE2_OUT + respectively. Also fill *RHS1_OUT and *RHS2_OUT such that converting + those operands to types *TYPE1_OUT and *TYPE2_OUT would give the + operands of the multiplication. */ + +static bool +is_widening_mult_p (gimple stmt, + tree *type1_out, tree *rhs1_out, + tree *type2_out, tree *rhs2_out) { - gimple rhs1_stmt = NULL, rhs2_stmt = NULL; - tree type1 = NULL, type2 = NULL; - tree rhs1, rhs2, rhs1_convop = NULL, rhs2_convop = NULL; - enum tree_code rhs1_code, rhs2_code; tree type; type = TREE_TYPE (gimple_assign_lhs (stmt)); + if (TREE_CODE (type) != INTEGER_TYPE + && TREE_CODE (type) != FIXED_POINT_TYPE) + return false; - if (TREE_CODE (type) != INTEGER_TYPE) + if (!is_widening_mult_rhs_p (gimple_assign_rhs1 (stmt), type1_out, rhs1_out)) return false; - rhs1 = gimple_assign_rhs1 (stmt); - rhs2 = gimple_assign_rhs2 (stmt); + if (!is_widening_mult_rhs_p (gimple_assign_rhs2 (stmt), type2_out, rhs2_out)) + return false; - if (TREE_CODE (rhs1) == SSA_NAME) + if (*type1_out == NULL) { - rhs1_stmt = SSA_NAME_DEF_STMT (rhs1); - if (!is_gimple_assign (rhs1_stmt)) - return false; - rhs1_code = gimple_assign_rhs_code (rhs1_stmt); - if (!CONVERT_EXPR_CODE_P (rhs1_code)) - return false; - rhs1_convop = gimple_assign_rhs1 (rhs1_stmt); - type1 = TREE_TYPE (rhs1_convop); - if (TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type)) + if (*type2_out == NULL || !int_fits_type_p (*rhs1_out, *type2_out)) return false; + *type1_out = *type2_out; } - else if (TREE_CODE (rhs1) != INTEGER_CST) - return false; - if (TREE_CODE (rhs2) == SSA_NAME) + if (*type2_out == NULL) { - rhs2_stmt = SSA_NAME_DEF_STMT (rhs2); - if (!is_gimple_assign (rhs2_stmt)) - return false; - rhs2_code = gimple_assign_rhs_code (rhs2_stmt); - if (!CONVERT_EXPR_CODE_P (rhs2_code)) - return false; - rhs2_convop = gimple_assign_rhs1 (rhs2_stmt); - type2 = TREE_TYPE (rhs2_convop); - if (TYPE_PRECISION (type2) * 2 != TYPE_PRECISION (type)) + if (!int_fits_type_p (*rhs2_out, *type1_out)) return false; + *type2_out = *type1_out; } - else if (TREE_CODE (rhs2) != INTEGER_CST) - return false; - if (rhs1_stmt == NULL && rhs2_stmt == NULL) - return false; + return true; +} - /* Verify that the machine can perform a widening multiply in this - mode/signedness combination, otherwise this transformation is - likely to pessimize code. */ - if ((rhs1_stmt == NULL || TYPE_UNSIGNED (type1)) - && (rhs2_stmt == NULL || TYPE_UNSIGNED (type2)) - && (optab_handler (umul_widen_optab, TYPE_MODE (type)) - == CODE_FOR_nothing)) - return false; - else if ((rhs1_stmt == NULL || !TYPE_UNSIGNED (type1)) - && (rhs2_stmt == NULL || !TYPE_UNSIGNED (type2)) - && (optab_handler (smul_widen_optab, TYPE_MODE (type)) - == CODE_FOR_nothing)) - return false; - else if (rhs1_stmt != NULL && rhs2_stmt != NULL - && (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)) - && (optab_handler (usmul_widen_optab, TYPE_MODE (type)) - == CODE_FOR_nothing)) +/* Process a single gimple statement STMT, which has a MULT_EXPR as + its rhs, and try to convert it into a WIDEN_MULT_EXPR. The return + value is true iff we converted the statement. */ + +static bool +convert_mult_to_widen (gimple stmt) +{ + tree lhs, rhs1, rhs2, type, type1, type2; + enum insn_code handler; + + lhs = gimple_assign_lhs (stmt); + type = TREE_TYPE (lhs); + if (TREE_CODE (type) != INTEGER_TYPE) return false; - if ((rhs1_stmt == NULL && !int_fits_type_p (rhs1, type2)) - || (rhs2_stmt == NULL && !int_fits_type_p (rhs2, type1))) + if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2)) return false; - if (rhs1_stmt == NULL) - gimple_assign_set_rhs1 (stmt, fold_convert (type2, rhs1)); + if (TYPE_UNSIGNED (type1) && TYPE_UNSIGNED (type2)) + handler = optab_handler (umul_widen_optab, TYPE_MODE (type)); + else if (!TYPE_UNSIGNED (type1) && !TYPE_UNSIGNED (type2)) + handler = optab_handler (smul_widen_optab, TYPE_MODE (type)); else - gimple_assign_set_rhs1 (stmt, rhs1_convop); - if (rhs2_stmt == NULL) - gimple_assign_set_rhs2 (stmt, fold_convert (type1, rhs2)); - else - gimple_assign_set_rhs2 (stmt, rhs2_convop); + handler = optab_handler (usmul_widen_optab, TYPE_MODE (type)); + + if (handler == CODE_FOR_nothing) + return false; + + gimple_assign_set_rhs1 (stmt, fold_convert (type1, rhs1)); + gimple_assign_set_rhs2 (stmt, fold_convert (type2, rhs2)); gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR); update_stmt (stmt); return true; @@ -1363,7 +1397,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, enum tree_code code) { gimple rhs1_stmt = NULL, rhs2_stmt = NULL; - tree type; + tree type, type1, type2; tree lhs, rhs1, rhs2, mult_rhs1, mult_rhs2, add_rhs; enum tree_code rhs1_code = ERROR_MARK, rhs2_code = ERROR_MARK; optab this_optab; @@ -1371,7 +1405,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, lhs = gimple_assign_lhs (stmt); type = TREE_TYPE (lhs); - if (TREE_CODE (type) != INTEGER_TYPE) + if (TREE_CODE (type) != INTEGER_TYPE + && TREE_CODE (type) != FIXED_POINT_TYPE) return false; if (code == MINUS_EXPR) @@ -1407,20 +1442,25 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, else return false; - if (rhs1_code == MULT_EXPR) + if (code == PLUS_EXPR && rhs1_code == MULT_EXPR) { - if (!convert_mult_to_widen (rhs1_stmt)) + if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1, + &type2, &mult_rhs2)) return false; - rhs1_code = gimple_assign_rhs_code (rhs1_stmt); + mult_rhs1 = fold_convert (type1, mult_rhs1); + mult_rhs2 = fold_convert (type2, mult_rhs2); + add_rhs = rhs2; } - if (rhs2_code == MULT_EXPR) + else if (rhs2_code == MULT_EXPR) { - if (!convert_mult_to_widen (rhs2_stmt)) + if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1, + &type2, &mult_rhs2)) return false; - rhs2_code = gimple_assign_rhs_code (rhs2_stmt); + mult_rhs1 = fold_convert (type1, mult_rhs1); + mult_rhs2 = fold_convert (type2, mult_rhs2); + add_rhs = rhs1; } - - if (code == PLUS_EXPR && rhs1_code == WIDEN_MULT_EXPR) + else if (code == PLUS_EXPR && rhs1_code == WIDEN_MULT_EXPR) { mult_rhs1 = gimple_assign_rhs1 (rhs1_stmt); mult_rhs2 = gimple_assign_rhs2 (rhs1_stmt); |