]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-ssa-forwprop.c
* config/bfin/bfin.h (splitting_loops): Declare.
[thirdparty/gcc.git] / gcc / tree-ssa-forwprop.c
CommitLineData
291d763b 1/* Forward propagation of expressions for single use variables.
cfaf579d 2 Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
4ee9c684 3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8c4c00c1 8the Free Software Foundation; either version 3, or (at your option)
4ee9c684 9any later version.
10
11GCC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
8c4c00c1 17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
4ee9c684 19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
23#include "tm.h"
4ee9c684 24#include "ggc.h"
25#include "tree.h"
26#include "rtl.h"
27#include "tm_p.h"
28#include "basic-block.h"
29#include "timevar.h"
30#include "diagnostic.h"
31#include "tree-flow.h"
32#include "tree-pass.h"
33#include "tree-dump.h"
291d763b 34#include "langhooks.h"
5adc1066 35#include "flags.h"
75a70cf9 36#include "gimple.h"
4ee9c684 37
291d763b 38/* This pass propagates the RHS of assignment statements into use
39 sites of the LHS of the assignment. It's basically a specialized
8f628ee8 40 form of tree combination. It is hoped all of this can disappear
41 when we have a generalized tree combiner.
4ee9c684 42
291d763b 43 One class of common cases we handle is forward propagating a single use
c78cbec8 44 variable into a COND_EXPR.
4ee9c684 45
46 bb0:
47 x = a COND b;
48 if (x) goto ... else goto ...
49
50 Will be transformed into:
51
52 bb0:
53 if (a COND b) goto ... else goto ...
54
55 Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
56
57 Or (assuming c1 and c2 are constants):
58
59 bb0:
60 x = a + c1;
61 if (x EQ/NEQ c2) goto ... else goto ...
62
63 Will be transformed into:
64
65 bb0:
66 if (a EQ/NEQ (c2 - c1)) goto ... else goto ...
67
68 Similarly for x = a - c1.
69
70 Or
71
72 bb0:
73 x = !a
74 if (x) goto ... else goto ...
75
76 Will be transformed into:
77
78 bb0:
79 if (a == 0) goto ... else goto ...
80
81 Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
82 For these cases, we propagate A into all, possibly more than one,
83 COND_EXPRs that use X.
84
f5c8cff5 85 Or
86
87 bb0:
88 x = (typecast) a
89 if (x) goto ... else goto ...
90
91 Will be transformed into:
92
93 bb0:
94 if (a != 0) goto ... else goto ...
95
96 (Assuming a is an integral type and x is a boolean or x is an
97 integral and a is a boolean.)
98
99 Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1).
100 For these cases, we propagate A into all, possibly more than one,
101 COND_EXPRs that use X.
102
4ee9c684 103 In addition to eliminating the variable and the statement which assigns
104 a value to the variable, we may be able to later thread the jump without
e6dfde59 105 adding insane complexity in the dominator optimizer.
4ee9c684 106
f5c8cff5 107 Also note these transformations can cascade. We handle this by having
108 a worklist of COND_EXPR statements to examine. As we make a change to
109 a statement, we put it back on the worklist to examine on the next
110 iteration of the main loop.
111
291d763b 112 A second class of propagation opportunities arises for ADDR_EXPR
113 nodes.
114
115 ptr = &x->y->z;
116 res = *ptr;
117
118 Will get turned into
119
120 res = x->y->z;
121
50f39ec6 122 Or
123 ptr = (type1*)&type2var;
124 res = *ptr
125
126 Will get turned into (if type1 and type2 are the same size
127 and neither have volatile on them):
128 res = VIEW_CONVERT_EXPR<type1>(type2var)
129
291d763b 130 Or
131
132 ptr = &x[0];
133 ptr2 = ptr + <constant>;
134
135 Will get turned into
136
137 ptr2 = &x[constant/elementsize];
138
139 Or
140
141 ptr = &x[0];
142 offset = index * element_size;
143 offset_p = (pointer) offset;
144 ptr2 = ptr + offset_p
145
146 Will get turned into:
147
148 ptr2 = &x[index];
149
1c4607fd 150 Or
151 ssa = (int) decl
152 res = ssa & 1
153
154 Provided that decl has known alignment >= 2, will get turned into
155
156 res = 0
157
8f628ee8 158 We also propagate casts into SWITCH_EXPR and COND_EXPR conditions to
159 allow us to remove the cast and {NOT_EXPR,NEG_EXPR} into a subsequent
160 {NOT_EXPR,NEG_EXPR}.
291d763b 161
4ee9c684 162 This will (of course) be extended as other needs arise. */
163
15ec875c 164static bool forward_propagate_addr_expr (tree name, tree rhs);
148aa112 165
166/* Set to true if we delete EH edges during the optimization. */
167static bool cfg_changed;
168
75a70cf9 169static tree rhs_to_tree (tree type, gimple stmt);
148aa112 170
83a20baf 171/* Get the next statement we can propagate NAME's value into skipping
5adc1066 172 trivial copies. Returns the statement that is suitable as a
173 propagation destination or NULL_TREE if there is no such one.
174 This only returns destinations in a single-use chain. FINAL_NAME_P
175 if non-NULL is written to the ssa name that represents the use. */
a3451973 176
75a70cf9 177static gimple
5adc1066 178get_prop_dest_stmt (tree name, tree *final_name_p)
a3451973 179{
5adc1066 180 use_operand_p use;
75a70cf9 181 gimple use_stmt;
a3451973 182
5adc1066 183 do {
184 /* If name has multiple uses, bail out. */
185 if (!single_imm_use (name, &use, &use_stmt))
75a70cf9 186 return NULL;
a3451973 187
5adc1066 188 /* If this is not a trivial copy, we found it. */
8f0b877f 189 if (!gimple_assign_ssa_name_copy_p (use_stmt)
75a70cf9 190 || gimple_assign_rhs1 (use_stmt) != name)
5adc1066 191 break;
192
193 /* Continue searching uses of the copy destination. */
75a70cf9 194 name = gimple_assign_lhs (use_stmt);
5adc1066 195 } while (1);
196
197 if (final_name_p)
198 *final_name_p = name;
199
200 return use_stmt;
a3451973 201}
202
5adc1066 203/* Get the statement we can propagate from into NAME skipping
204 trivial copies. Returns the statement which defines the
205 propagation source or NULL_TREE if there is no such one.
206 If SINGLE_USE_ONLY is set considers only sources which have
207 a single use chain up to NAME. If SINGLE_USE_P is non-null,
208 it is set to whether the chain to NAME is a single use chain
209 or not. SINGLE_USE_P is not written to if SINGLE_USE_ONLY is set. */
4ee9c684 210
75a70cf9 211static gimple
5adc1066 212get_prop_source_stmt (tree name, bool single_use_only, bool *single_use_p)
f5c8cff5 213{
5adc1066 214 bool single_use = true;
215
216 do {
75a70cf9 217 gimple def_stmt = SSA_NAME_DEF_STMT (name);
5adc1066 218
219 if (!has_single_use (name))
220 {
221 single_use = false;
222 if (single_use_only)
75a70cf9 223 return NULL;
5adc1066 224 }
225
226 /* If name is defined by a PHI node or is the default def, bail out. */
8f0b877f 227 if (!is_gimple_assign (def_stmt))
75a70cf9 228 return NULL;
5adc1066 229
8f0b877f 230 /* If def_stmt is not a simple copy, we possibly found it. */
231 if (!gimple_assign_ssa_name_copy_p (def_stmt))
5adc1066 232 {
b9e98b8a 233 tree rhs;
234
5adc1066 235 if (!single_use_only && single_use_p)
236 *single_use_p = single_use;
237
b9e98b8a 238 /* We can look through pointer conversions in the search
239 for a useful stmt for the comparison folding. */
75a70cf9 240 rhs = gimple_assign_rhs1 (def_stmt);
d9659041 241 if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))
75a70cf9 242 && TREE_CODE (rhs) == SSA_NAME
243 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_lhs (def_stmt)))
244 && POINTER_TYPE_P (TREE_TYPE (rhs)))
245 name = rhs;
b9e98b8a 246 else
247 return def_stmt;
248 }
249 else
250 {
251 /* Continue searching the def of the copy source name. */
75a70cf9 252 name = gimple_assign_rhs1 (def_stmt);
5adc1066 253 }
5adc1066 254 } while (1);
255}
e6dfde59 256
5adc1066 257/* Checks if the destination ssa name in DEF_STMT can be used as
258 propagation source. Returns true if so, otherwise false. */
e6dfde59 259
5adc1066 260static bool
75a70cf9 261can_propagate_from (gimple def_stmt)
5adc1066 262{
cc5ef3f4 263 use_operand_p use_p;
264 ssa_op_iter iter;
e6dfde59 265
75a70cf9 266 gcc_assert (is_gimple_assign (def_stmt));
8f0b877f 267
484b827b 268 /* If the rhs has side-effects we cannot propagate from it. */
75a70cf9 269 if (gimple_has_volatile_ops (def_stmt))
484b827b 270 return false;
271
272 /* If the rhs is a load we cannot propagate from it. */
75a70cf9 273 if (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt)) == tcc_reference
274 || TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt)) == tcc_declaration)
484b827b 275 return false;
276
b9e98b8a 277 /* Constants can be always propagated. */
8f0b877f 278 if (gimple_assign_single_p (def_stmt)
279 && is_gimple_min_invariant (gimple_assign_rhs1 (def_stmt)))
b9e98b8a 280 return true;
281
75a70cf9 282 /* We cannot propagate ssa names that occur in abnormal phi nodes. */
cc5ef3f4 283 FOR_EACH_SSA_USE_OPERAND (use_p, def_stmt, iter, SSA_OP_USE)
284 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (USE_FROM_PTR (use_p)))
5adc1066 285 return false;
4ee9c684 286
5adc1066 287 /* If the definition is a conversion of a pointer to a function type,
75a70cf9 288 then we can not apply optimizations as some targets require
289 function pointers to be canonicalized and in this case this
290 optimization could eliminate a necessary canonicalization. */
8f0b877f 291 if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
75a70cf9 292 {
293 tree rhs = gimple_assign_rhs1 (def_stmt);
294 if (POINTER_TYPE_P (TREE_TYPE (rhs))
295 && TREE_CODE (TREE_TYPE (TREE_TYPE (rhs))) == FUNCTION_TYPE)
296 return false;
297 }
8f0b877f 298
5adc1066 299 return true;
e6dfde59 300}
301
5adc1066 302/* Remove a copy chain ending in NAME along the defs but not
303 further or including UP_TO_STMT. If NAME was replaced in
304 its only use then this function can be used to clean up
305 dead stmts. Returns true if UP_TO_STMT can be removed
306 as well, otherwise false. */
8f628ee8 307
5adc1066 308static bool
75a70cf9 309remove_prop_source_from_use (tree name, gimple up_to_stmt)
5adc1066 310{
75a70cf9 311 gimple_stmt_iterator gsi;
312 gimple stmt;
8f628ee8 313
5adc1066 314 do {
315 if (!has_zero_uses (name))
316 return false;
8f628ee8 317
5adc1066 318 stmt = SSA_NAME_DEF_STMT (name);
319 if (stmt == up_to_stmt)
320 return true;
8f628ee8 321
75a70cf9 322 gsi = gsi_for_stmt (stmt);
5adc1066 323 release_defs (stmt);
75a70cf9 324 gsi_remove (&gsi, true);
8f628ee8 325
75a70cf9 326 name = (gimple_assign_copy_p (stmt)) ? gimple_assign_rhs1 (stmt) : NULL;
327 } while (name && TREE_CODE (name) == SSA_NAME);
8f628ee8 328
5adc1066 329 return false;
330}
8f628ee8 331
75a70cf9 332/* Return the rhs of a gimple_assign STMT in a form of a single tree,
333 converted to type TYPE.
334
335 This should disappear, but is needed so we can combine expressions and use
336 the fold() interfaces. Long term, we need to develop folding and combine
337 routines that deal with gimple exclusively . */
338
339static tree
340rhs_to_tree (tree type, gimple stmt)
341{
342 enum tree_code code = gimple_assign_rhs_code (stmt);
343 if (get_gimple_rhs_class (code) == GIMPLE_BINARY_RHS)
fb8ed03f 344 return fold_build2 (code, type, gimple_assign_rhs1 (stmt),
345 gimple_assign_rhs2 (stmt));
75a70cf9 346 else if (get_gimple_rhs_class (code) == GIMPLE_UNARY_RHS)
fb8ed03f 347 return build1 (code, type, gimple_assign_rhs1 (stmt));
75a70cf9 348 else if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS)
349 return gimple_assign_rhs1 (stmt);
350 else
351 gcc_unreachable ();
352}
353
5adc1066 354/* Combine OP0 CODE OP1 in the context of a COND_EXPR. Returns
355 the folded result in a form suitable for COND_EXPR_COND or
356 NULL_TREE, if there is no suitable simplified form. If
357 INVARIANT_ONLY is true only gimple_min_invariant results are
358 considered simplified. */
8f628ee8 359
360static tree
5adc1066 361combine_cond_expr_cond (enum tree_code code, tree type,
362 tree op0, tree op1, bool invariant_only)
8f628ee8 363{
5adc1066 364 tree t;
8f628ee8 365
5adc1066 366 gcc_assert (TREE_CODE_CLASS (code) == tcc_comparison);
8f628ee8 367
5adc1066 368 t = fold_binary (code, type, op0, op1);
369 if (!t)
370 return NULL_TREE;
8f628ee8 371
5adc1066 372 /* Require that we got a boolean type out if we put one in. */
373 gcc_assert (TREE_CODE (TREE_TYPE (t)) == TREE_CODE (type));
8f628ee8 374
a7392604 375 /* Canonicalize the combined condition for use in a COND_EXPR. */
376 t = canonicalize_cond_expr_cond (t);
8f628ee8 377
5adc1066 378 /* Bail out if we required an invariant but didn't get one. */
75a70cf9 379 if (!t || (invariant_only && !is_gimple_min_invariant (t)))
5adc1066 380 return NULL_TREE;
8f628ee8 381
a7392604 382 return t;
8f628ee8 383}
384
5adc1066 385/* Propagate from the ssa name definition statements of COND_EXPR
75a70cf9 386 in GIMPLE_COND statement STMT into the conditional if that simplifies it.
387 Returns zero if no statement was changed, one if there were
388 changes and two if cfg_cleanup needs to run.
389
390 This must be kept in sync with forward_propagate_into_cond. */
391
392static int
393forward_propagate_into_gimple_cond (gimple stmt)
394{
395 int did_something = 0;
396
397 do {
398 tree tmp = NULL_TREE;
399 tree name, rhs0 = NULL_TREE, rhs1 = NULL_TREE;
400 gimple def_stmt;
401 bool single_use0_p = false, single_use1_p = false;
402 enum tree_code code = gimple_cond_code (stmt);
403
404 /* We can do tree combining on SSA_NAME and comparison expressions. */
405 if (TREE_CODE_CLASS (gimple_cond_code (stmt)) == tcc_comparison
406 && TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME)
407 {
408 /* For comparisons use the first operand, that is likely to
409 simplify comparisons against constants. */
410 name = gimple_cond_lhs (stmt);
411 def_stmt = get_prop_source_stmt (name, false, &single_use0_p);
412 if (def_stmt && can_propagate_from (def_stmt))
413 {
414 tree op1 = gimple_cond_rhs (stmt);
415 rhs0 = rhs_to_tree (TREE_TYPE (op1), def_stmt);
416 tmp = combine_cond_expr_cond (code, boolean_type_node, rhs0,
417 op1, !single_use0_p);
418 }
419 /* If that wasn't successful, try the second operand. */
420 if (tmp == NULL_TREE
421 && TREE_CODE (gimple_cond_rhs (stmt)) == SSA_NAME)
422 {
423 tree op0 = gimple_cond_lhs (stmt);
424 name = gimple_cond_rhs (stmt);
425 def_stmt = get_prop_source_stmt (name, false, &single_use1_p);
426 if (!def_stmt || !can_propagate_from (def_stmt))
427 return did_something;
428
429 rhs1 = rhs_to_tree (TREE_TYPE (op0), def_stmt);
430 tmp = combine_cond_expr_cond (code, boolean_type_node, op0, rhs1,
431 !single_use1_p);
432 }
433 /* If that wasn't successful either, try both operands. */
434 if (tmp == NULL_TREE
435 && rhs0 != NULL_TREE
436 && rhs1 != NULL_TREE)
437 tmp = combine_cond_expr_cond (code, boolean_type_node, rhs0,
438 fold_convert (TREE_TYPE (rhs0), rhs1),
439 !(single_use0_p && single_use1_p));
440 }
441
442 if (tmp)
443 {
444 if (dump_file && tmp)
445 {
446 tree cond = build2 (gimple_cond_code (stmt),
447 boolean_type_node,
448 gimple_cond_lhs (stmt),
449 gimple_cond_rhs (stmt));
450 fprintf (dump_file, " Replaced '");
451 print_generic_expr (dump_file, cond, 0);
452 fprintf (dump_file, "' with '");
453 print_generic_expr (dump_file, tmp, 0);
454 fprintf (dump_file, "'\n");
455 }
456
457 gimple_cond_set_condition_from_tree (stmt, unshare_expr (tmp));
458 update_stmt (stmt);
459
460 /* Remove defining statements. */
461 remove_prop_source_from_use (name, NULL);
462
463 if (is_gimple_min_invariant (tmp))
464 did_something = 2;
465 else if (did_something == 0)
466 did_something = 1;
467
468 /* Continue combining. */
469 continue;
470 }
471
472 break;
473 } while (1);
474
475 return did_something;
476}
477
478
479/* Propagate from the ssa name definition statements of COND_EXPR
480 in the rhs of statement STMT into the conditional if that simplifies it.
4c580c8c 481 Returns zero if no statement was changed, one if there were
75a70cf9 482 changes and two if cfg_cleanup needs to run.
483
484 This must be kept in sync with forward_propagate_into_gimple_cond. */
4ee9c684 485
4c580c8c 486static int
75a70cf9 487forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
e6dfde59 488{
75a70cf9 489 gimple stmt = gsi_stmt (*gsi_p);
4c580c8c 490 int did_something = 0;
d080be9e 491
5adc1066 492 do {
493 tree tmp = NULL_TREE;
75a70cf9 494 tree cond = gimple_assign_rhs1 (stmt);
495 tree name, rhs0 = NULL_TREE, rhs1 = NULL_TREE;
496 gimple def_stmt;
f4628d45 497 bool single_use0_p = false, single_use1_p = false;
5adc1066 498
499 /* We can do tree combining on SSA_NAME and comparison expressions. */
500 if (COMPARISON_CLASS_P (cond)
501 && TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME)
502 {
503 /* For comparisons use the first operand, that is likely to
504 simplify comparisons against constants. */
505 name = TREE_OPERAND (cond, 0);
f4628d45 506 def_stmt = get_prop_source_stmt (name, false, &single_use0_p);
75a70cf9 507 if (def_stmt && can_propagate_from (def_stmt))
5adc1066 508 {
509 tree op1 = TREE_OPERAND (cond, 1);
75a70cf9 510 rhs0 = rhs_to_tree (TREE_TYPE (op1), def_stmt);
5adc1066 511 tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
75a70cf9 512 rhs0, op1, !single_use0_p);
5adc1066 513 }
514 /* If that wasn't successful, try the second operand. */
515 if (tmp == NULL_TREE
516 && TREE_CODE (TREE_OPERAND (cond, 1)) == SSA_NAME)
517 {
518 tree op0 = TREE_OPERAND (cond, 0);
519 name = TREE_OPERAND (cond, 1);
f4628d45 520 def_stmt = get_prop_source_stmt (name, false, &single_use1_p);
75a70cf9 521 if (!def_stmt || !can_propagate_from (def_stmt))
d080be9e 522 return did_something;
5adc1066 523
75a70cf9 524 rhs1 = rhs_to_tree (TREE_TYPE (op0), def_stmt);
5adc1066 525 tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
75a70cf9 526 op0, rhs1, !single_use1_p);
5adc1066 527 }
484b827b 528 /* If that wasn't successful either, try both operands. */
529 if (tmp == NULL_TREE
530 && rhs0 != NULL_TREE
531 && rhs1 != NULL_TREE)
532 tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
75a70cf9 533 rhs0, fold_convert (TREE_TYPE (rhs0),
534 rhs1),
f4628d45 535 !(single_use0_p && single_use1_p));
5adc1066 536 }
537 else if (TREE_CODE (cond) == SSA_NAME)
538 {
539 name = cond;
540 def_stmt = get_prop_source_stmt (name, true, NULL);
75a70cf9 541 if (def_stmt || !can_propagate_from (def_stmt))
d080be9e 542 return did_something;
5adc1066 543
75a70cf9 544 rhs0 = gimple_assign_rhs1 (def_stmt);
484b827b 545 tmp = combine_cond_expr_cond (NE_EXPR, boolean_type_node, rhs0,
546 build_int_cst (TREE_TYPE (rhs0), 0),
5adc1066 547 false);
548 }
549
550 if (tmp)
551 {
552 if (dump_file && tmp)
553 {
554 fprintf (dump_file, " Replaced '");
555 print_generic_expr (dump_file, cond, 0);
556 fprintf (dump_file, "' with '");
557 print_generic_expr (dump_file, tmp, 0);
558 fprintf (dump_file, "'\n");
559 }
560
75a70cf9 561 gimple_assign_set_rhs_from_tree (gsi_p, unshare_expr (tmp));
562 stmt = gsi_stmt (*gsi_p);
5adc1066 563 update_stmt (stmt);
564
565 /* Remove defining statements. */
566 remove_prop_source_from_use (name, NULL);
567
4c580c8c 568 if (is_gimple_min_invariant (tmp))
569 did_something = 2;
570 else if (did_something == 0)
571 did_something = 1;
d080be9e 572
5adc1066 573 /* Continue combining. */
574 continue;
575 }
576
577 break;
578 } while (1);
d080be9e 579
580 return did_something;
4ee9c684 581}
582
148aa112 583/* We've just substituted an ADDR_EXPR into stmt. Update all the
584 relevant data structures to match. */
585
586static void
75a70cf9 587tidy_after_forward_propagate_addr (gimple stmt)
148aa112 588{
148aa112 589 /* We may have turned a trapping insn into a non-trapping insn. */
590 if (maybe_clean_or_replace_eh_stmt (stmt, stmt)
75a70cf9 591 && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
148aa112 592 cfg_changed = true;
f2fae51f 593
75a70cf9 594 if (TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR)
595 recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));
148aa112 596}
597
75a70cf9 598/* DEF_RHS contains the address of the 0th element in an array.
6c01267c 599 USE_STMT uses type of DEF_RHS to compute the address of an
291d763b 600 arbitrary element within the array. The (variable) byte offset
601 of the element is contained in OFFSET.
602
603 We walk back through the use-def chains of OFFSET to verify that
604 it is indeed computing the offset of an element within the array
605 and extract the index corresponding to the given byte offset.
606
607 We then try to fold the entire address expression into a form
608 &array[index].
609
610 If we are successful, we replace the right hand side of USE_STMT
611 with the new address computation. */
612
613static bool
6c01267c 614forward_propagate_addr_into_variable_array_index (tree offset,
75a70cf9 615 tree def_rhs,
616 gimple_stmt_iterator *use_stmt_gsi)
291d763b 617{
401d1fb3 618 tree index, tunit;
75a70cf9 619 gimple offset_def, use_stmt = gsi_stmt (*use_stmt_gsi);
401d1fb3 620 tree tmp;
621
622 tunit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs)));
623 if (!host_integerp (tunit, 1))
624 return false;
291d763b 625
65c220cd 626 /* Get the offset's defining statement. */
627 offset_def = SSA_NAME_DEF_STMT (offset);
628
629 /* Try to find an expression for a proper index. This is either a
630 multiplication expression by the element size or just the ssa name we came
631 along in case the element size is one. In that case, however, we do not
632 allow multiplications because they can be computing index to a higher
633 level dimension (PR 37861). */
401d1fb3 634 if (integer_onep (tunit))
1a773ec5 635 {
65c220cd 636 if (is_gimple_assign (offset_def)
637 && gimple_assign_rhs_code (offset_def) == MULT_EXPR)
638 return false;
291d763b 639
65c220cd 640 index = offset;
641 }
642 else
643 {
0de36bdb 644 /* The statement which defines OFFSET before type conversion
75a70cf9 645 must be a simple GIMPLE_ASSIGN. */
65c220cd 646 if (!is_gimple_assign (offset_def))
1a773ec5 647 return false;
291d763b 648
0de36bdb 649 /* The RHS of the statement which defines OFFSET must be a
650 multiplication of an object by the size of the array elements.
651 This implicitly verifies that the size of the array elements
652 is constant. */
401d1fb3 653 if (gimple_assign_rhs_code (offset_def) == MULT_EXPR
654 && TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
655 && tree_int_cst_equal (gimple_assign_rhs2 (offset_def), tunit))
656 {
657 /* The first operand to the MULT_EXPR is the desired index. */
658 index = gimple_assign_rhs1 (offset_def);
659 }
660 /* If we have idx * tunit + CST * tunit re-associate that. */
661 else if ((gimple_assign_rhs_code (offset_def) == PLUS_EXPR
662 || gimple_assign_rhs_code (offset_def) == MINUS_EXPR)
663 && TREE_CODE (gimple_assign_rhs1 (offset_def)) == SSA_NAME
664 && TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
665 && (tmp = div_if_zero_remainder (EXACT_DIV_EXPR,
666 gimple_assign_rhs2 (offset_def),
667 tunit)) != NULL_TREE)
668 {
669 gimple offset_def2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (offset_def));
507b89a4 670 if (is_gimple_assign (offset_def2)
671 && gimple_assign_rhs_code (offset_def2) == MULT_EXPR
401d1fb3 672 && TREE_CODE (gimple_assign_rhs2 (offset_def2)) == INTEGER_CST
673 && tree_int_cst_equal (gimple_assign_rhs2 (offset_def2), tunit))
674 {
675 index = fold_build2 (gimple_assign_rhs_code (offset_def),
676 TREE_TYPE (offset),
677 gimple_assign_rhs1 (offset_def2), tmp);
678 }
679 else
680 return false;
681 }
682 else
1a773ec5 683 return false;
1a773ec5 684 }
291d763b 685
686 /* Replace the pointer addition with array indexing. */
401d1fb3 687 index = force_gimple_operand_gsi (use_stmt_gsi, index, true, NULL_TREE,
688 true, GSI_SAME_STMT);
75a70cf9 689 gimple_assign_set_rhs_from_tree (use_stmt_gsi, unshare_expr (def_rhs));
690 use_stmt = gsi_stmt (*use_stmt_gsi);
691 TREE_OPERAND (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0), 1)
35cc02b5 692 = index;
291d763b 693
694 /* That should have created gimple, so there is no need to
695 record information to undo the propagation. */
148aa112 696 fold_stmt_inplace (use_stmt);
697 tidy_after_forward_propagate_addr (use_stmt);
291d763b 698 return true;
699}
700
15ec875c 701/* NAME is a SSA_NAME representing DEF_RHS which is of the form
702 ADDR_EXPR <whatever>.
291d763b 703
3d5cfe81 704 Try to forward propagate the ADDR_EXPR into the use USE_STMT.
291d763b 705 Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF
3d5cfe81 706 node or for recovery of array indexing from pointer arithmetic.
75a70cf9 707
6b5a5c42 708 Return true if the propagation was successful (the propagation can
709 be not totally successful, yet things may have been changed). */
291d763b 710
711static bool
75a70cf9 712forward_propagate_addr_expr_1 (tree name, tree def_rhs,
713 gimple_stmt_iterator *use_stmt_gsi,
6776dec8 714 bool single_use_p)
291d763b 715{
75a70cf9 716 tree lhs, rhs, rhs2, array_ref;
971c637a 717 tree *rhsp, *lhsp;
75a70cf9 718 gimple use_stmt = gsi_stmt (*use_stmt_gsi);
719 enum tree_code rhs_code;
291d763b 720
971c637a 721 gcc_assert (TREE_CODE (def_rhs) == ADDR_EXPR);
291d763b 722
75a70cf9 723 lhs = gimple_assign_lhs (use_stmt);
724 rhs_code = gimple_assign_rhs_code (use_stmt);
725 rhs = gimple_assign_rhs1 (use_stmt);
15ec875c 726
6776dec8 727 /* Trivial cases. The use statement could be a trivial copy or a
15ec875c 728 useless conversion. Recurse to the uses of the lhs as copyprop does
971c637a 729 not copy through different variant pointers and FRE does not catch
6776dec8 730 all useless conversions. Treat the case of a single-use name and
731 a conversion to def_rhs type separate, though. */
971c637a 732 if (TREE_CODE (lhs) == SSA_NAME
75a70cf9 733 && ((rhs_code == SSA_NAME && rhs == name)
316616c9 734 || CONVERT_EXPR_CODE_P (rhs_code)))
6776dec8 735 {
316616c9 736 /* Only recurse if we don't deal with a single use or we cannot
737 do the propagation to the current statement. In particular
738 we can end up with a conversion needed for a non-invariant
739 address which we cannot do in a single statement. */
740 if (!single_use_p
741 || (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs))
742 && !is_gimple_min_invariant (def_rhs)))
971c637a 743 return forward_propagate_addr_expr (lhs, def_rhs);
744
75a70cf9 745 gimple_assign_set_rhs1 (use_stmt, unshare_expr (def_rhs));
316616c9 746 if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs)))
747 gimple_assign_set_rhs_code (use_stmt, TREE_CODE (def_rhs));
748 else
749 gimple_assign_set_rhs_code (use_stmt, NOP_EXPR);
6776dec8 750 return true;
751 }
971c637a 752
753 /* Now strip away any outer COMPONENT_REF/ARRAY_REF nodes from the LHS.
754 ADDR_EXPR will not appear on the LHS. */
75a70cf9 755 lhsp = gimple_assign_lhs_ptr (use_stmt);
971c637a 756 while (handled_component_p (*lhsp))
757 lhsp = &TREE_OPERAND (*lhsp, 0);
758 lhs = *lhsp;
759
760 /* Now see if the LHS node is an INDIRECT_REF using NAME. If so,
761 propagate the ADDR_EXPR into the use of NAME and fold the result. */
762 if (TREE_CODE (lhs) == INDIRECT_REF
763 && TREE_OPERAND (lhs, 0) == name
e29848bc 764 && may_propagate_address_into_dereference (def_rhs, lhs)
765 && (lhsp != gimple_assign_lhs_ptr (use_stmt)
766 || useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (def_rhs, 0)),
767 TREE_TYPE (rhs))))
971c637a 768 {
e29848bc 769 *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
770 fold_stmt_inplace (use_stmt);
771 tidy_after_forward_propagate_addr (use_stmt);
772
773 /* Continue propagating into the RHS if this was not the only use. */
774 if (single_use_p)
775 return true;
971c637a 776 }
15ec875c 777
631d5db6 778 /* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
779 nodes from the RHS. */
75a70cf9 780 rhsp = gimple_assign_rhs1_ptr (use_stmt);
971c637a 781 while (handled_component_p (*rhsp)
782 || TREE_CODE (*rhsp) == ADDR_EXPR)
783 rhsp = &TREE_OPERAND (*rhsp, 0);
784 rhs = *rhsp;
291d763b 785
75a70cf9 786 /* Now see if the RHS node is an INDIRECT_REF using NAME. If so,
291d763b 787 propagate the ADDR_EXPR into the use of NAME and fold the result. */
971c637a 788 if (TREE_CODE (rhs) == INDIRECT_REF
789 && TREE_OPERAND (rhs, 0) == name
fb8ed03f 790 && may_propagate_address_into_dereference (def_rhs, rhs))
291d763b 791 {
971c637a 792 *rhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
148aa112 793 fold_stmt_inplace (use_stmt);
794 tidy_after_forward_propagate_addr (use_stmt);
291d763b 795 return true;
796 }
797
50f39ec6 798 /* Now see if the RHS node is an INDIRECT_REF using NAME. If so,
799 propagate the ADDR_EXPR into the use of NAME and try to
800 create a VCE and fold the result. */
801 if (TREE_CODE (rhs) == INDIRECT_REF
802 && TREE_OPERAND (rhs, 0) == name
803 && TYPE_SIZE (TREE_TYPE (rhs))
804 && TYPE_SIZE (TREE_TYPE (TREE_OPERAND (def_rhs, 0)))
37d2e64d 805 /* Function decls should not be used for VCE either as it could be a
806 function descriptor that we want and not the actual function code. */
6ec63422 807 && TREE_CODE (TREE_OPERAND (def_rhs, 0)) != FUNCTION_DECL
50f39ec6 808 /* We should not convert volatile loads to non volatile loads. */
809 && !TYPE_VOLATILE (TREE_TYPE (rhs))
810 && !TYPE_VOLATILE (TREE_TYPE (TREE_OPERAND (def_rhs, 0)))
811 && operand_equal_p (TYPE_SIZE (TREE_TYPE (rhs)),
812 TYPE_SIZE (TREE_TYPE (TREE_OPERAND (def_rhs, 0))), 0))
813 {
c4d6ac81 814 tree def_rhs_base, new_rhs = unshare_expr (TREE_OPERAND (def_rhs, 0));
37d2e64d 815 new_rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (rhs), new_rhs);
816 if (TREE_CODE (new_rhs) != VIEW_CONVERT_EXPR)
817 {
818 /* If we have folded the VIEW_CONVERT_EXPR then the result is only
819 valid if we can replace the whole rhs of the use statement. */
820 if (rhs != gimple_assign_rhs1 (use_stmt))
821 return false;
822 new_rhs = force_gimple_operand_gsi (use_stmt_gsi, new_rhs, true, NULL,
823 true, GSI_NEW_STMT);
824 gimple_assign_set_rhs1 (use_stmt, new_rhs);
c4d6ac81 825 tidy_after_forward_propagate_addr (use_stmt);
826 return true;
37d2e64d 827 }
c4d6ac81 828 /* If the defining rhs comes from an indirect reference, then do not
829 convert into a VIEW_CONVERT_EXPR. */
830 def_rhs_base = TREE_OPERAND (def_rhs, 0);
831 while (handled_component_p (def_rhs_base))
832 def_rhs_base = TREE_OPERAND (def_rhs_base, 0);
833 if (!INDIRECT_REF_P (def_rhs_base))
37d2e64d 834 {
835 /* We may have arbitrary VIEW_CONVERT_EXPRs in a nested component
836 reference. Place it there and fold the thing. */
837 *rhsp = new_rhs;
838 fold_stmt_inplace (use_stmt);
c4d6ac81 839 tidy_after_forward_propagate_addr (use_stmt);
840 return true;
37d2e64d 841 }
50f39ec6 842 }
843
971c637a 844 /* If the use of the ADDR_EXPR is not a POINTER_PLUS_EXPR, there
845 is nothing to do. */
75a70cf9 846 if (gimple_assign_rhs_code (use_stmt) != POINTER_PLUS_EXPR
847 || gimple_assign_rhs1 (use_stmt) != name)
971c637a 848 return false;
849
291d763b 850 /* The remaining cases are all for turning pointer arithmetic into
851 array indexing. They only apply when we have the address of
852 element zero in an array. If that is not the case then there
853 is nothing to do. */
15ec875c 854 array_ref = TREE_OPERAND (def_rhs, 0);
291d763b 855 if (TREE_CODE (array_ref) != ARRAY_REF
856 || TREE_CODE (TREE_TYPE (TREE_OPERAND (array_ref, 0))) != ARRAY_TYPE
088cc5d5 857 || TREE_CODE (TREE_OPERAND (array_ref, 1)) != INTEGER_CST)
291d763b 858 return false;
859
75a70cf9 860 rhs2 = gimple_assign_rhs2 (use_stmt);
088cc5d5 861 /* Try to optimize &x[C1] p+ C2 where C2 is a multiple of the size
862 of the elements in X into &x[C1 + C2/element size]. */
75a70cf9 863 if (TREE_CODE (rhs2) == INTEGER_CST)
291d763b 864 {
75a70cf9 865 tree new_rhs = maybe_fold_stmt_addition (gimple_expr_type (use_stmt),
088cc5d5 866 def_rhs, rhs2);
75a70cf9 867 if (new_rhs)
291d763b 868 {
088cc5d5 869 gimple_assign_set_rhs_from_tree (use_stmt_gsi,
870 unshare_expr (new_rhs));
75a70cf9 871 use_stmt = gsi_stmt (*use_stmt_gsi);
872 update_stmt (use_stmt);
148aa112 873 tidy_after_forward_propagate_addr (use_stmt);
291d763b 874 return true;
875 }
291d763b 876 }
877
0de36bdb 878 /* Try to optimize &x[0] p+ OFFSET where OFFSET is defined by
291d763b 879 converting a multiplication of an index by the size of the
880 array elements, then the result is converted into the proper
881 type for the arithmetic. */
75a70cf9 882 if (TREE_CODE (rhs2) == SSA_NAME
088cc5d5 883 && integer_zerop (TREE_OPERAND (array_ref, 1))
c019af4d 884 && useless_type_conversion_p (TREE_TYPE (name), TREE_TYPE (def_rhs))
291d763b 885 /* Avoid problems with IVopts creating PLUS_EXPRs with a
886 different type than their operands. */
83a99d39 887 && useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs)))
75a70cf9 888 return forward_propagate_addr_into_variable_array_index (rhs2, def_rhs,
889 use_stmt_gsi);
291d763b 890 return false;
891}
892
3d5cfe81 893/* STMT is a statement of the form SSA_NAME = ADDR_EXPR <whatever>.
894
895 Try to forward propagate the ADDR_EXPR into all uses of the SSA_NAME.
896 Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF
897 node or for recovery of array indexing from pointer arithmetic.
898 Returns true, if all uses have been propagated into. */
899
900static bool
15ec875c 901forward_propagate_addr_expr (tree name, tree rhs)
3d5cfe81 902{
75a70cf9 903 int stmt_loop_depth = gimple_bb (SSA_NAME_DEF_STMT (name))->loop_depth;
3d5cfe81 904 imm_use_iterator iter;
75a70cf9 905 gimple use_stmt;
3d5cfe81 906 bool all = true;
6776dec8 907 bool single_use_p = has_single_use (name);
3d5cfe81 908
09aca5bc 909 FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
3d5cfe81 910 {
c96420f8 911 bool result;
9481f629 912 tree use_rhs;
3d5cfe81 913
914 /* If the use is not in a simple assignment statement, then
915 there is nothing we can do. */
75a70cf9 916 if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
3d5cfe81 917 {
918 all = false;
919 continue;
920 }
921
a540e2fe 922 /* If the use is in a deeper loop nest, then we do not want
75a70cf9 923 to propagate the ADDR_EXPR into the loop as that is likely
924 adding expression evaluations into the loop. */
925 if (gimple_bb (use_stmt)->loop_depth > stmt_loop_depth)
3d5cfe81 926 {
927 all = false;
928 continue;
929 }
a540e2fe 930
75a70cf9 931 {
932 gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
dd277d48 933 push_stmt_changes (&use_stmt);
75a70cf9 934 result = forward_propagate_addr_expr_1 (name, rhs, &gsi,
935 single_use_p);
dd277d48 936 /* If the use has moved to a different statement adjust
937 the update machinery. */
938 if (use_stmt != gsi_stmt (gsi))
939 {
940 pop_stmt_changes (&use_stmt);
941 use_stmt = gsi_stmt (gsi);
942 update_stmt (use_stmt);
943 }
944 else
945 pop_stmt_changes (&use_stmt);
75a70cf9 946 }
c96420f8 947 all &= result;
de6ed584 948
15ec875c 949 /* Remove intermediate now unused copy and conversion chains. */
75a70cf9 950 use_rhs = gimple_assign_rhs1 (use_stmt);
15ec875c 951 if (result
75a70cf9 952 && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME
9481f629 953 && (TREE_CODE (use_rhs) == SSA_NAME
72dd6141 954 || (CONVERT_EXPR_P (use_rhs)
9481f629 955 && TREE_CODE (TREE_OPERAND (use_rhs, 0)) == SSA_NAME)))
15ec875c 956 {
75a70cf9 957 gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
15ec875c 958 release_defs (use_stmt);
75a70cf9 959 gsi_remove (&gsi, true);
15ec875c 960 }
3d5cfe81 961 }
962
963 return all;
964}
965
75a70cf9 966/* Forward propagate the comparison defined in STMT like
5adc1066 967 cond_1 = x CMP y to uses of the form
968 a_1 = (T')cond_1
969 a_1 = !cond_1
970 a_1 = cond_1 != 0
971 Returns true if stmt is now unused. */
972
973static bool
75a70cf9 974forward_propagate_comparison (gimple stmt)
5adc1066 975{
75a70cf9 976 tree name = gimple_assign_lhs (stmt);
977 gimple use_stmt;
978 tree tmp = NULL_TREE;
5adc1066 979
980 /* Don't propagate ssa names that occur in abnormal phis. */
75a70cf9 981 if ((TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
982 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt)))
983 || (TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME
984 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs2 (stmt))))
5adc1066 985 return false;
986
987 /* Do not un-cse comparisons. But propagate through copies. */
988 use_stmt = get_prop_dest_stmt (name, &name);
75a70cf9 989 if (!use_stmt)
5adc1066 990 return false;
991
992 /* Conversion of the condition result to another integral type. */
75a70cf9 993 if (is_gimple_assign (use_stmt)
d9659041 994 && (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt))
75a70cf9 995 || TREE_CODE_CLASS (gimple_assign_rhs_code (use_stmt))
996 == tcc_comparison
997 || gimple_assign_rhs_code (use_stmt) == TRUTH_NOT_EXPR)
998 && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (use_stmt))))
5adc1066 999 {
75a70cf9 1000 tree lhs = gimple_assign_lhs (use_stmt);
5adc1066 1001
1002 /* We can propagate the condition into a conversion. */
d9659041 1003 if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt)))
5adc1066 1004 {
1005 /* Avoid using fold here as that may create a COND_EXPR with
1006 non-boolean condition as canonical form. */
75a70cf9 1007 tmp = build2 (gimple_assign_rhs_code (stmt), TREE_TYPE (lhs),
1008 gimple_assign_rhs1 (stmt), gimple_assign_rhs2 (stmt));
5adc1066 1009 }
1010 /* We can propagate the condition into X op CST where op
f0b5f617 1011 is EQ_EXPR or NE_EXPR and CST is either one or zero. */
75a70cf9 1012 else if (TREE_CODE_CLASS (gimple_assign_rhs_code (use_stmt))
1013 == tcc_comparison
1014 && TREE_CODE (gimple_assign_rhs1 (use_stmt)) == SSA_NAME
1015 && TREE_CODE (gimple_assign_rhs2 (use_stmt)) == INTEGER_CST)
1016 {
1017 enum tree_code code = gimple_assign_rhs_code (use_stmt);
1018 tree cst = gimple_assign_rhs2 (use_stmt);
1019 tree cond;
1020
1021 cond = build2 (gimple_assign_rhs_code (stmt),
1022 TREE_TYPE (cst),
1023 gimple_assign_rhs1 (stmt),
1024 gimple_assign_rhs2 (stmt));
1025
1026 tmp = combine_cond_expr_cond (code, TREE_TYPE (lhs), cond, cst, false);
1027 if (tmp == NULL_TREE)
1028 return false;
1029 }
5adc1066 1030 /* We can propagate the condition into a statement that
1031 computes the logical negation of the comparison result. */
75a70cf9 1032 else if (gimple_assign_rhs_code (use_stmt) == TRUTH_NOT_EXPR)
5adc1066 1033 {
75a70cf9 1034 tree type = TREE_TYPE (gimple_assign_rhs1 (stmt));
5adc1066 1035 bool nans = HONOR_NANS (TYPE_MODE (type));
1036 enum tree_code code;
75a70cf9 1037 code = invert_tree_comparison (gimple_assign_rhs_code (stmt), nans);
5adc1066 1038 if (code == ERROR_MARK)
1039 return false;
1040
75a70cf9 1041 tmp = build2 (code, TREE_TYPE (lhs), gimple_assign_rhs1 (stmt),
1042 gimple_assign_rhs2 (stmt));
5adc1066 1043 }
1044 else
1045 return false;
1046
75a70cf9 1047 {
1048 gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
1049 gimple_assign_set_rhs_from_tree (&gsi, unshare_expr (tmp));
1050 use_stmt = gsi_stmt (gsi);
1051 update_stmt (use_stmt);
1052 }
5adc1066 1053
1054 /* Remove defining statements. */
1055 remove_prop_source_from_use (name, stmt);
1056
1057 if (dump_file && (dump_flags & TDF_DETAILS))
1058 {
75a70cf9 1059 tree old_rhs = rhs_to_tree (TREE_TYPE (gimple_assign_lhs (stmt)),
1060 stmt);
5adc1066 1061 fprintf (dump_file, " Replaced '");
75a70cf9 1062 print_generic_expr (dump_file, old_rhs, dump_flags);
5adc1066 1063 fprintf (dump_file, "' with '");
1064 print_generic_expr (dump_file, tmp, dump_flags);
1065 fprintf (dump_file, "'\n");
1066 }
1067
1068 return true;
1069 }
1070
1071 return false;
1072}
1073
3a938499 1074/* If we have lhs = ~x (STMT), look and see if earlier we had x = ~y.
1075 If so, we can change STMT into lhs = y which can later be copy
1076 propagated. Similarly for negation.
1077
1078 This could trivially be formulated as a forward propagation
1079 to immediate uses. However, we already had an implementation
1080 from DOM which used backward propagation via the use-def links.
1081
1082 It turns out that backward propagation is actually faster as
1083 there's less work to do for each NOT/NEG expression we find.
1084 Backwards propagation needs to look at the statement in a single
1085 backlink. Forward propagation needs to look at potentially more
1086 than one forward link. */
1087
1088static void
75a70cf9 1089simplify_not_neg_expr (gimple_stmt_iterator *gsi_p)
3a938499 1090{
75a70cf9 1091 gimple stmt = gsi_stmt (*gsi_p);
1092 tree rhs = gimple_assign_rhs1 (stmt);
1093 gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
3a938499 1094
1095 /* See if the RHS_DEF_STMT has the same form as our statement. */
75a70cf9 1096 if (is_gimple_assign (rhs_def_stmt)
1097 && gimple_assign_rhs_code (rhs_def_stmt) == gimple_assign_rhs_code (stmt))
3a938499 1098 {
75a70cf9 1099 tree rhs_def_operand = gimple_assign_rhs1 (rhs_def_stmt);
3a938499 1100
1101 /* Verify that RHS_DEF_OPERAND is a suitable SSA_NAME. */
1102 if (TREE_CODE (rhs_def_operand) == SSA_NAME
1103 && ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs_def_operand))
1104 {
75a70cf9 1105 gimple_assign_set_rhs_from_tree (gsi_p, rhs_def_operand);
1106 stmt = gsi_stmt (*gsi_p);
3a938499 1107 update_stmt (stmt);
1108 }
1109 }
1110}
3d5cfe81 1111
b5860aba 1112/* STMT is a SWITCH_EXPR for which we attempt to find equivalent forms of
1113 the condition which we may be able to optimize better. */
1114
1115static void
75a70cf9 1116simplify_gimple_switch (gimple stmt)
b5860aba 1117{
75a70cf9 1118 tree cond = gimple_switch_index (stmt);
b5860aba 1119 tree def, to, ti;
75a70cf9 1120 gimple def_stmt;
b5860aba 1121
1122 /* The optimization that we really care about is removing unnecessary
1123 casts. That will let us do much better in propagating the inferred
1124 constant at the switch target. */
1125 if (TREE_CODE (cond) == SSA_NAME)
1126 {
75a70cf9 1127 def_stmt = SSA_NAME_DEF_STMT (cond);
1128 if (is_gimple_assign (def_stmt))
b5860aba 1129 {
75a70cf9 1130 if (gimple_assign_rhs_code (def_stmt) == NOP_EXPR)
b5860aba 1131 {
1132 int need_precision;
1133 bool fail;
1134
75a70cf9 1135 def = gimple_assign_rhs1 (def_stmt);
b5860aba 1136
1137#ifdef ENABLE_CHECKING
1138 /* ??? Why was Jeff testing this? We are gimple... */
1139 gcc_assert (is_gimple_val (def));
1140#endif
1141
1142 to = TREE_TYPE (cond);
1143 ti = TREE_TYPE (def);
1144
1145 /* If we have an extension that preserves value, then we
1146 can copy the source value into the switch. */
1147
1148 need_precision = TYPE_PRECISION (ti);
1149 fail = false;
c5237b8b 1150 if (! INTEGRAL_TYPE_P (ti))
1151 fail = true;
1152 else if (TYPE_UNSIGNED (to) && !TYPE_UNSIGNED (ti))
b5860aba 1153 fail = true;
1154 else if (!TYPE_UNSIGNED (to) && TYPE_UNSIGNED (ti))
1155 need_precision += 1;
1156 if (TYPE_PRECISION (to) < need_precision)
1157 fail = true;
1158
1159 if (!fail)
1160 {
75a70cf9 1161 gimple_switch_set_index (stmt, def);
b5860aba 1162 update_stmt (stmt);
1163 }
1164 }
1165 }
1166 }
1167}
1168
1c4607fd 1169/* Run bitwise and assignments throug the folder. If the first argument is an
1170 ssa name that is itself a result of a typecast of an ADDR_EXPR to an
1171 integer, feed the ADDR_EXPR to the folder rather than the ssa name.
1172*/
1173
1174static void
1175simplify_bitwise_and (gimple_stmt_iterator *gsi, gimple stmt)
1176{
1177 tree res;
1178 tree arg1 = gimple_assign_rhs1 (stmt);
1179 tree arg2 = gimple_assign_rhs2 (stmt);
1180
1181 if (TREE_CODE (arg2) != INTEGER_CST)
1182 return;
1183
1184 if (TREE_CODE (arg1) == SSA_NAME && !SSA_NAME_IS_DEFAULT_DEF (arg1))
1185 {
1186 gimple def = SSA_NAME_DEF_STMT (arg1);
1187
1188 if (gimple_assign_cast_p (def)
1189 && INTEGRAL_TYPE_P (gimple_expr_type (def)))
1190 {
1191 tree op = gimple_assign_rhs1 (def);
1192
1193 if (TREE_CODE (op) == ADDR_EXPR)
1194 arg1 = op;
1195 }
1196 }
1197
1198 res = fold_binary (BIT_AND_EXPR, TREE_TYPE (gimple_assign_lhs (stmt)),
1199 arg1, arg2);
1200 if (res && is_gimple_min_invariant (res))
1201 {
1202 gimple_assign_set_rhs_from_tree (gsi, res);
1203 update_stmt (stmt);
1204 }
1205 return;
1206}
1207
4ee9c684 1208/* Main entry point for the forward propagation optimizer. */
1209
2a1990e9 1210static unsigned int
4ee9c684 1211tree_ssa_forward_propagate_single_use_vars (void)
1212{
f5c8cff5 1213 basic_block bb;
c96420f8 1214 unsigned int todoflags = 0;
4ee9c684 1215
148aa112 1216 cfg_changed = false;
1217
f5c8cff5 1218 FOR_EACH_BB (bb)
1219 {
75a70cf9 1220 gimple_stmt_iterator gsi;
291d763b 1221
75a70cf9 1222 /* Note we update GSI within the loop as necessary. */
1223 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
291d763b 1224 {
75a70cf9 1225 gimple stmt = gsi_stmt (gsi);
291d763b 1226
1227 /* If this statement sets an SSA_NAME to an address,
1228 try to propagate the address into the uses of the SSA_NAME. */
75a70cf9 1229 if (is_gimple_assign (stmt))
291d763b 1230 {
75a70cf9 1231 tree lhs = gimple_assign_lhs (stmt);
1232 tree rhs = gimple_assign_rhs1 (stmt);
3a938499 1233
1234 if (TREE_CODE (lhs) != SSA_NAME)
1235 {
75a70cf9 1236 gsi_next (&gsi);
3a938499 1237 continue;
1238 }
1239
75a70cf9 1240 if (gimple_assign_rhs_code (stmt) == ADDR_EXPR
971c637a 1241 /* Handle pointer conversions on invariant addresses
1242 as well, as this is valid gimple. */
d9659041 1243 || (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
75a70cf9 1244 && TREE_CODE (rhs) == ADDR_EXPR
1245 && POINTER_TYPE_P (TREE_TYPE (lhs))))
3a938499 1246 {
971c637a 1247 STRIP_NOPS (rhs);
b75537fb 1248 if (!stmt_references_abnormal_ssa_name (stmt)
1249 && forward_propagate_addr_expr (lhs, rhs))
24838d3f 1250 {
1251 release_defs (stmt);
ea0ab927 1252 todoflags |= TODO_remove_unused_locals;
75a70cf9 1253 gsi_remove (&gsi, true);
24838d3f 1254 }
3a938499 1255 else
75a70cf9 1256 gsi_next (&gsi);
3a938499 1257 }
87c5de3b 1258 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
1259 && is_gimple_min_invariant (rhs))
1260 {
1261 /* Make sure to fold &a[0] + off_1 here. */
1262 fold_stmt_inplace (stmt);
1263 update_stmt (stmt);
1264 if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1265 gsi_next (&gsi);
1266 }
75a70cf9 1267 else if ((gimple_assign_rhs_code (stmt) == BIT_NOT_EXPR
1268 || gimple_assign_rhs_code (stmt) == NEGATE_EXPR)
1269 && TREE_CODE (rhs) == SSA_NAME)
3a938499 1270 {
75a70cf9 1271 simplify_not_neg_expr (&gsi);
1272 gsi_next (&gsi);
3a938499 1273 }
75a70cf9 1274 else if (gimple_assign_rhs_code (stmt) == COND_EXPR)
ec0fa513 1275 {
75a70cf9 1276 /* In this case the entire COND_EXPR is in rhs1. */
4c580c8c 1277 int did_something;
d080be9e 1278 fold_defer_overflow_warnings ();
75a70cf9 1279 did_something = forward_propagate_into_cond (&gsi);
1280 stmt = gsi_stmt (gsi);
4c580c8c 1281 if (did_something == 2)
1282 cfg_changed = true;
d080be9e 1283 fold_undefer_overflow_warnings (!TREE_NO_WARNING (rhs)
1284 && did_something, stmt, WARN_STRICT_OVERFLOW_CONDITIONAL);
75a70cf9 1285 gsi_next (&gsi);
ec0fa513 1286 }
75a70cf9 1287 else if (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
1288 == tcc_comparison)
5adc1066 1289 {
75a70cf9 1290 if (forward_propagate_comparison (stmt))
5adc1066 1291 {
1292 release_defs (stmt);
1293 todoflags |= TODO_remove_unused_locals;
75a70cf9 1294 gsi_remove (&gsi, true);
5adc1066 1295 }
1296 else
75a70cf9 1297 gsi_next (&gsi);
5adc1066 1298 }
1c4607fd 1299 else if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR)
1300 {
1301 simplify_bitwise_and (&gsi, stmt);
1302 gsi_next (&gsi);
1303 }
291d763b 1304 else
75a70cf9 1305 gsi_next (&gsi);
291d763b 1306 }
75a70cf9 1307 else if (gimple_code (stmt) == GIMPLE_SWITCH)
b5860aba 1308 {
75a70cf9 1309 simplify_gimple_switch (stmt);
1310 gsi_next (&gsi);
b5860aba 1311 }
75a70cf9 1312 else if (gimple_code (stmt) == GIMPLE_COND)
291d763b 1313 {
4c580c8c 1314 int did_something;
d080be9e 1315 fold_defer_overflow_warnings ();
75a70cf9 1316 did_something = forward_propagate_into_gimple_cond (stmt);
4c580c8c 1317 if (did_something == 2)
1318 cfg_changed = true;
72c59a18 1319 fold_undefer_overflow_warnings (did_something, stmt,
d080be9e 1320 WARN_STRICT_OVERFLOW_CONDITIONAL);
75a70cf9 1321 gsi_next (&gsi);
291d763b 1322 }
1323 else
75a70cf9 1324 gsi_next (&gsi);
291d763b 1325 }
f5c8cff5 1326 }
148aa112 1327
1328 if (cfg_changed)
6fa78c7b 1329 todoflags |= TODO_cleanup_cfg;
c96420f8 1330 return todoflags;
4ee9c684 1331}
1332
1333
1334static bool
1335gate_forwprop (void)
1336{
1337 return 1;
1338}
1339
20099e35 1340struct gimple_opt_pass pass_forwprop =
1341{
1342 {
1343 GIMPLE_PASS,
4ee9c684 1344 "forwprop", /* name */
1345 gate_forwprop, /* gate */
1346 tree_ssa_forward_propagate_single_use_vars, /* execute */
1347 NULL, /* sub */
1348 NULL, /* next */
1349 0, /* static_pass_number */
1350 TV_TREE_FORWPROP, /* tv_id */
49290934 1351 PROP_cfg | PROP_ssa, /* properties_required */
4ee9c684 1352 0, /* properties_provided */
b6246c40 1353 0, /* properties_destroyed */
4ee9c684 1354 0, /* todo_flags_start */
de6ed584 1355 TODO_dump_func
abd433a7 1356 | TODO_ggc_collect
de6ed584 1357 | TODO_update_ssa
20099e35 1358 | TODO_verify_ssa /* todo_flags_finish */
1359 }
4ee9c684 1360};
37361b38 1361