aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Edelsohn <edelsohn@gnu.org>2005-04-11 20:17:38 +0000
committerDavid Edelsohn <dje@gcc.gnu.org>2005-04-11 16:17:38 -0400
commit37cca405546085f77cff5a0bacc334c77422587f (patch)
tree04f18bb925bd5e02b28ff241d3095e428e48878b
parent945891207919f9486961857c5de8db42a4771687 (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/tree-ssa-loop-im.c44
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;