tree-ssa-math-opts.c revision 169689
141120Sjdp/* Global, SSA-based optimizations using mathematical identities.
2103976Spst   Copyright (C) 2005 Free Software Foundation, Inc.
341120Sjdp
441120SjdpThis file is part of GCC.
541120Sjdp
641120SjdpGCC is free software; you can redistribute it and/or modify it
741120Sjdpunder the terms of the GNU General Public License as published by the
841120SjdpFree Software Foundation; either version 2, or (at your option) any
941120Sjdplater version.
1041120Sjdp
1141120SjdpGCC is distributed in the hope that it will be useful, but WITHOUT
1241120SjdpANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1341120SjdpFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1441120Sjdpfor more details.
1541120Sjdp
1641120SjdpYou should have received a copy of the GNU General Public License
1741120Sjdpalong with GCC; see the file COPYING.  If not, write to the Free
1841120SjdpSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
1941120Sjdp02110-1301, USA.  */
2041120Sjdp
2141120Sjdp/* Currently, the only mini-pass in this file tries to CSE reciprocal
2241120Sjdp   operations.  These are common in sequences such as this one:
2341120Sjdp
2441120Sjdp	modulus = sqrt(x*x + y*y + z*z);
2541120Sjdp	x = x / modulus;
2641120Sjdp	y = y / modulus;
2784222Sdillon	z = z / modulus;
2884222Sdillon
2984222Sdillon   that can be optimized to
3041120Sjdp
3141120Sjdp	modulus = sqrt(x*x + y*y + z*z);
3241120Sjdp        rmodulus = 1.0 / modulus;
3341120Sjdp	x = x * rmodulus;
3441120Sjdp	y = y * rmodulus;
3541120Sjdp	z = z * rmodulus;
3641120Sjdp
3741120Sjdp   We do this for loop invariant divisors, and with this pass whenever
3841120Sjdp   we notice that a division has the same divisor multiple times.
3941120Sjdp
4041120Sjdp   Of course, like in PRE, we don't insert a division if a dominator
4141120Sjdp   already has one.  However, this cannot be done as an extension of
4241120Sjdp   PRE for several reasons.
4341120Sjdp
4441120Sjdp   First of all, with some experiments it was found out that the
4541120Sjdp   transformation is not always useful if there are only two divisions
4641120Sjdp   hy the same divisor.  This is probably because modern processors
4741120Sjdp   can pipeline the divisions; on older, in-order processors it should
4841120Sjdp   still be effective to optimize two divisions by the same number.
4941120Sjdp   We make this a param, and it shall be called N in the remainder of
5041120Sjdp   this comment.
5141120Sjdp
5241120Sjdp   Second, if trapping math is active, we have less freedom on where
5341120Sjdp   to insert divisions: we can only do so in basic blocks that already
54103976Spst   contain one.  (If divisions don't trap, instead, we can insert
5541120Sjdp   divisions elsewhere, which will be in blocks that are common dominators
5641120Sjdp   of those that have the division).
5741120Sjdp
5841120Sjdp   We really don't want to compute the reciprocal unless a division will
5941120Sjdp   be found.  To do this, we won't insert the division in a basic block
6041120Sjdp   that has less than N divisions *post-dominating* it.
6141120Sjdp
6241120Sjdp   The algorithm constructs a subset of the dominator tree, holding the
6341120Sjdp   blocks containing the divisions and the common dominators to them,
6441120Sjdp   and walk it twice.  The first walk is in post-order, and it annotates
6541120Sjdp   each block with the number of divisions that post-dominate it: this
66103976Spst   gives information on where divisions can be inserted profitably.
67103976Spst   The second walk is in pre-order, and it inserts divisions as explained
6841120Sjdp   above, and replaces divisions by multiplications.
6941120Sjdp
7041120Sjdp   In the best case, the cost of the pass is O(n_statements).  In the
7141120Sjdp   worst-case, the cost is due to creating the dominator tree subset,
7241120Sjdp   with a cost of O(n_basic_blocks ^ 2); however this can only happen
7341120Sjdp   for n_statements / n_basic_blocks statements.  So, the amortized cost
7441120Sjdp   of creating the dominator tree subset is O(n_basic_blocks) and the
7541120Sjdp   worst-case cost of the pass is O(n_statements * n_basic_blocks).
7641120Sjdp
7741120Sjdp   More practically, the cost will be small because there are few
7841120Sjdp   divisions, and they tend to be in the same basic block, so insert_bb
79103976Spst   is called very few times.
80103976Spst
8141120Sjdp   If we did this using domwalk.c, an efficient implementation would have
8241120Sjdp   to work on all the variables in a single pass, because we could not
8341120Sjdp   work on just a subset of the dominator tree, as we do now, and the
8441120Sjdp   cost would also be something like O(n_statements * n_basic_blocks).
8541120Sjdp   The data structures would be more complex in order to work on all the
8641120Sjdp   variables in a single pass.  */
8741120Sjdp
8841120Sjdp#include "config.h"
8941120Sjdp#include "system.h"
9041120Sjdp#include "coretypes.h"
9141120Sjdp#include "tm.h"
9241120Sjdp#include "flags.h"
9341120Sjdp#include "tree.h"
9441120Sjdp#include "tree-flow.h"
9541120Sjdp#include "real.h"
9641120Sjdp#include "timevar.h"
9741120Sjdp#include "tree-pass.h"
9841120Sjdp#include "alloc-pool.h"
9941120Sjdp#include "basic-block.h"
10041120Sjdp#include "target.h"
10141120Sjdp
10241120Sjdp
10341120Sjdp/* This structure represents one basic block that either computes a
10441120Sjdp   division, or is a common dominator for basic block that compute a
10541120Sjdp   division.  */
10641120Sjdpstruct occurrence {
10741120Sjdp  /* The basic block represented by this structure.  */
10841120Sjdp  basic_block bb;
10941120Sjdp
11041120Sjdp  /* If non-NULL, the SSA_NAME holding the definition for a reciprocal
11141120Sjdp     inserted in BB.  */
11241120Sjdp  tree recip_def;
11341120Sjdp
11441120Sjdp  /* If non-NULL, the MODIFY_EXPR for a reciprocal computation that
11541120Sjdp     was inserted in BB.  */
11641120Sjdp  tree recip_def_stmt;
11741120Sjdp
11841120Sjdp  /* Pointer to a list of "struct occurrence"s for blocks dominated
11941120Sjdp     by BB.  */
12041120Sjdp  struct occurrence *children;
12141120Sjdp
12241120Sjdp  /* Pointer to the next "struct occurrence"s in the list of blocks
12341120Sjdp     sharing a common dominator.  */
12441120Sjdp  struct occurrence *next;
12541120Sjdp
12641120Sjdp  /* The number of divisions that are in BB before compute_merit.  The
12741120Sjdp     number of divisions that are in BB or post-dominate it after
12841120Sjdp     compute_merit.  */
12941120Sjdp  int num_divisions;
13041120Sjdp
13141120Sjdp  /* True if the basic block has a division, false if it is a common
13241120Sjdp     dominator for basic blocks that do.  If it is false and trapping
13341120Sjdp     math is active, BB is not a candidate for inserting a reciprocal.  */
13441120Sjdp  bool bb_has_division;
13541120Sjdp};
13641120Sjdp
13741120Sjdp
13841120Sjdp/* The instance of "struct occurrence" representing the highest
13941120Sjdp   interesting block in the dominator tree.  */
14041120Sjdpstatic struct occurrence *occ_head;
14141120Sjdp
14241120Sjdp/* Allocation pool for getting instances of "struct occurrence".  */
143103976Spststatic alloc_pool occ_pool;
14441120Sjdp
145103976Spst
14641120Sjdp
147103976Spst/* Allocate and return a new struct occurrence for basic block BB, and
148103976Spst   whose children list is headed by CHILDREN.  */
149103976Spststatic struct occurrence *
150103976Spstocc_new (basic_block bb, struct occurrence *children)
151103976Spst{
152103976Spst  struct occurrence *occ;
15341120Sjdp
154103976Spst  occ = bb->aux = pool_alloc (occ_pool);
155103976Spst  memset (occ, 0, sizeof (struct occurrence));
156103976Spst
157103976Spst  occ->bb = bb;
158103976Spst  occ->children = children;
159103976Spst  return occ;
16041120Sjdp}
161103976Spst
162103976Spst
16341120Sjdp/* Insert NEW_OCC into our subset of the dominator tree.  P_HEAD points to a
164103976Spst   list of "struct occurrence"s, one per basic block, having IDOM as
165103976Spst   their common dominator.
16641120Sjdp
167103976Spst   We try to insert NEW_OCC as deep as possible in the tree, and we also
168103976Spst   insert any other block that is a common dominator for BB and one
169103976Spst   block already in the tree.  */
170103976Spst
17141120Sjdpstatic void
172103976Spstinsert_bb (struct occurrence *new_occ, basic_block idom,
17341120Sjdp	   struct occurrence **p_head)
174103976Spst{
175103976Spst  struct occurrence *occ, **p_occ;
17641120Sjdp
177103976Spst  for (p_occ = p_head; (occ = *p_occ) != NULL; )
178103976Spst    {
179103976Spst      basic_block bb = new_occ->bb, occ_bb = occ->bb;
180103976Spst      basic_block dom = nearest_common_dominator (CDI_DOMINATORS, occ_bb, bb);
181103976Spst      if (dom == bb)
182103976Spst	{
183103976Spst	  /* BB dominates OCC_BB.  OCC becomes NEW_OCC's child: remove OCC
184103976Spst	     from its list.  */
185103976Spst	  *p_occ = occ->next;
186103976Spst	  occ->next = new_occ->children;
187103976Spst	  new_occ->children = occ;
188103976Spst
189103976Spst	  /* Try the next block (it may as well be dominated by BB).  */
190103976Spst	}
191103976Spst
192103976Spst      else if (dom == occ_bb)
193103976Spst	{
194103976Spst	  /* OCC_BB dominates BB.  Tail recurse to look deeper.  */
195103976Spst	  insert_bb (new_occ, dom, &occ->children);
196103976Spst	  return;
197103976Spst	}
198103976Spst
199103976Spst      else if (dom != idom)
200103976Spst	{
201103976Spst	  gcc_assert (!dom->aux);
202103976Spst
203103976Spst	  /* There is a dominator between IDOM and BB, add it and make
204103976Spst	     two children out of NEW_OCC and OCC.  First, remove OCC from
205103976Spst	     its list.	*/
206103976Spst	  *p_occ = occ->next;
207103976Spst	  new_occ->next = occ;
208103976Spst	  occ->next = NULL;
209103976Spst
21041120Sjdp	  /* None of the previous blocks has DOM as a dominator: if we tail
211103976Spst	     recursed, we would reexamine them uselessly. Just switch BB with
212103976Spst	     DOM, and go on looking for blocks dominated by DOM.  */
21341120Sjdp          new_occ = occ_new (dom, new_occ);
21441120Sjdp	}
215103976Spst
216103976Spst      else
217103976Spst	{
21841120Sjdp	  /* Nothing special, go on with the next element.  */
219103976Spst	  p_occ = &occ->next;
22041120Sjdp	}
22141120Sjdp    }
222103976Spst
22341120Sjdp  /* No place was found as a child of IDOM.  Make BB a sibling of IDOM.  */
22441120Sjdp  new_occ->next = *p_head;
22541120Sjdp  *p_head = new_occ;
22641120Sjdp}
22741120Sjdp
22841120Sjdp/* Register that we found a division in BB.  */
22941120Sjdp
23041120Sjdpstatic inline void
23141120Sjdpregister_division_in (basic_block bb)
23241120Sjdp{
23341120Sjdp  struct occurrence *occ;
23441120Sjdp
23541120Sjdp  occ = (struct occurrence *) bb->aux;
23641120Sjdp  if (!occ)
23741120Sjdp    {
23841120Sjdp      occ = occ_new (bb, NULL);
23941120Sjdp      insert_bb (occ, ENTRY_BLOCK_PTR, &occ_head);
24041120Sjdp    }
24141120Sjdp
24241120Sjdp  occ->bb_has_division = true;
24341120Sjdp  occ->num_divisions++;
24441120Sjdp}
24541120Sjdp
24641120Sjdp
24741120Sjdp/* Compute the number of divisions that postdominate each block in OCC and
24841120Sjdp   its children.  */
24941120Sjdp
25041120Sjdpstatic void
25141120Sjdpcompute_merit (struct occurrence *occ)
25241120Sjdp{
25341120Sjdp  struct occurrence *occ_child;
25441120Sjdp  basic_block dom = occ->bb;
25541120Sjdp
25641120Sjdp  for (occ_child = occ->children; occ_child; occ_child = occ_child->next)
25741120Sjdp    {
25841120Sjdp      basic_block bb;
259141918Sstefanf      if (occ_child->children)
26041120Sjdp        compute_merit (occ_child);
26141120Sjdp
26241120Sjdp      if (flag_exceptions)
26341120Sjdp	bb = single_noncomplex_succ (dom);
26441120Sjdp      else
26541120Sjdp	bb = dom;
26641120Sjdp
26741120Sjdp      if (dominated_by_p (CDI_POST_DOMINATORS, bb, occ_child->bb))
26841120Sjdp        occ->num_divisions += occ_child->num_divisions;
26941120Sjdp    }
27041120Sjdp}
27141120Sjdp
27241120Sjdp
27341120Sjdp/* Return whether USE_STMT is a floating-point division by DEF.  */
27441120Sjdpstatic inline bool
27541120Sjdpis_division_by (tree use_stmt, tree def)
27641120Sjdp{
27741120Sjdp  return TREE_CODE (use_stmt) == MODIFY_EXPR
27841120Sjdp	 && TREE_CODE (TREE_OPERAND (use_stmt, 1)) == RDIV_EXPR
27941120Sjdp	 && TREE_OPERAND (TREE_OPERAND (use_stmt, 1), 1) == def;
28041120Sjdp}
28141120Sjdp
28241120Sjdp/* Walk the subset of the dominator tree rooted at OCC, setting the
28341120Sjdp   RECIP_DEF field to a definition of 1.0 / DEF that can be used in
28441120Sjdp   the given basic block.  The field may be left NULL, of course,
28541120Sjdp   if it is not possible or profitable to do the optimization.
28641120Sjdp
28741120Sjdp   DEF_BSI is an iterator pointing at the statement defining DEF.
28841120Sjdp   If RECIP_DEF is set, a dominator already has a computation that can
28941120Sjdp   be used.  */
29041120Sjdp
29141120Sjdpstatic void
29241120Sjdpinsert_reciprocals (block_stmt_iterator *def_bsi, struct occurrence *occ,
29341120Sjdp		    tree def, tree recip_def, int threshold)
29441120Sjdp{
29541120Sjdp  tree type, new_stmt;
29641120Sjdp  block_stmt_iterator bsi;
29741120Sjdp  struct occurrence *occ_child;
29841120Sjdp
29941120Sjdp  if (!recip_def
30041120Sjdp      && (occ->bb_has_division || !flag_trapping_math)
30141120Sjdp      && occ->num_divisions >= threshold)
30241120Sjdp    {
30341120Sjdp      /* Make a variable with the replacement and substitute it.  */
30441120Sjdp      type = TREE_TYPE (def);
30541120Sjdp      recip_def = make_rename_temp (type, "reciptmp");
30641120Sjdp      new_stmt = build2 (MODIFY_EXPR, void_type_node, recip_def,
30741120Sjdp		         fold_build2 (RDIV_EXPR, type, build_one_cst (type),
30841120Sjdp				      def));
30941120Sjdp
31041120Sjdp
31141120Sjdp      if (occ->bb_has_division)
31241120Sjdp        {
31341120Sjdp          /* Case 1: insert before an existing division.  */
31441120Sjdp          bsi = bsi_after_labels (occ->bb);
31541120Sjdp          while (!bsi_end_p (bsi) && !is_division_by (bsi_stmt (bsi), def))
31641120Sjdp	    bsi_next (&bsi);
31741120Sjdp
31841120Sjdp          bsi_insert_before (&bsi, new_stmt, BSI_SAME_STMT);
31941120Sjdp        }
32041120Sjdp      else if (def_bsi && occ->bb == def_bsi->bb)
32141120Sjdp        {
32241120Sjdp          /* Case 2: insert right after the definition.  Note that this will
32341120Sjdp	     never happen if the definition statement can throw, because in
32441120Sjdp	     that case the sole successor of the statement's basic block will
32541120Sjdp	     dominate all the uses as well.  */
32641120Sjdp          bsi_insert_after (def_bsi, new_stmt, BSI_NEW_STMT);
32741120Sjdp        }
32841120Sjdp      else
32941120Sjdp        {
33041120Sjdp          /* Case 3: insert in a basic block not containing defs/uses.  */
33141120Sjdp          bsi = bsi_after_labels (occ->bb);
33241120Sjdp          bsi_insert_before (&bsi, new_stmt, BSI_SAME_STMT);
33341120Sjdp        }
33441120Sjdp
33541120Sjdp      occ->recip_def_stmt = new_stmt;
33641120Sjdp    }
33741120Sjdp
33841120Sjdp  occ->recip_def = recip_def;
33941120Sjdp  for (occ_child = occ->children; occ_child; occ_child = occ_child->next)
34041120Sjdp    insert_reciprocals (def_bsi, occ_child, def, recip_def, threshold);
34141120Sjdp}
34241120Sjdp
34341120Sjdp
34441120Sjdp/* Replace the division at USE_P with a multiplication by the reciprocal, if
34541120Sjdp   possible.  */
34641120Sjdp
34741120Sjdpstatic inline void
34841120Sjdpreplace_reciprocal (use_operand_p use_p)
34941120Sjdp{
35041120Sjdp  tree use_stmt = USE_STMT (use_p);
35141120Sjdp  basic_block bb = bb_for_stmt (use_stmt);
35241120Sjdp  struct occurrence *occ = (struct occurrence *) bb->aux;
35341120Sjdp
35441120Sjdp  if (occ->recip_def && use_stmt != occ->recip_def_stmt)
35541120Sjdp    {
35641120Sjdp      TREE_SET_CODE (TREE_OPERAND (use_stmt, 1), MULT_EXPR);
35741120Sjdp      SET_USE (use_p, occ->recip_def);
35841120Sjdp      fold_stmt_inplace (use_stmt);
35941120Sjdp      update_stmt (use_stmt);
36041120Sjdp    }
36141120Sjdp}
36241120Sjdp
36341120Sjdp
36441120Sjdp/* Free OCC and return one more "struct occurrence" to be freed.  */
36541120Sjdp
36641120Sjdpstatic struct occurrence *
36741120Sjdpfree_bb (struct occurrence *occ)
36841120Sjdp{
36941120Sjdp  struct occurrence *child, *next;
37041120Sjdp
37141120Sjdp  /* First get the two pointers hanging off OCC.  */
37241120Sjdp  next = occ->next;
37341120Sjdp  child = occ->children;
37441120Sjdp  occ->bb->aux = NULL;
37541120Sjdp  pool_free (occ_pool, occ);
37641120Sjdp
37741120Sjdp  /* Now ensure that we don't recurse unless it is necessary.  */
37841120Sjdp  if (!child)
37941120Sjdp    return next;
38041120Sjdp  else
38141120Sjdp    {
38241120Sjdp      while (next)
38341120Sjdp	next = free_bb (next);
38441120Sjdp
38541120Sjdp      return child;
38641120Sjdp    }
38741120Sjdp}
38841120Sjdp
38941120Sjdp
39041120Sjdp/* Look for floating-point divisions among DEF's uses, and try to
39141120Sjdp   replace them by multiplications with the reciprocal.  Add
39241120Sjdp   as many statements computing the reciprocal as needed.
39341120Sjdp
39441120Sjdp   DEF must be a GIMPLE register of a floating-point type.  */
39541120Sjdp
39641120Sjdpstatic void
39741120Sjdpexecute_cse_reciprocals_1 (block_stmt_iterator *def_bsi, tree def)
39841120Sjdp{
39941120Sjdp  use_operand_p use_p;
40041120Sjdp  imm_use_iterator use_iter;
40141120Sjdp  struct occurrence *occ;
40241120Sjdp  int count = 0, threshold;
40341120Sjdp
40441120Sjdp  gcc_assert (FLOAT_TYPE_P (TREE_TYPE (def)) && is_gimple_reg (def));
40541120Sjdp
40641120Sjdp  FOR_EACH_IMM_USE_FAST (use_p, use_iter, def)
40741120Sjdp    {
40841120Sjdp      tree use_stmt = USE_STMT (use_p);
40941120Sjdp      if (is_division_by (use_stmt, def))
41041120Sjdp	{
41141120Sjdp	  register_division_in (bb_for_stmt (use_stmt));
41241120Sjdp	  count++;
41341120Sjdp	}
41441120Sjdp    }
41541120Sjdp
41641120Sjdp  /* Do the expensive part only if we can hope to optimize something.  */
41741120Sjdp  threshold = targetm.min_divisions_for_recip_mul (TYPE_MODE (TREE_TYPE (def)));
41841120Sjdp  if (count >= threshold)
41941120Sjdp    {
42041120Sjdp      tree use_stmt;
42141120Sjdp      for (occ = occ_head; occ; occ = occ->next)
42241120Sjdp	{
42341120Sjdp	  compute_merit (occ);
42441120Sjdp	  insert_reciprocals (def_bsi, occ, def, NULL, threshold);
42541120Sjdp	}
42641120Sjdp
42741120Sjdp      FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, def)
42841120Sjdp	{
42941120Sjdp	  if (is_division_by (use_stmt, def))
43041120Sjdp	    {
43141120Sjdp	      FOR_EACH_IMM_USE_ON_STMT (use_p, use_iter)
43241120Sjdp		replace_reciprocal (use_p);
43341120Sjdp	    }
43441120Sjdp	}
43541120Sjdp    }
43641120Sjdp
43741120Sjdp  for (occ = occ_head; occ; )
43841120Sjdp    occ = free_bb (occ);
43941120Sjdp
44041120Sjdp  occ_head = NULL;
44141120Sjdp}
44241120Sjdp
443103976Spst
444103976Spststatic bool
445103976Spstgate_cse_reciprocals (void)
446103976Spst{
447103976Spst  return optimize && !optimize_size && flag_unsafe_math_optimizations;
448103976Spst}
449103976Spst
450103976Spst
45141120Sjdp/* Go through all the floating-point SSA_NAMEs, and call
45241120Sjdp   execute_cse_reciprocals_1 on each of them.  */
45341120Sjdpstatic unsigned int
45441120Sjdpexecute_cse_reciprocals (void)
45541120Sjdp{
45641120Sjdp  basic_block bb;
457103976Spst  tree arg;
458103976Spst
45941120Sjdp  occ_pool = create_alloc_pool ("dominators for recip",
46041120Sjdp				sizeof (struct occurrence),
461103976Spst				n_basic_blocks / 3 + 1);
462103976Spst
463103976Spst  calculate_dominance_info (CDI_DOMINATORS);
46441120Sjdp  calculate_dominance_info (CDI_POST_DOMINATORS);
46541120Sjdp
46641120Sjdp#ifdef ENABLE_CHECKING
46741120Sjdp  FOR_EACH_BB (bb)
46841120Sjdp    gcc_assert (!bb->aux);
46941120Sjdp#endif
47041120Sjdp
47141120Sjdp  for (arg = DECL_ARGUMENTS (cfun->decl); arg; arg = TREE_CHAIN (arg))
47241120Sjdp    if (default_def (arg)
47341120Sjdp	&& FLOAT_TYPE_P (TREE_TYPE (arg))
47441120Sjdp	&& is_gimple_reg (arg))
47541120Sjdp      execute_cse_reciprocals_1 (NULL, default_def (arg));
47641120Sjdp
47741120Sjdp  FOR_EACH_BB (bb)
47841120Sjdp    {
47941120Sjdp      block_stmt_iterator bsi;
48041120Sjdp      tree phi, def;
48141120Sjdp
48241120Sjdp      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
48341120Sjdp	{
48441120Sjdp	  def = PHI_RESULT (phi);
48541120Sjdp	  if (FLOAT_TYPE_P (TREE_TYPE (def))
48641120Sjdp	      && is_gimple_reg (def))
48741120Sjdp	    execute_cse_reciprocals_1 (NULL, def);
48841120Sjdp	}
48941120Sjdp
49041120Sjdp      for (bsi = bsi_after_labels (bb); !bsi_end_p (bsi); bsi_next (&bsi))
49141120Sjdp        {
49241120Sjdp	  tree stmt = bsi_stmt (bsi);
49341120Sjdp	  if (TREE_CODE (stmt) == MODIFY_EXPR
49441120Sjdp	      && (def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF)) != NULL
49541120Sjdp	      && FLOAT_TYPE_P (TREE_TYPE (def))
49641120Sjdp	      && TREE_CODE (def) == SSA_NAME)
49741120Sjdp	    execute_cse_reciprocals_1 (&bsi, def);
49841120Sjdp	}
49941120Sjdp    }
50041120Sjdp
50141120Sjdp  free_dominance_info (CDI_DOMINATORS);
50241120Sjdp  free_dominance_info (CDI_POST_DOMINATORS);
50341120Sjdp  free_alloc_pool (occ_pool);
50441120Sjdp  return 0;
50541120Sjdp}
50641120Sjdp
50741120Sjdpstruct tree_opt_pass pass_cse_reciprocals =
50841120Sjdp{
50941120Sjdp  "recip",				/* name */
51041120Sjdp  gate_cse_reciprocals,			/* gate */
51141120Sjdp  execute_cse_reciprocals,		/* execute */
51241120Sjdp  NULL,					/* sub */
51341120Sjdp  NULL,					/* next */
51441120Sjdp  0,					/* static_pass_number */
51541120Sjdp  0,					/* tv_id */
51641120Sjdp  PROP_ssa,				/* properties_required */
51741120Sjdp  0,					/* properties_provided */
51841120Sjdp  0,					/* properties_destroyed */
51941120Sjdp  0,					/* todo_flags_start */
52041120Sjdp  TODO_dump_func | TODO_update_ssa | TODO_verify_ssa
52141120Sjdp    | TODO_verify_stmts,                /* todo_flags_finish */
52241120Sjdp  0				        /* letter */
52341120Sjdp};
52441120Sjdp