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


>>>>> Zdenek Dvorak writes:

Zdenek> So you will get the current loop if DEF is not invariant in any
Zdenek> superloop of LOOP (specially, if it is the outermost loop), and NULL,
Zdenek> in case it is not invariant at all.

	So it returns the outermost loop in which DEF remains invariant
instead of the loop to which DEF should be moved to become variant.

	What is the difference between outermost_invariant_loop() and
outermost_invariant_loop_expr()?  I do not understand when to use one or
the other based on the descriptions in the comments.

	By the way, appended is the current version of the patch that
moves all processing to determine_invariantness_stmt().  I needed to add a
call to get_stmt_operands() that should have been unnecessary and now the
patch passes all of SPEC CPU2000.

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.31
diff -c -p -r2.31 tree-ssa-loop-im.c
*** tree-ssa-loop-im.c	11 Mar 2005 09:05:10 -0000	2.31
--- tree-ssa-loop-im.c	3 Apr 2005 23:11:08 -0000
*************** 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
*** 561,567 ****
  {
    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
*** 587,592 ****
--- 589,632 ----
  	  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
+ 	  && expr_invariant_in_loop_p (loop_containing_stmt (stmt),
+ 				       TREE_OPERAND (rhs, 1))
+ 	  && !expr_invariant_in_loop_p (loop_containing_stmt (stmt), rhs))
+ 	{
+ 	  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.  */
+ 	  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]