1 /* Global, SSA-based optimizations using mathematical identities.
2 Copyright (C) 2005 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. */
42 #include "coretypes.h"
46 #include "tree-flow.h"
49 #include "tree-pass.h"
52 gate_cse_reciprocals (void)
54 return optimize
&& !optimize_size
&& flag_unsafe_math_optimizations
;
57 /* Where to put the statement computing a reciprocal. */
60 PR_BEFORE_BSI
, /* Put it using bsi_insert_before. */
61 PR_AFTER_BSI
, /* Put it using bsi_insert_after. */
62 PR_ON_ENTRY_EDGE
/* Put it on the edge between the entry
63 and the first basic block. */
66 /* Check if DEF's uses include more than one floating-point division,
67 and if so replace them by multiplications with the reciprocal. Add
68 the statement computing the reciprocal according to WHERE.
70 Does not check the type of DEF, nor that DEF is a GIMPLE register.
71 This is done in the caller for speed, because otherwise this routine
72 would be called for every definition and phi node. */
74 execute_cse_reciprocals_1 (block_stmt_iterator
*bsi
, tree def
,
75 enum place_reciprocal where
)
78 imm_use_iterator use_iter
;
79 tree t
, new_stmt
, type
;
81 bool ok
= !flag_trapping_math
;
84 FOR_EACH_IMM_USE_FAST (use_p
, use_iter
, def
)
86 tree use_stmt
= USE_STMT (use_p
);
87 if (TREE_CODE (use_stmt
) == MODIFY_EXPR
88 && TREE_CODE (TREE_OPERAND (use_stmt
, 1)) == RDIV_EXPR
89 && TREE_OPERAND (TREE_OPERAND (use_stmt
, 1), 1) == def
)
92 /* Check if this use post-dominates the insertion point. */
93 if (ok
|| dominated_by_p (CDI_POST_DOMINATORS
, bsi
->bb
,
94 bb_for_stmt (use_stmt
)))
101 if (count
< 2 || !ok
)
104 /* Make a variable with the replacement and substitute it. */
105 type
= TREE_TYPE (def
);
106 t
= make_rename_temp (type
, "reciptmp");
107 new_stmt
= build2 (MODIFY_EXPR
, void_type_node
, t
,
108 fold_build2 (RDIV_EXPR
, type
, build_real (type
, dconst1
),
111 if (where
== PR_BEFORE_BSI
)
112 bsi_insert_before (bsi
, new_stmt
, BSI_SAME_STMT
);
113 else if (where
== PR_AFTER_BSI
)
114 bsi_insert_after (bsi
, new_stmt
, BSI_NEW_STMT
);
115 else if (where
== PR_ON_ENTRY_EDGE
)
116 bsi_insert_on_edge (single_succ_edge (ENTRY_BLOCK_PTR
), new_stmt
);
120 FOR_EACH_IMM_USE_SAFE (use_p
, use_iter
, def
)
122 tree use_stmt
= USE_STMT (use_p
);
123 if (use_stmt
!= new_stmt
124 && TREE_CODE (use_stmt
) == MODIFY_EXPR
125 && TREE_CODE (TREE_OPERAND (use_stmt
, 1)) == RDIV_EXPR
126 && TREE_OPERAND (TREE_OPERAND (use_stmt
, 1), 1) == def
)
128 TREE_SET_CODE (TREE_OPERAND (use_stmt
, 1), MULT_EXPR
);
135 execute_cse_reciprocals (void)
140 if (flag_trapping_math
)
141 calculate_dominance_info (CDI_POST_DOMINATORS
);
143 if (single_succ_p (ENTRY_BLOCK_PTR
))
144 for (arg
= DECL_ARGUMENTS (cfun
->decl
); arg
; arg
= TREE_CHAIN (arg
))
145 if (default_def (arg
))
147 block_stmt_iterator bsi
;
148 bsi
= bsi_start (single_succ (ENTRY_BLOCK_PTR
));
149 execute_cse_reciprocals_1 (&bsi
, default_def (arg
),
155 block_stmt_iterator bsi
;
157 for (bsi
= bsi_start (bb
);
158 !bsi_end_p (bsi
) && TREE_CODE (bsi_stmt (bsi
)) == LABEL_EXPR
;
162 for (phi
= phi_nodes (bb
); phi
; phi
= PHI_CHAIN (phi
))
164 def
= PHI_RESULT (phi
);
165 if (FLOAT_TYPE_P (TREE_TYPE (def
))
166 && is_gimple_reg (def
))
167 execute_cse_reciprocals_1 (&bsi
, def
, PR_BEFORE_BSI
);
170 for (; !bsi_end_p (bsi
); bsi_next (&bsi
))
172 tree stmt
= bsi_stmt (bsi
);
173 if (TREE_CODE (stmt
) == MODIFY_EXPR
174 && (def
= SINGLE_SSA_TREE_OPERAND (stmt
, SSA_OP_DEF
)) != NULL
175 && FLOAT_TYPE_P (TREE_TYPE (def
))
176 && TREE_CODE (def
) == SSA_NAME
)
177 execute_cse_reciprocals_1 (&bsi
, def
, PR_AFTER_BSI
);
181 if (flag_trapping_math
)
182 free_dominance_info (CDI_POST_DOMINATORS
);
184 if (single_succ_p (ENTRY_BLOCK_PTR
))
185 bsi_commit_one_edge_insert (single_succ_edge (ENTRY_BLOCK_PTR
), NULL
);
188 struct tree_opt_pass pass_cse_reciprocals
=
191 gate_cse_reciprocals
, /* gate */
192 execute_cse_reciprocals
, /* execute */
195 0, /* static_pass_number */
197 PROP_ssa
, /* properties_required */
198 0, /* properties_provided */
199 0, /* properties_destroyed */
200 0, /* todo_flags_start */
201 TODO_dump_func
| TODO_update_ssa
| TODO_verify_ssa
202 | TODO_verify_stmts
, /* todo_flags_finish */