OSDN Git Service

* tree-ssa-loop-im.c: Include real.h.
authordje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 11 Apr 2005 20:17:38 +0000 (20:17 +0000)
committerdje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 11 Apr 2005 20:17:38 +0000 (20:17 +0000)
        (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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@97983 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/tree-ssa-loop-im.c

index beb69e7..60e5aa3 100644 (file)
@@ -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
index 02599fb..57f3d1a 100644 (file)
@@ -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 \
index a0c4582..4e123f2 100644 (file)
@@ -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;