PR tree-opt/22237
[official-gcc.git] / gcc / tree-ssa-math-opts.c
blob456043fc3f45f30355f7b5d84975e81dd7a7c719
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
9 later version.
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
14 for more details.
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
19 02110-1301, USA. */
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);
25 x = x / modulus;
26 y = y / modulus;
27 z = z / modulus;
29 that can be optimized to
31 modulus = sqrt(x*x + y*y + z*z);
32 rmodulus = 1.0 / modulus;
33 x = x * rmodulus;
34 y = y * rmodulus;
35 z = z * rmodulus;
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 #include "config.h"
41 #include "system.h"
42 #include "coretypes.h"
43 #include "tm.h"
44 #include "flags.h"
45 #include "tree.h"
46 #include "tree-flow.h"
47 #include "real.h"
48 #include "timevar.h"
49 #include "tree-pass.h"
51 static bool
52 gate_cse_reciprocals (void)
54 return optimize && !optimize_size && flag_unsafe_math_optimizations;
57 /* Where to put the statement computing a reciprocal. */
58 enum place_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. */
73 static void
74 execute_cse_reciprocals_1 (block_stmt_iterator *bsi, tree def,
75 enum place_reciprocal where)
77 use_operand_p use_p;
78 imm_use_iterator use_iter;
79 tree t, new_stmt, type;
80 int count = 0;
81 bool ok = !flag_trapping_math;
83 /* Find uses. */
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)
91 ++count;
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)))
95 ok = true;
97 if (count >= 2 && ok)
98 break;
101 if (count < 2 || !ok)
102 return;
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),
109 def));
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);
117 else
118 gcc_unreachable ();
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);
129 SET_USE (use_p, t);
134 static void
135 execute_cse_reciprocals (void)
137 basic_block bb;
138 tree arg;
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),
150 PR_ON_ENTRY_EDGE);
153 FOR_EACH_BB (bb)
155 block_stmt_iterator bsi;
156 tree phi, def;
157 for (bsi = bsi_start (bb);
158 !bsi_end_p (bsi) && TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR;
159 bsi_next (&bsi))
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 =
190 "recip", /* name */
191 gate_cse_reciprocals, /* gate */
192 execute_cse_reciprocals, /* execute */
193 NULL, /* sub */
194 NULL, /* next */
195 0, /* static_pass_number */
196 0, /* tv_id */
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 */
203 0 /* letter */