This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Hoist reciprocal invariant out of loop


	Appended is the final version of the previously approved patch
that I checked in.

David


        * 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.

Index: tree-ssa-loop-im.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-im.c,v
retrieving revision 2.35
retrieving revision 2.36
diff -c -p -r2.35 -r2.36
*** tree-ssa-loop-im.c	9 Apr 2005 01:37:24 -0000	2.35
--- tree-ssa-loop-im.c	11 Apr 2005 20:17:38 -0000	2.36
*************** Software Foundation, 59 Temple Place - S
*** 37,42 ****
--- 37,43 ----
  #include "params.h"
  #include "tree-pass.h"
  #include "flags.h"
+ #include "real.h"
  
  /* TODO:  Support for predicated code motion.  I.e.
  
*************** determine_invariantness_stmt (struct dom
*** 562,568 ****
  {
    enum move_pos pos;
    block_stmt_iterator bsi;
!   tree stmt;
    bool maybe_never = ALWAYS_EXECUTED_IN (bb) == NULL;
    struct loop *outermost = ALWAYS_EXECUTED_IN (bb);
  
--- 563,569 ----
  {
    enum move_pos pos;
    block_stmt_iterator bsi;
!   tree stmt, rhs;
    bool maybe_never = ALWAYS_EXECUTED_IN (bb) == NULL;
    struct loop *outermost = ALWAYS_EXECUTED_IN (bb);
  
*************** determine_invariantness_stmt (struct dom
*** 588,593 ****
--- 589,635 ----
  	  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;
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]