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] do not lower a/b to a*(1/b)


On Fri, 2005-05-13 at 12:29, Paolo Bonzini wrote:

> +execute_cse_reciprocals (void)
> +{
> +  block_stmt_iterator bsi; 
> +  basic_block bb;
> +  def_operand_p def_p;
> +  use_operand_p use_p;
> +  ssa_op_iter def_iter;
> +  imm_use_iterator use_iter;
> +
> +  FOR_EACH_BB (bb)
> +    {
> +      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
> +        {
> +	  tree stmt = bsi_stmt (bsi), type;
> +	  if (TREE_CODE (stmt) != MODIFY_EXPR)
> +	    continue;
> +	  type = TREE_TYPE (TREE_OPERAND (stmt, 0));
> +	  if (!FLOAT_TYPE_P (type))
> +	    continue;
> +
> +	  FOR_EACH_PHI_OR_STMT_DEF(def_p, stmt, def_iter, SSA_OP_DEF)
            ^^^^^^^^^^^^^^^^^^^^^^^^
you are in a loop over the statements in block BB, so 'stmt' can never
be a PHI node. You should simply use  FOR_EACH_SSA_DEF_OPERAND here, it
compiles into more efficient code.
 


> +		  if (TREE_CODE (use_stmt) == MODIFY_EXPR
> +		      && TREE_CODE (TREE_OPERAND (use_stmt, 1)) == RDIV_EXPR
> +		      && TREE_OPERAND (TREE_OPERAND (use_stmt, 1), 1) == def)
> +		    count++;
> +	          if (count == 2)
> +		    break;

The immediate uses are not necessarily all in the same basic block. If
you want to ensure that they are, you will also have to add a check:

  if (bb_for_stmt (use_stmt) == bb

as well as the same check in the second immediate use loop when you are
changing values.  Although perhaps this has changed from the original
comment, and you do want to do it function wide now:

+   We do this for loop invariant divisors, and within a single basic
+   block in this function.  */


> +	      /* Make a variable with the replacement and substitute it.  */
> +	      t = make_rename_temp (type, "reciptmp");
> +	      new_stmt = build2 (MODIFY_EXPR, void_type_node, t,
> +				 fold_build2 (RDIV_EXPR, type,
> +					      build_real (type, dconst1),
> +					      TREE_OPERAND (stmt, 0)));
> +
> +	      SET_EXPR_LOCUS (new_stmt, EXPR_LOCUS (stmt));
> +	      TREE_BLOCK (new_stmt) = TREE_BLOCK (stmt);
> +	      bsi_insert_after (&bsi, new_stmt, BSI_NEW_STMT);
> +
> +	      FOR_EACH_IMM_USE_SAFE (use_p, use_iter, def)
> +	        {
> +		  tree use_stmt = USE_STMT (use_p);
> +		  if (use_stmt != new_stmt
> +		      && TREE_CODE (use_stmt) == MODIFY_EXPR
> +		      && TREE_CODE (TREE_OPERAND (use_stmt, 1)) == RDIV_EXPR
> +		      && TREE_OPERAND (TREE_OPERAND (use_stmt, 1), 1) == def)
> +		    {
> +		      TREE_CODE (TREE_OPERAND (use_stmt, 1)) = MULT_EXPR;
> +		      SET_USE (use_p, t);
> +		    }

Just a FYI, but once you create a new ssa_name, you could do the loop to
change the uses before inserting the new stmt and avoid having to check
whether (use_stmt != new_stmt).  The immediate uses will still be
associated with the ssa_name, even though the DEF hasn't actually been
inserted into the code yet.  Once an ssa_name is created, immediate uses
are associated with it until released via a call to release_ssa_name(). 

for whatever thats worth :-).

Andrew



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