1 /* Back-propagation of usage information to definitions.
2 Copyright (C) 2015-2018 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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 3, or (at your option)
9 any later version.
10
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.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 /* This pass propagates information that is common to all uses of an SSA
21 name back up through the sequence of statements that generate it,
22 simplifying the statements where possible. Sometimes this can expose
23 fully or partially dead code, but the main focus is simplifying
24 computations.
25
26 At the moment the pass only handles one piece of information: whether the
27 sign of a value matters, and therefore whether sign-changing operations
28 can be skipped. The pass could be extended to more interesting
29 information in future, such as which bits of an integer are significant.
30
31 For example, take the function:
32
33 double
34 f (double *a, int n, double start)
35 {
36 double x = fabs (start);
37 for (int i = 0; i < n; ++i)
38 x *= a[i];
39 return __builtin_cos (x);
40 }
41
42 cos(x) == cos(-x), so the sign of the final x doesn't matter.
43 That x is the result of a series of multiplications, and if
44 the sign of the result of a multiplication doesn't matter,
45 the signs of the inputs don't matter either.
46
47 The pass would replace the incoming value of x (i.e. fabs(start))
48 with start. Since there are no other uses of the fabs result,
49 the call would get deleted as dead.
50
51 The algorithm is:
52
53 (1) Do a post-order traversal of the blocks in the function, walking
54 each block backwards. For each potentially-simplifiable statement
55 that defines an SSA name X, examine all uses of X to see what
56 information is actually significant. Record this as INFO_MAP[X].
57 Optimistically ignore for now any back-edge references to
58 unprocessed phis.
59
60 (An alternative would be to record each use when we visit its
61 statement and take the intersection as we go along. However,
62 this would lead to more SSA names being entered into INFO_MAP
63 unnecessarily, only to be taken out again later. At the moment
64 very few SSA names end up with useful information.)
65
66 (2) Iteratively reduce the optimistic result of (1) until we reach
67 a maximal fixed point (which at the moment would mean revisiting
68 statements at most once). First push all SSA names that used an
69 optimistic assumption about a backedge phi onto a worklist.
70 While the worklist is nonempty, pick off an SSA name X and recompute
71 INFO_MAP[X]. If the value changes, push all SSA names used in the
72 definition of X onto the worklist.
73
74 (3) Iterate over each SSA name X with info in INFO_MAP, in the
75 opposite order to (1), i.e. a forward reverse-post-order walk.
76 Try to optimize the definition of X using INFO_MAP[X] and fold
77 the result. (This ensures that we fold definitions before uses.)
78
79 (4) Iterate over each SSA name X with info in INFO_MAP, in the same
80 order as (1), and delete any statements that are now dead.
81 (This ensures that if a sequence of statements is dead,
82 we delete the last statement first.)
83
84 Note that this pass does not deal with direct redundancies,
85 such as cos(-x)->cos(x). match.pd handles those cases instead. */
86
87 #include "config.h"
88 #include "system.h"
89 #include "coretypes.h"
90 #include "backend.h"
91 #include "tree.h"
92 #include "gimple.h"
93 #include "gimple-iterator.h"
94 #include "ssa.h"
95 #include "fold-const.h"
96 #include "tree-pass.h"
97 #include "cfganal.h"
98 #include "gimple-pretty-print.h"
99 #include "tree-cfg.h"
100 #include "tree-ssa.h"
101 #include "tree-ssa-propagate.h"
102 #include "gimple-fold.h"
103 #include "alloc-pool.h"
104 #include "tree-hash-traits.h"
105 #include "case-cfn-macros.h"
106
107 namespace {
108
109 /* Information about a group of uses of an SSA name. */
110 struct usage_info
111 {
usage_infousage_info112 usage_info () : flag_word (0) {}
113 usage_info &operator &= (const usage_info &);
114 usage_info operator & (const usage_info &) const;
115 bool operator == (const usage_info &) const;
116 bool operator != (const usage_info &) const;
117 bool is_useful () const;
118
119 static usage_info intersection_identity ();
120
121 union
122 {
123 struct
124 {
125 /* True if the uses treat x and -x in the same way. */
126 unsigned int ignore_sign : 1;
127 } flags;
128 /* All the flag bits as a single int. */
129 unsigned int flag_word;
130 };
131 };
132
133 /* Return an X such that X & Y == Y for all Y. This is the most
134 optimistic assumption possible. */
135
136 usage_info
intersection_identity()137 usage_info::intersection_identity ()
138 {
139 usage_info ret;
140 ret.flag_word = -1;
141 return ret;
142 }
143
144 /* Intersect *THIS with OTHER, so that *THIS describes all uses covered
145 by the original *THIS and OTHER. */
146
147 usage_info &
148 usage_info::operator &= (const usage_info &other)
149 {
150 flag_word &= other.flag_word;
151 return *this;
152 }
153
154 /* Return the intersection of *THIS and OTHER, i.e. a structure that
155 describes all uses covered by *THIS and OTHER. */
156
157 usage_info
158 usage_info::operator & (const usage_info &other) const
159 {
160 usage_info info (*this);
161 info &= other;
162 return info;
163 }
164
165 bool
166 usage_info::operator == (const usage_info &other) const
167 {
168 return flag_word == other.flag_word;
169 }
170
171 bool
172 usage_info::operator != (const usage_info &other) const
173 {
174 return !operator == (other);
175 }
176
177 /* Return true if *THIS is not simply the default, safe assumption. */
178
179 bool
is_useful()180 usage_info::is_useful () const
181 {
182 return flag_word != 0;
183 }
184
185 /* Start a dump line about SSA name VAR. */
186
187 static void
dump_usage_prefix(FILE * file,tree var)188 dump_usage_prefix (FILE *file, tree var)
189 {
190 fprintf (file, " ");
191 print_generic_expr (file, var);
192 fprintf (file, ": ");
193 }
194
195 /* Print INFO to FILE. */
196
197 static void
dump_usage_info(FILE * file,tree var,usage_info * info)198 dump_usage_info (FILE *file, tree var, usage_info *info)
199 {
200 if (info->flags.ignore_sign)
201 {
202 dump_usage_prefix (file, var);
203 fprintf (file, "sign bit not important\n");
204 }
205 }
206
207 /* Represents one execution of the pass. */
208 class backprop
209 {
210 public:
211 backprop (function *);
212 ~backprop ();
213
214 void execute ();
215
216 private:
217 const usage_info *lookup_operand (tree);
218
219 void push_to_worklist (tree);
220 tree pop_from_worklist ();
221
222 void process_builtin_call_use (gcall *, tree, usage_info *);
223 void process_assign_use (gassign *, tree, usage_info *);
224 void process_phi_use (gphi *, usage_info *);
225 void process_use (gimple *, tree, usage_info *);
226 bool intersect_uses (tree, usage_info *);
227 void reprocess_inputs (gimple *);
228 void process_var (tree);
229 void process_block (basic_block);
230
231 void prepare_change (tree);
232 void complete_change (gimple *);
233 void optimize_builtin_call (gcall *, tree, const usage_info *);
234 void replace_assign_rhs (gassign *, tree, tree, tree, tree);
235 void optimize_assign (gassign *, tree, const usage_info *);
236 void optimize_phi (gphi *, tree, const usage_info *);
237
238 typedef hash_map <tree_ssa_name_hash, usage_info *> info_map_type;
239 typedef std::pair <tree, usage_info *> var_info_pair;
240
241 /* The function we're optimizing. */
242 function *m_fn;
243
244 /* Pool for allocating usage_info structures. */
245 object_allocator <usage_info> m_info_pool;
246
247 /* Maps an SSA name to a description of all uses of that SSA name.
248 All the usage_infos satisfy is_useful.
249
250 We use a hash_map because the map is expected to be sparse
251 (i.e. most SSA names won't have useful information attached to them).
252 We could move to a directly-indexed array if that situation changes. */
253 info_map_type m_info_map;
254
255 /* Post-ordered list of all potentially-interesting SSA names,
256 along with information that describes all uses. */
257 auto_vec <var_info_pair, 128> m_vars;
258
259 /* A bitmap of blocks that we have finished processing in the initial
260 post-order walk. */
261 auto_sbitmap m_visited_blocks;
262
263 /* A bitmap of phis that we have finished processing in the initial
264 post-order walk, excluding those from blocks mentioned in
265 M_VISITED_BLOCKS. */
266 auto_bitmap m_visited_phis;
267
268 /* A worklist of SSA names whose definitions need to be reconsidered. */
269 auto_vec <tree, 64> m_worklist;
270
271 /* The SSA names in M_WORKLIST, identified by their SSA_NAME_VERSION.
272 We use a bitmap rather than an sbitmap because most SSA names are
273 never added to the worklist. */
274 bitmap m_worklist_names;
275 };
276
backprop(function * fn)277 backprop::backprop (function *fn)
278 : m_fn (fn),
279 m_info_pool ("usage_info"),
280 m_visited_blocks (last_basic_block_for_fn (m_fn)),
281 m_worklist_names (BITMAP_ALLOC (NULL))
282 {
283 bitmap_clear (m_visited_blocks);
284 }
285
~backprop()286 backprop::~backprop ()
287 {
288 BITMAP_FREE (m_worklist_names);
289 m_info_pool.release ();
290 }
291
292 /* Return usage information for general operand OP, or null if none. */
293
294 const usage_info *
lookup_operand(tree op)295 backprop::lookup_operand (tree op)
296 {
297 if (op && TREE_CODE (op) == SSA_NAME)
298 {
299 usage_info **slot = m_info_map.get (op);
300 if (slot)
301 return *slot;
302 }
303 return NULL;
304 }
305
306 /* Add SSA name VAR to the worklist, if it isn't on the worklist already. */
307
308 void
push_to_worklist(tree var)309 backprop::push_to_worklist (tree var)
310 {
311 if (!bitmap_set_bit (m_worklist_names, SSA_NAME_VERSION (var)))
312 return;
313 m_worklist.safe_push (var);
314 if (dump_file && (dump_flags & TDF_DETAILS))
315 {
316 fprintf (dump_file, "[WORKLIST] Pushing ");
317 print_generic_expr (dump_file, var);
318 fprintf (dump_file, "\n");
319 }
320 }
321
322 /* Remove and return the next SSA name from the worklist. The worklist
323 is known to be nonempty. */
324
325 tree
pop_from_worklist()326 backprop::pop_from_worklist ()
327 {
328 tree var = m_worklist.pop ();
329 bitmap_clear_bit (m_worklist_names, SSA_NAME_VERSION (var));
330 if (dump_file && (dump_flags & TDF_DETAILS))
331 {
332 fprintf (dump_file, "[WORKLIST] Popping ");
333 print_generic_expr (dump_file, var);
334 fprintf (dump_file, "\n");
335 }
336 return var;
337 }
338
339 /* Make INFO describe all uses of RHS in CALL, which is a call to a
340 built-in function. */
341
342 void
process_builtin_call_use(gcall * call,tree rhs,usage_info * info)343 backprop::process_builtin_call_use (gcall *call, tree rhs, usage_info *info)
344 {
345 combined_fn fn = gimple_call_combined_fn (call);
346 tree lhs = gimple_call_lhs (call);
347 switch (fn)
348 {
349 case CFN_LAST:
350 break;
351
352 CASE_CFN_COS:
353 CASE_CFN_COSH:
354 CASE_CFN_CCOS:
355 CASE_CFN_CCOSH:
356 CASE_CFN_HYPOT:
357 /* The signs of all inputs are ignored. */
358 info->flags.ignore_sign = true;
359 break;
360
361 CASE_CFN_COPYSIGN:
362 CASE_CFN_COPYSIGN_FN:
363 /* The sign of the first input is ignored. */
364 if (rhs != gimple_call_arg (call, 1))
365 info->flags.ignore_sign = true;
366 break;
367
368 CASE_CFN_POW:
369 {
370 /* The sign of the first input is ignored as long as the second
371 input is an even real. */
372 tree power = gimple_call_arg (call, 1);
373 HOST_WIDE_INT n;
374 if (TREE_CODE (power) == REAL_CST
375 && real_isinteger (&TREE_REAL_CST (power), &n)
376 && (n & 1) == 0)
377 info->flags.ignore_sign = true;
378 break;
379 }
380
381 CASE_CFN_FMA:
382 CASE_CFN_FMA_FN:
383 /* In X * X + Y, where Y is distinct from X, the sign of X doesn't
384 matter. */
385 if (gimple_call_arg (call, 0) == rhs
386 && gimple_call_arg (call, 1) == rhs
387 && gimple_call_arg (call, 2) != rhs)
388 info->flags.ignore_sign = true;
389 break;
390
391 default:
392 if (negate_mathfn_p (fn))
393 {
394 /* The sign of the (single) input doesn't matter provided
395 that the sign of the output doesn't matter. */
396 const usage_info *lhs_info = lookup_operand (lhs);
397 if (lhs_info)
398 info->flags.ignore_sign = lhs_info->flags.ignore_sign;
399 }
400 break;
401 }
402 }
403
404 /* Make INFO describe all uses of RHS in ASSIGN. */
405
406 void
process_assign_use(gassign * assign,tree rhs,usage_info * info)407 backprop::process_assign_use (gassign *assign, tree rhs, usage_info *info)
408 {
409 tree lhs = gimple_assign_lhs (assign);
410 switch (gimple_assign_rhs_code (assign))
411 {
412 case ABS_EXPR:
413 /* The sign of the input doesn't matter. */
414 info->flags.ignore_sign = true;
415 break;
416
417 case COND_EXPR:
418 /* For A = B ? C : D, propagate information about all uses of A
419 to C and D. */
420 if (rhs != gimple_assign_rhs1 (assign))
421 {
422 const usage_info *lhs_info = lookup_operand (lhs);
423 if (lhs_info)
424 *info = *lhs_info;
425 }
426 break;
427
428 case FMA_EXPR:
429 /* In X * X + Y, where Y is distinct from X, the sign of X doesn't
430 matter. */
431 if (gimple_assign_rhs1 (assign) == rhs
432 && gimple_assign_rhs2 (assign) == rhs
433 && gimple_assign_rhs3 (assign) != rhs)
434 info->flags.ignore_sign = true;
435 break;
436
437 case MULT_EXPR:
438 /* In X * X, the sign of X doesn't matter. */
439 if (gimple_assign_rhs1 (assign) == rhs
440 && gimple_assign_rhs2 (assign) == rhs)
441 info->flags.ignore_sign = true;
442 /* Fall through. */
443
444 case NEGATE_EXPR:
445 case RDIV_EXPR:
446 /* If the sign of the result doesn't matter, the sign of the inputs
447 doesn't matter either. */
448 if (FLOAT_TYPE_P (TREE_TYPE (rhs)))
449 {
450 const usage_info *lhs_info = lookup_operand (lhs);
451 if (lhs_info)
452 info->flags.ignore_sign = lhs_info->flags.ignore_sign;
453 }
454 break;
455
456 default:
457 break;
458 }
459 }
460
461 /* Make INFO describe the uses of PHI's result. */
462
463 void
process_phi_use(gphi * phi,usage_info * info)464 backprop::process_phi_use (gphi *phi, usage_info *info)
465 {
466 tree result = gimple_phi_result (phi);
467 if (const usage_info *result_info = lookup_operand (result))
468 *info = *result_info;
469 }
470
471 /* Make INFO describe all uses of RHS in STMT. */
472
473 void
process_use(gimple * stmt,tree rhs,usage_info * info)474 backprop::process_use (gimple *stmt, tree rhs, usage_info *info)
475 {
476 if (dump_file && (dump_flags & TDF_DETAILS))
477 {
478 fprintf (dump_file, "[USE] ");
479 print_generic_expr (dump_file, rhs);
480 fprintf (dump_file, " in ");
481 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
482 }
483
484 if (gcall *call = dyn_cast <gcall *> (stmt))
485 process_builtin_call_use (call, rhs, info);
486 else if (gassign *assign = dyn_cast <gassign *> (stmt))
487 process_assign_use (assign, rhs, info);
488 else if (gphi *phi = dyn_cast <gphi *> (stmt))
489 process_phi_use (phi, info);
490
491 if (dump_file && (dump_flags & TDF_DETAILS))
492 dump_usage_info (dump_file, rhs, info);
493 }
494
495 /* Make INFO describe all uses of VAR, returning true if the result
496 is useful. If the uses include phis that haven't been processed yet,
497 make the most optimistic assumption possible, so that we aim for
498 a maximum rather than a minimum fixed point. */
499
500 bool
intersect_uses(tree var,usage_info * info)501 backprop::intersect_uses (tree var, usage_info *info)
502 {
503 imm_use_iterator iter;
504 use_operand_p use_p;
505 *info = usage_info::intersection_identity ();
506 FOR_EACH_IMM_USE_FAST (use_p, iter, var)
507 {
508 gimple *stmt = USE_STMT (use_p);
509 if (is_gimple_debug (stmt))
510 continue;
511 gphi *phi = dyn_cast <gphi *> (stmt);
512 if (phi
513 && !bitmap_bit_p (m_visited_blocks, gimple_bb (phi)->index)
514 && !bitmap_bit_p (m_visited_phis,
515 SSA_NAME_VERSION (gimple_phi_result (phi))))
516 {
517 /* Skip unprocessed phis. */
518 if (dump_file && (dump_flags & TDF_DETAILS))
519 {
520 fprintf (dump_file, "[BACKEDGE] ");
521 print_generic_expr (dump_file, var);
522 fprintf (dump_file, " in ");
523 print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
524 }
525 }
526 else
527 {
528 usage_info subinfo;
529 process_use (stmt, var, &subinfo);
530 *info &= subinfo;
531 if (!info->is_useful ())
532 return false;
533 }
534 }
535 return true;
536 }
537
538 /* Queue for reconsideration any input of STMT that has information
539 associated with it. This is used if that information might be
540 too optimistic. */
541
542 void
reprocess_inputs(gimple * stmt)543 backprop::reprocess_inputs (gimple *stmt)
544 {
545 use_operand_p use_p;
546 ssa_op_iter oi;
547 FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, oi, SSA_OP_USE)
548 {
549 tree var = get_use_from_ptr (use_p);
550 if (lookup_operand (var))
551 push_to_worklist (var);
552 }
553 }
554
555 /* Say that we're recording INFO for SSA name VAR, or that we're deleting
556 existing information if INFO is null. INTRO describes the change. */
557
558 static void
dump_var_info(tree var,usage_info * info,const char * intro)559 dump_var_info (tree var, usage_info *info, const char *intro)
560 {
561 fprintf (dump_file, "[DEF] %s for ", intro);
562 print_gimple_stmt (dump_file, SSA_NAME_DEF_STMT (var), 0, TDF_SLIM);
563 if (info)
564 dump_usage_info (dump_file, var, info);
565 }
566
567 /* Process all uses of VAR and record or update the result in
568 M_INFO_MAP and M_VARS. */
569
570 void
process_var(tree var)571 backprop::process_var (tree var)
572 {
573 if (has_zero_uses (var))
574 return;
575
576 usage_info info;
577 intersect_uses (var, &info);
578
579 gimple *stmt = SSA_NAME_DEF_STMT (var);
580 if (info.is_useful ())
581 {
582 bool existed;
583 usage_info *&map_info = m_info_map.get_or_insert (var, &existed);
584 if (!existed)
585 {
586 /* Recording information about VAR for the first time. */
587 map_info = m_info_pool.allocate ();
588 *map_info = info;
589 m_vars.safe_push (var_info_pair (var, map_info));
590 if (dump_file && (dump_flags & TDF_DETAILS))
591 dump_var_info (var, map_info, "Recording new information");
592
593 /* If STMT is a phi, reprocess any backedge uses. This is a
594 no-op for other uses, which won't have any information
595 associated with them. */
596 if (is_a <gphi *> (stmt))
597 reprocess_inputs (stmt);
598 }
599 else if (info != *map_info)
600 {
601 /* Recording information that is less optimistic than before. */
602 gcc_checking_assert ((info & *map_info) == info);
603 *map_info = info;
604 if (dump_file && (dump_flags & TDF_DETAILS))
605 dump_var_info (var, map_info, "Updating information");
606 reprocess_inputs (stmt);
607 }
608 }
609 else
610 {
611 if (usage_info **slot = m_info_map.get (var))
612 {
613 /* Removing previously-recorded information. */
614 **slot = info;
615 m_info_map.remove (var);
616 if (dump_file && (dump_flags & TDF_DETAILS))
617 dump_var_info (var, NULL, "Deleting information");
618 reprocess_inputs (stmt);
619 }
620 else
621 {
622 /* If STMT is a phi, remove any information recorded for
623 its arguments. */
624 if (is_a <gphi *> (stmt))
625 reprocess_inputs (stmt);
626 }
627 }
628 }
629
630 /* Process all statements and phis in BB, during the first post-order walk. */
631
632 void
process_block(basic_block bb)633 backprop::process_block (basic_block bb)
634 {
635 for (gimple_stmt_iterator gsi = gsi_last_bb (bb); !gsi_end_p (gsi);
636 gsi_prev (&gsi))
637 {
638 tree lhs = gimple_get_lhs (gsi_stmt (gsi));
639 if (lhs && TREE_CODE (lhs) == SSA_NAME)
640 process_var (lhs);
641 }
642 for (gphi_iterator gpi = gsi_start_phis (bb); !gsi_end_p (gpi);
643 gsi_next (&gpi))
644 {
645 tree result = gimple_phi_result (gpi.phi ());
646 process_var (result);
647 bitmap_set_bit (m_visited_phis, SSA_NAME_VERSION (result));
648 }
649 bitmap_clear (m_visited_phis);
650 }
651
652 /* Delete the definition of VAR, which has no uses. */
653
654 static void
remove_unused_var(tree var)655 remove_unused_var (tree var)
656 {
657 gimple *stmt = SSA_NAME_DEF_STMT (var);
658 if (dump_file && (dump_flags & TDF_DETAILS))
659 {
660 fprintf (dump_file, "Deleting ");
661 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
662 }
663 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
664 gsi_remove (&gsi, true);
665 release_defs (stmt);
666 }
667
668 /* Note that we're replacing OLD_RHS with NEW_RHS in STMT. */
669
670 static void
note_replacement(gimple * stmt,tree old_rhs,tree new_rhs)671 note_replacement (gimple *stmt, tree old_rhs, tree new_rhs)
672 {
673 fprintf (dump_file, "Replacing use of ");
674 print_generic_expr (dump_file, old_rhs);
675 fprintf (dump_file, " with ");
676 print_generic_expr (dump_file, new_rhs);
677 fprintf (dump_file, " in ");
678 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
679 }
680
681 /* If RHS is an SSA name whose definition just changes the sign of a value,
682 return that other value, otherwise return null. */
683
684 static tree
strip_sign_op_1(tree rhs)685 strip_sign_op_1 (tree rhs)
686 {
687 if (TREE_CODE (rhs) != SSA_NAME)
688 return NULL_TREE;
689
690 gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
691 if (gassign *assign = dyn_cast <gassign *> (def_stmt))
692 switch (gimple_assign_rhs_code (assign))
693 {
694 case ABS_EXPR:
695 case NEGATE_EXPR:
696 return gimple_assign_rhs1 (assign);
697
698 default:
699 break;
700 }
701 else if (gcall *call = dyn_cast <gcall *> (def_stmt))
702 switch (gimple_call_combined_fn (call))
703 {
704 CASE_CFN_COPYSIGN:
705 CASE_CFN_COPYSIGN_FN:
706 return gimple_call_arg (call, 0);
707
708 default:
709 break;
710 }
711
712 return NULL_TREE;
713 }
714
715 /* If RHS is an SSA name whose definition just changes the sign of a value,
716 strip all such operations and return the ultimate input to them.
717 Return null otherwise.
718
719 Although this could in principle lead to quadratic searching,
720 in practice a long sequence of sign manipulations should already
721 have been folded down. E.g. --x -> x, abs(-x) -> abs(x). We search
722 for more than one operation in order to catch cases like -abs(x). */
723
724 static tree
strip_sign_op(tree rhs)725 strip_sign_op (tree rhs)
726 {
727 tree new_rhs = strip_sign_op_1 (rhs);
728 if (!new_rhs)
729 return NULL_TREE;
730 while (tree next = strip_sign_op_1 (new_rhs))
731 new_rhs = next;
732 return new_rhs;
733 }
734
735 /* Start a change in the value of VAR that is suitable for all non-debug
736 uses of VAR. We need to make sure that debug statements continue to
737 use the original definition of VAR where possible, or are nullified
738 otherwise. */
739
740 void
prepare_change(tree var)741 backprop::prepare_change (tree var)
742 {
743 if (MAY_HAVE_DEBUG_BIND_STMTS)
744 insert_debug_temp_for_var_def (NULL, var);
745 reset_flow_sensitive_info (var);
746 }
747
748 /* STMT has been changed. Give the fold machinery a chance to simplify
749 and canonicalize it (e.g. by ensuring that commutative operands have
750 the right order), then record the updates. */
751
752 void
complete_change(gimple * stmt)753 backprop::complete_change (gimple *stmt)
754 {
755 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
756 if (fold_stmt (&gsi))
757 {
758 if (dump_file && (dump_flags & TDF_DETAILS))
759 {
760 fprintf (dump_file, " which folds to: ");
761 print_gimple_stmt (dump_file, gsi_stmt (gsi), 0, TDF_SLIM);
762 }
763 }
764 update_stmt (gsi_stmt (gsi));
765 }
766
767 /* Optimize CALL, a call to a built-in function with lhs LHS, on the
768 basis that INFO describes all uses of LHS. */
769
770 void
optimize_builtin_call(gcall * call,tree lhs,const usage_info * info)771 backprop::optimize_builtin_call (gcall *call, tree lhs, const usage_info *info)
772 {
773 /* If we have an f such that -f(x) = f(-x), and if the sign of the result
774 doesn't matter, strip any sign operations from the input. */
775 if (info->flags.ignore_sign
776 && negate_mathfn_p (gimple_call_combined_fn (call)))
777 {
778 tree new_arg = strip_sign_op (gimple_call_arg (call, 0));
779 if (new_arg)
780 {
781 prepare_change (lhs);
782 gimple_call_set_arg (call, 0, new_arg);
783 complete_change (call);
784 }
785 }
786 }
787
788 /* Optimize ASSIGN, an assignment to LHS, by replacing rhs operand N
789 with RHS<N>, if RHS<N> is nonnull. This may change the value of LHS. */
790
791 void
replace_assign_rhs(gassign * assign,tree lhs,tree rhs1,tree rhs2,tree rhs3)792 backprop::replace_assign_rhs (gassign *assign, tree lhs, tree rhs1,
793 tree rhs2, tree rhs3)
794 {
795 if (!rhs1 && !rhs2 && !rhs3)
796 return;
797
798 prepare_change (lhs);
799 if (rhs1)
800 gimple_assign_set_rhs1 (assign, rhs1);
801 if (rhs2)
802 gimple_assign_set_rhs2 (assign, rhs2);
803 if (rhs3)
804 gimple_assign_set_rhs3 (assign, rhs3);
805 complete_change (assign);
806 }
807
808 /* Optimize ASSIGN, an assignment to LHS, on the basis that INFO
809 describes all uses of LHS. */
810
811 void
optimize_assign(gassign * assign,tree lhs,const usage_info * info)812 backprop::optimize_assign (gassign *assign, tree lhs, const usage_info *info)
813 {
814 switch (gimple_assign_rhs_code (assign))
815 {
816 case MULT_EXPR:
817 case RDIV_EXPR:
818 /* If the sign of the result doesn't matter, strip sign operations
819 from both inputs. */
820 if (info->flags.ignore_sign)
821 replace_assign_rhs (assign, lhs,
822 strip_sign_op (gimple_assign_rhs1 (assign)),
823 strip_sign_op (gimple_assign_rhs2 (assign)),
824 NULL_TREE);
825 break;
826
827 case COND_EXPR:
828 /* If the sign of A ? B : C doesn't matter, strip sign operations
829 from both B and C. */
830 if (info->flags.ignore_sign)
831 replace_assign_rhs (assign, lhs,
832 NULL_TREE,
833 strip_sign_op (gimple_assign_rhs2 (assign)),
834 strip_sign_op (gimple_assign_rhs3 (assign)));
835 break;
836
837 default:
838 break;
839 }
840 }
841
842 /* Optimize PHI, which defines VAR, on the basis that INFO describes all
843 uses of the result. */
844
845 void
optimize_phi(gphi * phi,tree var,const usage_info * info)846 backprop::optimize_phi (gphi *phi, tree var, const usage_info *info)
847 {
848 /* If the sign of the result doesn't matter, try to strip sign operations
849 from arguments. */
850 if (info->flags.ignore_sign)
851 {
852 basic_block bb = gimple_bb (phi);
853 use_operand_p use;
854 ssa_op_iter oi;
855 bool replaced = false;
856 FOR_EACH_PHI_ARG (use, phi, oi, SSA_OP_USE)
857 {
858 /* Propagating along abnormal edges is delicate, punt for now. */
859 const int index = PHI_ARG_INDEX_FROM_USE (use);
860 if (EDGE_PRED (bb, index)->flags & EDGE_ABNORMAL)
861 continue;
862
863 tree new_arg = strip_sign_op (USE_FROM_PTR (use));
864 if (new_arg)
865 {
866 if (!replaced)
867 prepare_change (var);
868 if (dump_file && (dump_flags & TDF_DETAILS))
869 note_replacement (phi, USE_FROM_PTR (use), new_arg);
870 replace_exp (use, new_arg);
871 replaced = true;
872 }
873 }
874 }
875 }
876
877 void
execute()878 backprop::execute ()
879 {
880 /* Phase 1: Traverse the function, making optimistic assumptions
881 about any phi whose definition we haven't seen. */
882 int *postorder = XNEWVEC (int, n_basic_blocks_for_fn (m_fn));
883 unsigned int postorder_num = post_order_compute (postorder, false, false);
884 for (unsigned int i = 0; i < postorder_num; ++i)
885 {
886 process_block (BASIC_BLOCK_FOR_FN (m_fn, postorder[i]));
887 bitmap_set_bit (m_visited_blocks, postorder[i]);
888 }
889 XDELETEVEC (postorder);
890
891 /* Phase 2: Use the initial (perhaps overly optimistic) information
892 to create a maximal fixed point solution. */
893 while (!m_worklist.is_empty ())
894 process_var (pop_from_worklist ());
895
896 if (dump_file && (dump_flags & TDF_DETAILS))
897 fprintf (dump_file, "\n");
898
899 /* Phase 3: Do a reverse post-order walk, using information about
900 the uses of SSA names to optimize their definitions. */
901 for (unsigned int i = m_vars.length (); i-- > 0;)
902 {
903 usage_info *info = m_vars[i].second;
904 if (info->is_useful ())
905 {
906 tree var = m_vars[i].first;
907 gimple *stmt = SSA_NAME_DEF_STMT (var);
908 if (gcall *call = dyn_cast <gcall *> (stmt))
909 optimize_builtin_call (call, var, info);
910 else if (gassign *assign = dyn_cast <gassign *> (stmt))
911 optimize_assign (assign, var, info);
912 else if (gphi *phi = dyn_cast <gphi *> (stmt))
913 optimize_phi (phi, var, info);
914 }
915 }
916
917 /* Phase 4: Do a post-order walk, deleting statements that are no
918 longer needed. */
919 for (unsigned int i = 0; i < m_vars.length (); ++i)
920 {
921 tree var = m_vars[i].first;
922 if (has_zero_uses (var))
923 remove_unused_var (var);
924 }
925
926 if (dump_file && (dump_flags & TDF_DETAILS))
927 fprintf (dump_file, "\n");
928 }
929
930 const pass_data pass_data_backprop =
931 {
932 GIMPLE_PASS, /* type */
933 "backprop", /* name */
934 OPTGROUP_NONE, /* optinfo_flags */
935 TV_TREE_BACKPROP, /* tv_id */
936 ( PROP_cfg | PROP_ssa ), /* properties_required */
937 0, /* properties_provided */
938 0, /* properties_destroyed */
939 0, /* todo_flags_start */
940 0, /* todo_flags_finish */
941 };
942
943 class pass_backprop : public gimple_opt_pass
944 {
945 public:
pass_backprop(gcc::context * ctxt)946 pass_backprop (gcc::context *ctxt)
947 : gimple_opt_pass (pass_data_backprop, ctxt)
948 {}
949
950 /* opt_pass methods: */
clone()951 opt_pass * clone () { return new pass_backprop (m_ctxt); }
gate(function *)952 virtual bool gate (function *) { return flag_ssa_backprop; }
953 virtual unsigned int execute (function *);
954
955 }; // class pass_backprop
956
957 unsigned int
execute(function * fn)958 pass_backprop::execute (function *fn)
959 {
960 backprop (fn).execute ();
961 return 0;
962 }
963
964 } // anon namespace
965
966 gimple_opt_pass *
make_pass_backprop(gcc::context * ctxt)967 make_pass_backprop (gcc::context *ctxt)
968 {
969 return new pass_backprop (ctxt);
970 }
971