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 /* Given an SSA_NAME VAR, return true if and only if VAR is defined by
116 ssa_name_defined_by_comparison_p (tree var
)
118 tree def
= SSA_NAME_DEF_STMT (var
);
120 if (TREE_CODE (def
) == MODIFY_EXPR
)
122 tree rhs
= TREE_OPERAND (def
, 1);
123 return COMPARISON_CLASS_P (rhs
);
129 /* Forward propagate a single-use variable into COND once. Return a
130 new condition if successful. Return NULL_TREE otherwise. */
133 forward_propagate_into_cond_1 (tree cond
, tree
*test_var_p
)
135 tree new_cond
= NULL_TREE
;
136 enum tree_code cond_code
= TREE_CODE (cond
);
137 tree test_var
= NULL_TREE
;
141 /* If the condition is not a lone variable or an equality test of an
142 SSA_NAME against an integral constant, then we do not have an
145 Note these conditions also ensure the COND_EXPR has no
146 virtual operands or other side effects. */
147 if (cond_code
!= SSA_NAME
148 && !((cond_code
== EQ_EXPR
|| cond_code
== NE_EXPR
)
149 && TREE_CODE (TREE_OPERAND (cond
, 0)) == SSA_NAME
150 && CONSTANT_CLASS_P (TREE_OPERAND (cond
, 1))
151 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (cond
, 1)))))
154 /* Extract the single variable used in the test into TEST_VAR. */
155 if (cond_code
== SSA_NAME
)
158 test_var
= TREE_OPERAND (cond
, 0);
160 /* Now get the defining statement for TEST_VAR. Skip this case if
161 it's not defined by some MODIFY_EXPR. */
162 def
= SSA_NAME_DEF_STMT (test_var
);
163 if (TREE_CODE (def
) != MODIFY_EXPR
)
166 def_rhs
= TREE_OPERAND (def
, 1);
168 /* If TEST_VAR is set by adding or subtracting a constant
169 from an SSA_NAME, then it is interesting to us as we
170 can adjust the constant in the conditional and thus
171 eliminate the arithmetic operation. */
172 if (TREE_CODE (def_rhs
) == PLUS_EXPR
173 || TREE_CODE (def_rhs
) == MINUS_EXPR
)
175 tree op0
= TREE_OPERAND (def_rhs
, 0);
176 tree op1
= TREE_OPERAND (def_rhs
, 1);
178 /* The first operand must be an SSA_NAME and the second
179 operand must be a constant. */
180 if (TREE_CODE (op0
) != SSA_NAME
181 || !CONSTANT_CLASS_P (op1
)
182 || !INTEGRAL_TYPE_P (TREE_TYPE (op1
)))
185 /* Don't propagate if the first operand occurs in
187 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0
))
190 if (has_single_use (test_var
))
192 enum tree_code new_code
;
195 /* If the variable was defined via X + C, then we must
196 subtract C from the constant in the conditional.
197 Otherwise we add C to the constant in the
198 conditional. The result must fold into a valid
199 gimple operand to be optimizable. */
200 new_code
= (TREE_CODE (def_rhs
) == PLUS_EXPR
201 ? MINUS_EXPR
: PLUS_EXPR
);
202 t
= int_const_binop (new_code
, TREE_OPERAND (cond
, 1), op1
, 0);
203 if (!is_gimple_val (t
))
206 new_cond
= build (cond_code
, boolean_type_node
, op0
, t
);
210 /* These cases require comparisons of a naked SSA_NAME or
211 comparison of an SSA_NAME against zero or one. */
212 else if (TREE_CODE (cond
) == SSA_NAME
213 || integer_zerop (TREE_OPERAND (cond
, 1))
214 || integer_onep (TREE_OPERAND (cond
, 1)))
216 /* If TEST_VAR is set from a relational operation
217 between two SSA_NAMEs or a combination of an SSA_NAME
218 and a constant, then it is interesting. */
219 if (COMPARISON_CLASS_P (def_rhs
))
221 tree op0
= TREE_OPERAND (def_rhs
, 0);
222 tree op1
= TREE_OPERAND (def_rhs
, 1);
224 /* Both operands of DEF_RHS must be SSA_NAMEs or
226 if ((TREE_CODE (op0
) != SSA_NAME
227 && !is_gimple_min_invariant (op0
))
228 || (TREE_CODE (op1
) != SSA_NAME
229 && !is_gimple_min_invariant (op1
)))
232 /* Don't propagate if the first operand occurs in
234 if (TREE_CODE (op0
) == SSA_NAME
235 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0
))
238 /* Don't propagate if the second operand occurs in
240 if (TREE_CODE (op1
) == SSA_NAME
241 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1
))
244 if (has_single_use (test_var
))
246 /* TEST_VAR was set from a relational operator. */
247 new_cond
= build (TREE_CODE (def_rhs
),
248 boolean_type_node
, op0
, op1
);
250 /* Invert the conditional if necessary. */
251 if ((cond_code
== EQ_EXPR
252 && integer_zerop (TREE_OPERAND (cond
, 1)))
253 || (cond_code
== NE_EXPR
254 && integer_onep (TREE_OPERAND (cond
, 1))))
256 new_cond
= invert_truthvalue (new_cond
);
258 /* If we did not get a simple relational
259 expression or bare SSA_NAME, then we can
260 not optimize this case. */
261 if (!COMPARISON_CLASS_P (new_cond
)
262 && TREE_CODE (new_cond
) != SSA_NAME
)
263 new_cond
= NULL_TREE
;
268 /* If TEST_VAR is set from a TRUTH_NOT_EXPR, then it
270 else if (TREE_CODE (def_rhs
) == TRUTH_NOT_EXPR
)
272 enum tree_code new_code
;
274 def_rhs
= TREE_OPERAND (def_rhs
, 0);
276 /* DEF_RHS must be an SSA_NAME or constant. */
277 if (TREE_CODE (def_rhs
) != SSA_NAME
278 && !is_gimple_min_invariant (def_rhs
))
281 /* Don't propagate if the operand occurs in
283 if (TREE_CODE (def_rhs
) == SSA_NAME
284 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def_rhs
))
287 if (cond_code
== SSA_NAME
288 || (cond_code
== NE_EXPR
289 && integer_zerop (TREE_OPERAND (cond
, 1)))
290 || (cond_code
== EQ_EXPR
291 && integer_onep (TREE_OPERAND (cond
, 1))))
296 new_cond
= build2 (new_code
, boolean_type_node
, def_rhs
,
297 fold_convert (TREE_TYPE (def_rhs
),
301 /* If TEST_VAR was set from a cast of an integer type
302 to a boolean type or a cast of a boolean to an
303 integral, then it is interesting. */
304 else if (TREE_CODE (def_rhs
) == NOP_EXPR
305 || TREE_CODE (def_rhs
) == CONVERT_EXPR
)
310 outer_type
= TREE_TYPE (def_rhs
);
311 inner_type
= TREE_TYPE (TREE_OPERAND (def_rhs
, 0));
313 if ((TREE_CODE (outer_type
) == BOOLEAN_TYPE
314 && INTEGRAL_TYPE_P (inner_type
))
315 || (TREE_CODE (inner_type
) == BOOLEAN_TYPE
316 && INTEGRAL_TYPE_P (outer_type
)))
318 else if (INTEGRAL_TYPE_P (outer_type
)
319 && INTEGRAL_TYPE_P (inner_type
)
320 && TREE_CODE (TREE_OPERAND (def_rhs
, 0)) == SSA_NAME
321 && ssa_name_defined_by_comparison_p (TREE_OPERAND (def_rhs
,
327 /* Don't propagate if the operand occurs in
329 if (TREE_CODE (TREE_OPERAND (def_rhs
, 0)) == SSA_NAME
330 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND
334 if (has_single_use (test_var
))
336 enum tree_code new_code
;
339 if (cond_code
== SSA_NAME
340 || (cond_code
== NE_EXPR
341 && integer_zerop (TREE_OPERAND (cond
, 1)))
342 || (cond_code
== EQ_EXPR
343 && integer_onep (TREE_OPERAND (cond
, 1))))
348 new_arg
= TREE_OPERAND (def_rhs
, 0);
349 new_cond
= build2 (new_code
, boolean_type_node
, new_arg
,
350 fold_convert (TREE_TYPE (new_arg
),
356 *test_var_p
= test_var
;
360 /* Forward propagate a single-use variable into COND_EXPR as many
361 times as possible. */
364 forward_propagate_into_cond (tree cond_expr
)
366 gcc_assert (TREE_CODE (cond_expr
) == COND_EXPR
);
370 tree test_var
= NULL_TREE
;
371 tree cond
= COND_EXPR_COND (cond_expr
);
372 tree new_cond
= forward_propagate_into_cond_1 (cond
, &test_var
);
374 /* Return if unsuccessful. */
375 if (new_cond
== NULL_TREE
)
379 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
381 fprintf (dump_file
, " Replaced '");
382 print_generic_expr (dump_file
, cond
, dump_flags
);
383 fprintf (dump_file
, "' with '");
384 print_generic_expr (dump_file
, new_cond
, dump_flags
);
385 fprintf (dump_file
, "'\n");
388 COND_EXPR_COND (cond_expr
) = new_cond
;
389 update_stmt (cond_expr
);
391 if (has_zero_uses (test_var
))
393 tree def
= SSA_NAME_DEF_STMT (test_var
);
394 block_stmt_iterator bsi
= bsi_for_stmt (def
);
400 /* Main entry point for the forward propagation optimizer. */
403 tree_ssa_forward_propagate_single_use_vars (void)
409 tree last
= last_stmt (bb
);
410 if (last
&& TREE_CODE (last
) == COND_EXPR
)
411 forward_propagate_into_cond (last
);
422 struct tree_opt_pass pass_forwprop
= {
423 "forwprop", /* name */
424 gate_forwprop
, /* gate */
425 tree_ssa_forward_propagate_single_use_vars
, /* execute */
428 0, /* static_pass_number */
429 TV_TREE_FORWPROP
, /* tv_id */
431 | PROP_alias
, /* properties_required */
432 0, /* properties_provided */
433 0, /* properties_destroyed */
434 0, /* todo_flags_start */
435 TODO_dump_func
| TODO_ggc_collect
/* todo_flags_finish */