diff options
author | David Edelsohn <edelsohn@gnu.org> | 2005-04-11 20:17:38 +0000 |
---|---|---|
committer | David Edelsohn <dje@gcc.gnu.org> | 2005-04-11 16:17:38 -0400 |
commit | 37cca405546085f77cff5a0bacc334c77422587f (patch) | |
tree | 04f18bb925bd5e02b28ff241d3095e428e48878b | |
parent | 945891207919f9486961857c5de8db42a4771687 (diff) | |
download | gcc-37cca405546085f77cff5a0bacc334c77422587f.zip gcc-37cca405546085f77cff5a0bacc334c77422587f.tar.gz gcc-37cca405546085f77cff5a0bacc334c77422587f.tar.bz2 |
tree-ssa-loop-im.c: Include real.h.
* tree-ssa-loop-im.c: Include real.h.
(determine_invariantness_stmt): If real division divisor is
invariant and flag_unsafe_math_optimizations enabled, generate
invariant reciprocal for hoisting.
* Makefile.in (tree-ssa-loop-im.o): Add real.h dependency.
From-SVN: r97983
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-im.c | 44 |
3 files changed, 52 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index beb69e7..60e5aa3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2005-04-11 David Edelsohn <edelsohn@gnu.org> + + * tree-ssa-loop-im.c: Include real.h. + (determine_invariantness_stmt): If real division divisor is + invariant and flag_unsafe_math_optimizations enabled, generate + invariant reciprocal for hoisting. + * Makefile.in (tree-ssa-loop-im.o): Add real.h dependency. + 2005-04-11 Daniel Berlin <dberlin@dberlin.org> Fix PR tree-optimization/20926 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 02599fb..57f3d1a 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1761,7 +1761,7 @@ tree-ssa-loop-manip.o : tree-ssa-loop-manip.c $(TREE_FLOW_H) $(CONFIG_H) \ tree-ssa-loop-im.o : tree-ssa-loop-im.c $(TREE_FLOW_H) $(CONFIG_H) \ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) domwalk.h $(PARAMS_H)\ output.h diagnostic.h $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \ - tree-pass.h $(FLAGS_H) $(HASHTAB_H) + tree-pass.h $(FLAGS_H) $(HASHTAB_H) real.h tree-ssa-alias.o : tree-ssa-alias.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) tree-inline.h $(FLAGS_H) \ function.h $(TIMEVAR_H) convert.h $(TM_H) coretypes.h \ diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index a0c4582..4e123f2 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -37,6 +37,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "params.h" #include "tree-pass.h" #include "flags.h" +#include "real.h" /* TODO: Support for predicated code motion. I.e. @@ -562,7 +563,7 @@ determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED, { enum move_pos pos; block_stmt_iterator bsi; - tree stmt; + tree stmt, rhs; bool maybe_never = ALWAYS_EXECUTED_IN (bb) == NULL; struct loop *outermost = ALWAYS_EXECUTED_IN (bb); @@ -588,6 +589,47 @@ determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED, continue; } + /* If divisor is invariant, convert a/b to a*(1/b), allowing reciprocal + to be hoisted out of loop, saving expensive divide. */ + if (pos == MOVE_POSSIBLE + && (rhs = TREE_OPERAND (stmt, 1)) != NULL + && TREE_CODE (rhs) == RDIV_EXPR + && flag_unsafe_math_optimizations + && outermost_invariant_loop_expr (TREE_OPERAND (rhs, 1), + loop_containing_stmt (stmt)) != NULL + && outermost_invariant_loop_expr (rhs, + loop_containing_stmt (stmt)) == NULL) + { + tree lhs, stmt1, stmt2, var, name; + + lhs = TREE_OPERAND (stmt, 0); + + /* stmt must be MODIFY_EXPR. */ + var = create_tmp_var (TREE_TYPE (rhs), "reciptmp"); + add_referenced_tmp_var (var); + + stmt1 = build2 (MODIFY_EXPR, void_type_node, var, + build2 (RDIV_EXPR, TREE_TYPE (rhs), + build_real (TREE_TYPE (rhs), dconst1), + TREE_OPERAND (rhs, 1))); + name = make_ssa_name (var, stmt1); + TREE_OPERAND (stmt1, 0) = name; + stmt2 = build2 (MODIFY_EXPR, void_type_node, lhs, + build2 (MULT_EXPR, TREE_TYPE (rhs), + name, TREE_OPERAND (rhs, 0))); + + /* Replace division stmt with reciprocal and multiply stmts. + The multiply stmt is not invariant, so update iterator + and avoid rescanning. */ + bsi_replace (&bsi, stmt1, true); + get_stmt_operands (stmt1); /* Should not be necessary. */ + bsi_insert_after (&bsi, stmt2, BSI_NEW_STMT); + SSA_NAME_DEF_STMT (lhs) = stmt2; + + /* Continue processing with invariant reciprocal statment. */ + stmt = stmt1; + } + stmt_ann (stmt)->common.aux = xcalloc (1, sizeof (struct lim_aux_data)); LIM_DATA (stmt)->always_executed_in = outermost; |