1 /* Forward propagation of single use variables.
2 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License 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
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
23 #include "coretypes.h"
30 #include "basic-block.h"
32 #include "diagnostic.h"
33 #include "tree-flow.h"
34 #include "tree-pass.h"
35 #include "tree-dump.h"
37 /* This pass performs simple forward propagation of single use variables
38 from their definition site into their single use site.
40 Right now we only bother forward propagating into COND_EXPRs since those
41 are relatively common cases where forward propagation creates valid
42 gimple code without the expression needing to fold. i.e.
46 if (x) goto ... else goto ...
48 Will be transformed into:
51 if (a COND b) goto ... else goto ...
53 Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
55 Or (assuming c1 and c2 are constants):
59 if (x EQ/NEQ c2) goto ... else goto ...
61 Will be transformed into:
64 if (a EQ/NEQ (c2 - c1)) goto ... else goto ...
66 Similarly for x = a - c1.
72 if (x) goto ... else goto ...
74 Will be transformed into:
77 if (a == 0) goto ... else goto ...
79 Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
80 For these cases, we propagate A into all, possibly more than one,
81 COND_EXPRs that use X.
87 if (x) goto ... else goto ...
89 Will be transformed into:
92 if (a != 0) goto ... else goto ...
94 (Assuming a is an integral type and x is a boolean or x is an
95 integral and a is a boolean.)
97 Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
98 For these cases, we propagate A into all, possibly more than one,
99 COND_EXPRs that use X.
101 In addition to eliminating the variable and the statement which assigns
102 a value to the variable, we may be able to later thread the jump without
103 adding insane complexity in the dominator optimizer.
105 Also note these transformations can cascade. We handle this by having
106 a worklist of COND_EXPR statements to examine. As we make a change to
107 a statement, we put it back on the worklist to examine on the next
108 iteration of the main loop.
110 This will (of course) be extended as other needs arise. */
112 /* Forward propagate a single-use variable into COND once. Return a
113 new condition if successful. Return NULL_TREE otherwise. */
116 forward_propagate_into_cond_1 (tree cond, tree *test_var_p)
118 tree new_cond = NULL_TREE;
119 enum tree_code cond_code = TREE_CODE (cond);
120 tree test_var = NULL_TREE;
124 /* If the condition is not a lone variable or an equality test of an
125 SSA_NAME against an integral constant, then we do not have an
128 Note these conditions also ensure the COND_EXPR has no
129 virtual operands or other side effects. */
130 if (cond_code != SSA_NAME
131 && !((cond_code == EQ_EXPR || cond_code == NE_EXPR)
132 && TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME
133 && CONSTANT_CLASS_P (TREE_OPERAND (cond, 1))
134 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 1)))))
137 /* Extract the single variable used in the test into TEST_VAR. */
138 if (cond_code == SSA_NAME)
141 test_var = TREE_OPERAND (cond, 0);
143 /* Now get the defining statement for TEST_VAR. Skip this case if
144 it's not defined by some MODIFY_EXPR. */
145 def = SSA_NAME_DEF_STMT (test_var);
146 if (TREE_CODE (def) != MODIFY_EXPR)
149 def_rhs = TREE_OPERAND (def, 1);
151 /* If TEST_VAR is set by adding or subtracting a constant
152 from an SSA_NAME, then it is interesting to us as we
153 can adjust the constant in the conditional and thus
154 eliminate the arithmetic operation. */
155 if (TREE_CODE (def_rhs) == PLUS_EXPR
156 || TREE_CODE (def_rhs) == MINUS_EXPR)
158 tree op0 = TREE_OPERAND (def_rhs, 0);
159 tree op1 = TREE_OPERAND (def_rhs, 1);
161 /* The first operand must be an SSA_NAME and the second
162 operand must be a constant. */
163 if (TREE_CODE (op0) != SSA_NAME
164 || !CONSTANT_CLASS_P (op1)
165 || !INTEGRAL_TYPE_P (TREE_TYPE (op1)))
168 /* Don't propagate if the first operand occurs in
170 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
173 if (has_single_use (test_var))
175 tree op0 = TREE_OPERAND (def_rhs, 0);
176 tree op1 = TREE_OPERAND (def_rhs, 1);
177 enum tree_code new_code;
180 /* If the variable was defined via X + C, then we must
181 subtract C from the constant in the conditional.
182 Otherwise we add C to the constant in the
183 conditional. The result must fold into a valid
184 gimple operand to be optimizable. */
185 new_code = (TREE_CODE (def_rhs) == PLUS_EXPR
186 ? MINUS_EXPR : PLUS_EXPR);
187 t = int_const_binop (new_code, TREE_OPERAND (cond, 1), op1, 0);
188 if (!is_gimple_val (t))
191 new_cond = build (cond_code, boolean_type_node, op0, t);
195 /* These cases require comparisons of a naked SSA_NAME or
196 comparison of an SSA_NAME against zero or one. */
197 else if (TREE_CODE (cond) == SSA_NAME
198 || integer_zerop (TREE_OPERAND (cond, 1))
199 || integer_onep (TREE_OPERAND (cond, 1)))
201 /* If TEST_VAR is set from a relational operation
202 between two SSA_NAMEs or a combination of an SSA_NAME
203 and a constant, then it is interesting. */
204 if (COMPARISON_CLASS_P (def_rhs))
206 tree op0 = TREE_OPERAND (def_rhs, 0);
207 tree op1 = TREE_OPERAND (def_rhs, 1);
209 /* Both operands of DEF_RHS must be SSA_NAMEs or
211 if ((TREE_CODE (op0) != SSA_NAME
212 && !is_gimple_min_invariant (op0))
213 || (TREE_CODE (op1) != SSA_NAME
214 && !is_gimple_min_invariant (op1)))
217 /* Don't propagate if the first operand occurs in
219 if (TREE_CODE (op0) == SSA_NAME
220 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
223 /* Don't propagate if the second operand occurs in
225 if (TREE_CODE (op1) == SSA_NAME
226 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))
229 if (has_single_use (test_var))
231 /* TEST_VAR was set from a relational operator. */
232 tree op0 = TREE_OPERAND (def_rhs, 0);
233 tree op1 = TREE_OPERAND (def_rhs, 1);
235 new_cond = build (TREE_CODE (def_rhs),
236 boolean_type_node, op0, op1);
238 /* Invert the conditional if necessary. */
239 if ((cond_code == EQ_EXPR
240 && integer_zerop (TREE_OPERAND (cond, 1)))
241 || (cond_code == NE_EXPR
242 && integer_onep (TREE_OPERAND (cond, 1))))
244 new_cond = invert_truthvalue (new_cond);
246 /* If we did not get a simple relational
247 expression or bare SSA_NAME, then we can
248 not optimize this case. */
249 if (!COMPARISON_CLASS_P (new_cond)
250 && TREE_CODE (new_cond) != SSA_NAME)
251 new_cond = NULL_TREE;
256 /* If TEST_VAR is set from a TRUTH_NOT_EXPR, then it
258 else if (TREE_CODE (def_rhs) == TRUTH_NOT_EXPR)
260 enum tree_code new_code;
262 def_rhs = TREE_OPERAND (def_rhs, 0);
264 /* DEF_RHS must be an SSA_NAME or constant. */
265 if (TREE_CODE (def_rhs) != SSA_NAME
266 && !is_gimple_min_invariant (def_rhs))
269 /* Don't propagate if the operand occurs in
271 if (TREE_CODE (def_rhs) == SSA_NAME
272 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def_rhs))
275 if (cond_code == SSA_NAME
276 || (cond_code == NE_EXPR
277 && integer_zerop (TREE_OPERAND (cond, 1)))
278 || (cond_code == EQ_EXPR
279 && integer_onep (TREE_OPERAND (cond, 1))))
284 new_cond = build2 (new_code, boolean_type_node, def_rhs,
285 fold_convert (TREE_TYPE (def_rhs),
289 /* If TEST_VAR was set from a cast of an integer type
290 to a boolean type or a cast of a boolean to an
291 integral, then it is interesting. */
292 else if (TREE_CODE (def_rhs) == NOP_EXPR
293 || TREE_CODE (def_rhs) == CONVERT_EXPR)
298 outer_type = TREE_TYPE (def_rhs);
299 inner_type = TREE_TYPE (TREE_OPERAND (def_rhs, 0));
301 if ((TREE_CODE (outer_type) == BOOLEAN_TYPE
302 && INTEGRAL_TYPE_P (inner_type))
303 || (TREE_CODE (inner_type) == BOOLEAN_TYPE
304 && INTEGRAL_TYPE_P (outer_type)))
309 /* Don't propagate if the operand occurs in
311 if (TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME
312 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND
316 if (has_single_use (test_var))
318 enum tree_code new_code;
321 if (cond_code == SSA_NAME
322 || (cond_code == NE_EXPR
323 && integer_zerop (TREE_OPERAND (cond, 1)))
324 || (cond_code == EQ_EXPR
325 && integer_onep (TREE_OPERAND (cond, 1))))
330 new_arg = TREE_OPERAND (def_rhs, 0);
331 new_cond = build2 (new_code, boolean_type_node, new_arg,
332 fold_convert (TREE_TYPE (new_arg),
338 *test_var_p = test_var;
342 /* Forward propagate a single-use variable into COND_EXPR as many
343 times as possible. */
346 forward_propagate_into_cond (tree cond_expr)
348 gcc_assert (TREE_CODE (cond_expr) == COND_EXPR);
352 tree test_var = NULL_TREE;
353 tree cond = COND_EXPR_COND (cond_expr);
354 tree new_cond = forward_propagate_into_cond_1 (cond, &test_var);
356 /* Return if unsuccessful. */
357 if (new_cond == NULL_TREE)
361 if (dump_file && (dump_flags & TDF_DETAILS))
363 fprintf (dump_file, " Replaced '");
364 print_generic_expr (dump_file, cond, dump_flags);
365 fprintf (dump_file, "' with '");
366 print_generic_expr (dump_file, new_cond, dump_flags);
367 fprintf (dump_file, "'\n");
370 COND_EXPR_COND (cond_expr) = new_cond;
371 update_stmt (cond_expr);
373 if (has_zero_uses (test_var))
375 tree def = SSA_NAME_DEF_STMT (test_var);
376 block_stmt_iterator bsi = bsi_for_stmt (def);
382 /* Main entry point for the forward propagation optimizer. */
385 tree_ssa_forward_propagate_single_use_vars (void)
391 tree last = last_stmt (bb);
392 if (last && TREE_CODE (last) == COND_EXPR)
393 forward_propagate_into_cond (last);
404 struct tree_opt_pass pass_forwprop = {
405 "forwprop", /* name */
406 gate_forwprop, /* gate */
407 tree_ssa_forward_propagate_single_use_vars, /* execute */
410 0, /* static_pass_number */
411 TV_TREE_FORWPROP, /* tv_id */
413 | PROP_alias, /* properties_required */
414 0, /* properties_provided */
415 0, /* properties_destroyed */
416 0, /* todo_flags_start */
417 TODO_dump_func | TODO_ggc_collect /* todo_flags_finish */