1 /* Global, SSA-based optimizations using mathematical identities.
2 Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21 /* Currently, the only mini-pass in this file tries to CSE reciprocal
22 operations. These are common in sequences such as this one:
24 modulus = sqrt(x*x + y*y + z*z);
29 that can be optimized to
31 modulus = sqrt(x*x + y*y + z*z);
32 rmodulus = 1.0 / modulus;
37 We do this for loop invariant divisors, and with this pass whenever
38 we notice that a division has the same divisor multiple times.
40 Of course, like in PRE, we don't insert a division if a dominator
41 already has one. However, this cannot be done as an extension of
42 PRE for several reasons.
44 First of all, with some experiments it was found out that the
45 transformation is not always useful if there are only two divisions
46 hy the same divisor. This is probably because modern processors
47 can pipeline the divisions; on older, in-order processors it should
48 still be effective to optimize two divisions by the same number.
49 We make this a param, and it shall be called N in the remainder of
52 Second, if trapping math is active, we have less freedom on where
53 to insert divisions: we can only do so in basic blocks that already
54 contain one. (If divisions don't trap, instead, we can insert
55 divisions elsewhere, which will be in blocks that are common dominators
56 of those that have the division).
58 We really don't want to compute the reciprocal unless a division will
59 be found. To do this, we won't insert the division in a basic block
60 that has less than N divisions *post-dominating* it.
62 The algorithm constructs a subset of the dominator tree, holding the
63 blocks containing the divisions and the common dominators to them,
64 and walk it twice. The first walk is in post-order, and it annotates
65 each block with the number of divisions that post-dominate it: this
66 gives information on where divisions can be inserted profitably.
67 The second walk is in pre-order, and it inserts divisions as explained
68 above, and replaces divisions by multiplications.
70 In the best case, the cost of the pass is O(n_statements). In the
71 worst-case, the cost is due to creating the dominator tree subset,
72 with a cost of O(n_basic_blocks ^ 2); however this can only happen
73 for n_statements / n_basic_blocks statements. So, the amortized cost
74 of creating the dominator tree subset is O(n_basic_blocks) and the
75 worst-case cost of the pass is O(n_statements * n_basic_blocks).
77 More practically, the cost will be small because there are few
78 divisions, and they tend to be in the same basic block, so insert_bb
79 is called very few times.
81 If we did this using domwalk.c, an efficient implementation would have
82 to work on all the variables in a single pass, because we could not
83 work on just a subset of the dominator tree, as we do now, and the
84 cost would also be something like O(n_statements * n_basic_blocks).
85 The data structures would be more complex in order to work on all the
86 variables in a single pass. */
90 #include "coretypes.h"
94 #include "tree-flow.h"
97 #include "tree-pass.h"
98 #include "alloc-pool.h"
99 #include "basic-block.h"
103 /* This structure represents one basic block that either computes a
104 division, or is a common dominator for basic block that compute a
107 /* The basic block represented by this structure. */
110 /* If non-NULL, the SSA_NAME holding the definition for a reciprocal
114 /* If non-NULL, the GIMPLE_MODIFY_STMT for a reciprocal computation that
115 was inserted in BB. */
118 /* Pointer to a list of "struct occurrence"s for blocks dominated
120 struct occurrence
*children
;
122 /* Pointer to the next "struct occurrence"s in the list of blocks
123 sharing a common dominator. */
124 struct occurrence
*next
;
126 /* The number of divisions that are in BB before compute_merit. The
127 number of divisions that are in BB or post-dominate it after
131 /* True if the basic block has a division, false if it is a common
132 dominator for basic blocks that do. If it is false and trapping
133 math is active, BB is not a candidate for inserting a reciprocal. */
134 bool bb_has_division
;
138 /* The instance of "struct occurrence" representing the highest
139 interesting block in the dominator tree. */
140 static struct occurrence
*occ_head
;
142 /* Allocation pool for getting instances of "struct occurrence". */
143 static alloc_pool occ_pool
;
147 /* Allocate and return a new struct occurrence for basic block BB, and
148 whose children list is headed by CHILDREN. */
149 static struct occurrence
*
150 occ_new (basic_block bb
, struct occurrence
*children
)
152 struct occurrence
*occ
;
154 bb
->aux
= occ
= (struct occurrence
*) pool_alloc (occ_pool
);
155 memset (occ
, 0, sizeof (struct occurrence
));
158 occ
->children
= children
;
163 /* Insert NEW_OCC into our subset of the dominator tree. P_HEAD points to a
164 list of "struct occurrence"s, one per basic block, having IDOM as
165 their common dominator.
167 We try to insert NEW_OCC as deep as possible in the tree, and we also
168 insert any other block that is a common dominator for BB and one
169 block already in the tree. */
172 insert_bb (struct occurrence
*new_occ
, basic_block idom
,
173 struct occurrence
**p_head
)
175 struct occurrence
*occ
, **p_occ
;
177 for (p_occ
= p_head
; (occ
= *p_occ
) != NULL
; )
179 basic_block bb
= new_occ
->bb
, occ_bb
= occ
->bb
;
180 basic_block dom
= nearest_common_dominator (CDI_DOMINATORS
, occ_bb
, bb
);
183 /* BB dominates OCC_BB. OCC becomes NEW_OCC's child: remove OCC
186 occ
->next
= new_occ
->children
;
187 new_occ
->children
= occ
;
189 /* Try the next block (it may as well be dominated by BB). */
192 else if (dom
== occ_bb
)
194 /* OCC_BB dominates BB. Tail recurse to look deeper. */
195 insert_bb (new_occ
, dom
, &occ
->children
);
199 else if (dom
!= idom
)
201 gcc_assert (!dom
->aux
);
203 /* There is a dominator between IDOM and BB, add it and make
204 two children out of NEW_OCC and OCC. First, remove OCC from
210 /* None of the previous blocks has DOM as a dominator: if we tail
211 recursed, we would reexamine them uselessly. Just switch BB with
212 DOM, and go on looking for blocks dominated by DOM. */
213 new_occ
= occ_new (dom
, new_occ
);
218 /* Nothing special, go on with the next element. */
223 /* No place was found as a child of IDOM. Make BB a sibling of IDOM. */
224 new_occ
->next
= *p_head
;
228 /* Register that we found a division in BB. */
231 register_division_in (basic_block bb
)
233 struct occurrence
*occ
;
235 occ
= (struct occurrence
*) bb
->aux
;
238 occ
= occ_new (bb
, NULL
);
239 insert_bb (occ
, ENTRY_BLOCK_PTR
, &occ_head
);
242 occ
->bb_has_division
= true;
243 occ
->num_divisions
++;
247 /* Compute the number of divisions that postdominate each block in OCC and
251 compute_merit (struct occurrence
*occ
)
253 struct occurrence
*occ_child
;
254 basic_block dom
= occ
->bb
;
256 for (occ_child
= occ
->children
; occ_child
; occ_child
= occ_child
->next
)
259 if (occ_child
->children
)
260 compute_merit (occ_child
);
263 bb
= single_noncomplex_succ (dom
);
267 if (dominated_by_p (CDI_POST_DOMINATORS
, bb
, occ_child
->bb
))
268 occ
->num_divisions
+= occ_child
->num_divisions
;
273 /* Return whether USE_STMT is a floating-point division by DEF. */
275 is_division_by (tree use_stmt
, tree def
)
277 return TREE_CODE (use_stmt
) == GIMPLE_MODIFY_STMT
278 && TREE_CODE (GIMPLE_STMT_OPERAND (use_stmt
, 1)) == RDIV_EXPR
279 && TREE_OPERAND (GIMPLE_STMT_OPERAND (use_stmt
, 1), 1) == def
;
282 /* Walk the subset of the dominator tree rooted at OCC, setting the
283 RECIP_DEF field to a definition of 1.0 / DEF that can be used in
284 the given basic block. The field may be left NULL, of course,
285 if it is not possible or profitable to do the optimization.
287 DEF_BSI is an iterator pointing at the statement defining DEF.
288 If RECIP_DEF is set, a dominator already has a computation that can
292 insert_reciprocals (block_stmt_iterator
*def_bsi
, struct occurrence
*occ
,
293 tree def
, tree recip_def
, int threshold
)
296 block_stmt_iterator bsi
;
297 struct occurrence
*occ_child
;
300 && (occ
->bb_has_division
|| !flag_trapping_math
)
301 && occ
->num_divisions
>= threshold
)
303 /* Make a variable with the replacement and substitute it. */
304 type
= TREE_TYPE (def
);
305 recip_def
= make_rename_temp (type
, "reciptmp");
306 new_stmt
= build_gimple_modify_stmt (recip_def
,
307 fold_build2 (RDIV_EXPR
, type
,
308 build_one_cst (type
),
312 if (occ
->bb_has_division
)
314 /* Case 1: insert before an existing division. */
315 bsi
= bsi_after_labels (occ
->bb
);
316 while (!bsi_end_p (bsi
) && !is_division_by (bsi_stmt (bsi
), def
))
319 bsi_insert_before (&bsi
, new_stmt
, BSI_SAME_STMT
);
321 else if (def_bsi
&& occ
->bb
== def_bsi
->bb
)
323 /* Case 2: insert right after the definition. Note that this will
324 never happen if the definition statement can throw, because in
325 that case the sole successor of the statement's basic block will
326 dominate all the uses as well. */
327 bsi_insert_after (def_bsi
, new_stmt
, BSI_NEW_STMT
);
331 /* Case 3: insert in a basic block not containing defs/uses. */
332 bsi
= bsi_after_labels (occ
->bb
);
333 bsi_insert_before (&bsi
, new_stmt
, BSI_SAME_STMT
);
336 occ
->recip_def_stmt
= new_stmt
;
339 occ
->recip_def
= recip_def
;
340 for (occ_child
= occ
->children
; occ_child
; occ_child
= occ_child
->next
)
341 insert_reciprocals (def_bsi
, occ_child
, def
, recip_def
, threshold
);
345 /* Replace the division at USE_P with a multiplication by the reciprocal, if
349 replace_reciprocal (use_operand_p use_p
)
351 tree use_stmt
= USE_STMT (use_p
);
352 basic_block bb
= bb_for_stmt (use_stmt
);
353 struct occurrence
*occ
= (struct occurrence
*) bb
->aux
;
355 if (occ
->recip_def
&& use_stmt
!= occ
->recip_def_stmt
)
357 TREE_SET_CODE (GIMPLE_STMT_OPERAND (use_stmt
, 1), MULT_EXPR
);
358 SET_USE (use_p
, occ
->recip_def
);
359 fold_stmt_inplace (use_stmt
);
360 update_stmt (use_stmt
);
365 /* Free OCC and return one more "struct occurrence" to be freed. */
367 static struct occurrence
*
368 free_bb (struct occurrence
*occ
)
370 struct occurrence
*child
, *next
;
372 /* First get the two pointers hanging off OCC. */
374 child
= occ
->children
;
376 pool_free (occ_pool
, occ
);
378 /* Now ensure that we don't recurse unless it is necessary. */
384 next
= free_bb (next
);
391 /* Look for floating-point divisions among DEF's uses, and try to
392 replace them by multiplications with the reciprocal. Add
393 as many statements computing the reciprocal as needed.
395 DEF must be a GIMPLE register of a floating-point type. */
398 execute_cse_reciprocals_1 (block_stmt_iterator
*def_bsi
, tree def
)
401 imm_use_iterator use_iter
;
402 struct occurrence
*occ
;
403 int count
= 0, threshold
;
405 gcc_assert (FLOAT_TYPE_P (TREE_TYPE (def
)) && is_gimple_reg (def
));
407 FOR_EACH_IMM_USE_FAST (use_p
, use_iter
, def
)
409 tree use_stmt
= USE_STMT (use_p
);
410 if (is_division_by (use_stmt
, def
))
412 register_division_in (bb_for_stmt (use_stmt
));
417 /* Do the expensive part only if we can hope to optimize something. */
418 threshold
= targetm
.min_divisions_for_recip_mul (TYPE_MODE (TREE_TYPE (def
)));
419 if (count
>= threshold
)
422 for (occ
= occ_head
; occ
; occ
= occ
->next
)
425 insert_reciprocals (def_bsi
, occ
, def
, NULL
, threshold
);
428 FOR_EACH_IMM_USE_STMT (use_stmt
, use_iter
, def
)
430 if (is_division_by (use_stmt
, def
))
432 FOR_EACH_IMM_USE_ON_STMT (use_p
, use_iter
)
433 replace_reciprocal (use_p
);
438 for (occ
= occ_head
; occ
; )
445 gate_cse_reciprocals (void)
447 return optimize
&& !optimize_size
&& flag_unsafe_math_optimizations
;
450 /* Go through all the floating-point SSA_NAMEs, and call
451 execute_cse_reciprocals_1 on each of them. */
453 execute_cse_reciprocals (void)
458 occ_pool
= create_alloc_pool ("dominators for recip",
459 sizeof (struct occurrence
),
460 n_basic_blocks
/ 3 + 1);
462 calculate_dominance_info (CDI_DOMINATORS
);
463 calculate_dominance_info (CDI_POST_DOMINATORS
);
465 #ifdef ENABLE_CHECKING
467 gcc_assert (!bb
->aux
);
470 for (arg
= DECL_ARGUMENTS (cfun
->decl
); arg
; arg
= TREE_CHAIN (arg
))
471 if (gimple_default_def (cfun
, arg
)
472 && FLOAT_TYPE_P (TREE_TYPE (arg
))
473 && is_gimple_reg (arg
))
474 execute_cse_reciprocals_1 (NULL
, gimple_default_def (cfun
, arg
));
478 block_stmt_iterator bsi
;
481 for (phi
= phi_nodes (bb
); phi
; phi
= PHI_CHAIN (phi
))
483 def
= PHI_RESULT (phi
);
484 if (FLOAT_TYPE_P (TREE_TYPE (def
))
485 && is_gimple_reg (def
))
486 execute_cse_reciprocals_1 (NULL
, def
);
489 for (bsi
= bsi_after_labels (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
491 tree stmt
= bsi_stmt (bsi
);
493 if (TREE_CODE (stmt
) == GIMPLE_MODIFY_STMT
494 && (def
= SINGLE_SSA_TREE_OPERAND (stmt
, SSA_OP_DEF
)) != NULL
495 && FLOAT_TYPE_P (TREE_TYPE (def
))
496 && TREE_CODE (def
) == SSA_NAME
)
497 execute_cse_reciprocals_1 (&bsi
, def
);
500 /* Scan for a/func(b) and convert it to reciprocal a*rfunc(b). */
501 for (bsi
= bsi_after_labels (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
503 tree stmt
= bsi_stmt (bsi
);
506 if (TREE_CODE (stmt
) == GIMPLE_MODIFY_STMT
507 && TREE_CODE (GIMPLE_STMT_OPERAND (stmt
, 1)) == RDIV_EXPR
)
509 tree arg1
= TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt
, 1), 1);
510 tree stmt1
= SSA_NAME_DEF_STMT (arg1
);
512 if (TREE_CODE (stmt1
) == GIMPLE_MODIFY_STMT
513 && TREE_CODE (GIMPLE_STMT_OPERAND (stmt1
, 1)) == CALL_EXPR
515 = get_callee_fndecl (GIMPLE_STMT_OPERAND (stmt1
, 1)))
516 && (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
517 || DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_MD
))
519 enum built_in_function code
;
523 code
= DECL_FUNCTION_CODE (fndecl
);
524 fndecl
= targetm
.builtin_reciprocal (code
, false);
528 arg10
= CALL_EXPR_ARG (GIMPLE_STMT_OPERAND (stmt1
, 1), 0);
529 tmp
= build_call_expr (fndecl
, 1, arg10
);
530 GIMPLE_STMT_OPERAND (stmt1
, 1) = tmp
;
533 TREE_SET_CODE (GIMPLE_STMT_OPERAND (stmt
, 1), MULT_EXPR
);
534 fold_stmt_inplace (stmt
);
541 free_dominance_info (CDI_DOMINATORS
);
542 free_dominance_info (CDI_POST_DOMINATORS
);
543 free_alloc_pool (occ_pool
);
547 struct tree_opt_pass pass_cse_reciprocals
=
550 gate_cse_reciprocals
, /* gate */
551 execute_cse_reciprocals
, /* execute */
554 0, /* static_pass_number */
556 PROP_ssa
, /* properties_required */
557 0, /* properties_provided */
558 0, /* properties_destroyed */
559 0, /* todo_flags_start */
560 TODO_dump_func
| TODO_update_ssa
| TODO_verify_ssa
561 | TODO_verify_stmts
, /* todo_flags_finish */
565 /* Records an occurrence at statement USE_STMT in the vector of trees
566 STMTS if it is dominated by *TOP_BB or dominates it or this basic block
567 is not yet initialized. Returns true if the occurrence was pushed on
568 the vector. Adjusts *TOP_BB to be the basic block dominating all
569 statements in the vector. */
572 maybe_record_sincos (VEC(tree
, heap
) **stmts
,
573 basic_block
*top_bb
, tree use_stmt
)
575 basic_block use_bb
= bb_for_stmt (use_stmt
);
577 && (*top_bb
== use_bb
578 || dominated_by_p (CDI_DOMINATORS
, use_bb
, *top_bb
)))
579 VEC_safe_push (tree
, heap
, *stmts
, use_stmt
);
581 || dominated_by_p (CDI_DOMINATORS
, *top_bb
, use_bb
))
583 VEC_safe_push (tree
, heap
, *stmts
, use_stmt
);
592 /* Look for sin, cos and cexpi calls with the same argument NAME and
593 create a single call to cexpi CSEing the result in this case.
594 We first walk over all immediate uses of the argument collecting
595 statements that we can CSE in a vector and in a second pass replace
596 the statement rhs with a REALPART or IMAGPART expression on the
597 result of the cexpi call we insert before the use statement that
598 dominates all other candidates. */
601 execute_cse_sincos_1 (tree name
)
603 block_stmt_iterator bsi
;
604 imm_use_iterator use_iter
;
605 tree def_stmt
, use_stmt
, fndecl
, res
, call
, stmt
, type
;
606 int seen_cos
= 0, seen_sin
= 0, seen_cexpi
= 0;
607 VEC(tree
, heap
) *stmts
= NULL
;
608 basic_block top_bb
= NULL
;
611 type
= TREE_TYPE (name
);
612 FOR_EACH_IMM_USE_STMT (use_stmt
, use_iter
, name
)
614 if (TREE_CODE (use_stmt
) != GIMPLE_MODIFY_STMT
615 || TREE_CODE (GIMPLE_STMT_OPERAND (use_stmt
, 1)) != CALL_EXPR
616 || !(fndecl
= get_callee_fndecl (GIMPLE_STMT_OPERAND (use_stmt
, 1)))
617 || DECL_BUILT_IN_CLASS (fndecl
) != BUILT_IN_NORMAL
)
620 switch (DECL_FUNCTION_CODE (fndecl
))
622 CASE_FLT_FN (BUILT_IN_COS
):
623 seen_cos
|= maybe_record_sincos (&stmts
, &top_bb
, use_stmt
) ? 1 : 0;
626 CASE_FLT_FN (BUILT_IN_SIN
):
627 seen_sin
|= maybe_record_sincos (&stmts
, &top_bb
, use_stmt
) ? 1 : 0;
630 CASE_FLT_FN (BUILT_IN_CEXPI
):
631 seen_cexpi
|= maybe_record_sincos (&stmts
, &top_bb
, use_stmt
) ? 1 : 0;
638 if (seen_cos
+ seen_sin
+ seen_cexpi
<= 1)
640 VEC_free(tree
, heap
, stmts
);
644 /* Simply insert cexpi at the beginning of top_bb but not earlier than
645 the name def statement. */
646 fndecl
= mathfn_built_in (type
, BUILT_IN_CEXPI
);
649 res
= make_rename_temp (TREE_TYPE (TREE_TYPE (fndecl
)), "sincostmp");
650 call
= build_call_expr (fndecl
, 1, name
);
651 stmt
= build_gimple_modify_stmt (res
, call
);
652 def_stmt
= SSA_NAME_DEF_STMT (name
);
653 if (bb_for_stmt (def_stmt
) == top_bb
654 && TREE_CODE (def_stmt
) == GIMPLE_MODIFY_STMT
)
656 bsi
= bsi_for_stmt (def_stmt
);
657 bsi_insert_after (&bsi
, stmt
, BSI_SAME_STMT
);
661 bsi
= bsi_after_labels (top_bb
);
662 bsi_insert_before (&bsi
, stmt
, BSI_SAME_STMT
);
666 /* And adjust the recorded old call sites. */
667 for (i
= 0; VEC_iterate(tree
, stmts
, i
, use_stmt
); ++i
)
669 fndecl
= get_callee_fndecl (GIMPLE_STMT_OPERAND (use_stmt
, 1));
670 switch (DECL_FUNCTION_CODE (fndecl
))
672 CASE_FLT_FN (BUILT_IN_COS
):
673 GIMPLE_STMT_OPERAND (use_stmt
, 1) = fold_build1 (REALPART_EXPR
,
677 CASE_FLT_FN (BUILT_IN_SIN
):
678 GIMPLE_STMT_OPERAND (use_stmt
, 1) = fold_build1 (IMAGPART_EXPR
,
682 CASE_FLT_FN (BUILT_IN_CEXPI
):
683 GIMPLE_STMT_OPERAND (use_stmt
, 1) = res
;
690 update_stmt (use_stmt
);
693 VEC_free(tree
, heap
, stmts
);
696 /* Go through all calls to sin, cos and cexpi and call execute_cse_sincos_1
697 on the SSA_NAME argument of each of them. */
700 execute_cse_sincos (void)
704 calculate_dominance_info (CDI_DOMINATORS
);
708 block_stmt_iterator bsi
;
710 for (bsi
= bsi_after_labels (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
712 tree stmt
= bsi_stmt (bsi
);
715 if (TREE_CODE (stmt
) == GIMPLE_MODIFY_STMT
716 && TREE_CODE (GIMPLE_STMT_OPERAND (stmt
, 1)) == CALL_EXPR
717 && (fndecl
= get_callee_fndecl (GIMPLE_STMT_OPERAND (stmt
, 1)))
718 && DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
722 switch (DECL_FUNCTION_CODE (fndecl
))
724 CASE_FLT_FN (BUILT_IN_COS
):
725 CASE_FLT_FN (BUILT_IN_SIN
):
726 CASE_FLT_FN (BUILT_IN_CEXPI
):
727 arg
= GIMPLE_STMT_OPERAND (stmt
, 1);
728 arg
= CALL_EXPR_ARG (arg
, 0);
729 if (TREE_CODE (arg
) == SSA_NAME
)
730 execute_cse_sincos_1 (arg
);
739 free_dominance_info (CDI_DOMINATORS
);
744 gate_cse_sincos (void)
746 /* Make sure we have either sincos or cexp. */
747 return (TARGET_HAS_SINCOS
748 || TARGET_C99_FUNCTIONS
)
752 struct tree_opt_pass pass_cse_sincos
=
755 gate_cse_sincos
, /* gate */
756 execute_cse_sincos
, /* execute */
759 0, /* static_pass_number */
761 PROP_ssa
, /* properties_required */
762 0, /* properties_provided */
763 0, /* properties_destroyed */
764 0, /* todo_flags_start */
765 TODO_dump_func
| TODO_update_ssa
| TODO_verify_ssa
766 | TODO_verify_stmts
, /* todo_flags_finish */
770 /* Find all expressions in the form of sqrt(a/b) and
771 convert them to rsqrt(b/a). */
774 execute_convert_to_rsqrt (void)
780 block_stmt_iterator bsi
;
782 for (bsi
= bsi_after_labels (bb
); !bsi_end_p (bsi
); bsi_next (&bsi
))
784 tree stmt
= bsi_stmt (bsi
);
787 if (TREE_CODE (stmt
) == GIMPLE_MODIFY_STMT
788 && TREE_CODE (GIMPLE_STMT_OPERAND (stmt
, 1)) == CALL_EXPR
789 && (fndecl
= get_callee_fndecl (GIMPLE_STMT_OPERAND (stmt
, 1)))
790 && (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
791 || DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_MD
))
793 enum built_in_function code
;
797 code
= DECL_FUNCTION_CODE (fndecl
);
798 fndecl
= targetm
.builtin_reciprocal (code
, true);
802 arg1
= CALL_EXPR_ARG (GIMPLE_STMT_OPERAND (stmt
, 1), 0);
803 stmt1
= SSA_NAME_DEF_STMT (arg1
);
805 if (TREE_CODE (stmt1
) == GIMPLE_MODIFY_STMT
806 && TREE_CODE (GIMPLE_STMT_OPERAND (stmt1
, 1)) == RDIV_EXPR
)
811 arg10
= TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt1
, 1), 0);
812 arg11
= TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt1
, 1), 1);
814 /* Swap operands of RDIV_EXPR. */
815 TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt1
, 1), 0) = arg11
;
816 TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt1
, 1), 1) = arg10
;
817 fold_stmt_inplace (stmt1
);
820 tmp
= build_call_expr (fndecl
, 1, arg1
);
821 GIMPLE_STMT_OPERAND (stmt
, 1) = tmp
;
832 gate_convert_to_rsqrt (void)
834 return flag_unsafe_math_optimizations
&& optimize
;
837 struct tree_opt_pass pass_convert_to_rsqrt
=
840 gate_convert_to_rsqrt
, /* gate */
841 execute_convert_to_rsqrt
, /* execute */
844 0, /* static_pass_number */
846 PROP_ssa
, /* properties_required */
847 0, /* properties_provided */
848 0, /* properties_destroyed */
849 0, /* todo_flags_start */
850 TODO_dump_func
| TODO_update_ssa
| TODO_verify_ssa
851 | TODO_verify_stmts
, /* todo_flags_finish */