coretypes.h: Include input.h and as-a.h.
[platform/upstream/gcc.git] / gcc / postreload-gcse.c
1 /* Post reload partially redundant load elimination
2    Copyright (C) 2004-2015 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 it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
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 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "diagnostic-core.h"
25
26 #include "rtl.h"
27 #include "alias.h"
28 #include "symtab.h"
29 #include "tree.h"
30 #include "tm_p.h"
31 #include "regs.h"
32 #include "hard-reg-set.h"
33 #include "flags.h"
34 #include "insn-config.h"
35 #include "recog.h"
36 #include "predict.h"
37 #include "function.h"
38 #include "dominance.h"
39 #include "cfg.h"
40 #include "cfgrtl.h"
41 #include "basic-block.h"
42 #include "profile.h"
43 #include "expmed.h"
44 #include "dojump.h"
45 #include "explow.h"
46 #include "calls.h"
47 #include "emit-rtl.h"
48 #include "varasm.h"
49 #include "stmt.h"
50 #include "expr.h"
51 #include "except.h"
52 #include "intl.h"
53 #include "obstack.h"
54 #include "params.h"
55 #include "target.h"
56 #include "tree-pass.h"
57 #include "dbgcnt.h"
58 #include "df.h"
59 #include "gcse-common.h"
60
61 /* The following code implements gcse after reload, the purpose of this
62    pass is to cleanup redundant loads generated by reload and other
63    optimizations that come after gcse. It searches for simple inter-block
64    redundancies and tries to eliminate them by adding moves and loads
65    in cold places.
66
67    Perform partially redundant load elimination, try to eliminate redundant
68    loads created by the reload pass.  We try to look for full or partial
69    redundant loads fed by one or more loads/stores in predecessor BBs,
70    and try adding loads to make them fully redundant.  We also check if
71    it's worth adding loads to be able to delete the redundant load.
72
73    Algorithm:
74    1. Build available expressions hash table:
75        For each load/store instruction, if the loaded/stored memory didn't
76        change until the end of the basic block add this memory expression to
77        the hash table.
78    2. Perform Redundancy elimination:
79       For each load instruction do the following:
80          perform partial redundancy elimination, check if it's worth adding
81          loads to make the load fully redundant.  If so add loads and
82          register copies and delete the load.
83    3. Delete instructions made redundant in step 2.
84
85    Future enhancement:
86      If the loaded register is used/defined between load and some store,
87      look for some other free register between load and all its stores,
88      and replace the load with a copy from this register to the loaded
89      register.
90 */
91 \f
92
93 /* Keep statistics of this pass.  */
94 static struct
95 {
96   int moves_inserted;
97   int copies_inserted;
98   int insns_deleted;
99 } stats;
100
101 /* We need to keep a hash table of expressions.  The table entries are of
102    type 'struct expr', and for each expression there is a single linked
103    list of occurrences.  */
104
105 /* Expression elements in the hash table.  */
106 struct expr
107 {
108   /* The expression (SET_SRC for expressions, PATTERN for assignments).  */
109   rtx expr;
110
111   /* The same hash for this entry.  */
112   hashval_t hash;
113
114   /* Index in the transparent bitmaps.  */
115   unsigned int bitmap_index;
116
117   /* List of available occurrence in basic blocks in the function.  */
118   struct occr *avail_occr;
119 };
120
121 /* Hashtable helpers.  */
122
123 struct expr_hasher : typed_noop_remove <expr>
124 {
125   typedef expr *value_type;
126   typedef expr *compare_type;
127   static inline hashval_t hash (const expr *);
128   static inline bool equal (const expr *, const expr *);
129 };
130
131
132 /* Hash expression X.
133    DO_NOT_RECORD_P is a boolean indicating if a volatile operand is found
134    or if the expression contains something we don't want to insert in the
135    table.  */
136
137 static hashval_t
138 hash_expr (rtx x, int *do_not_record_p)
139 {
140   *do_not_record_p = 0;
141   return hash_rtx (x, GET_MODE (x), do_not_record_p,
142                    NULL,  /*have_reg_qty=*/false);
143 }
144
145 /* Callback for hashtab.
146    Return the hash value for expression EXP.  We don't actually hash
147    here, we just return the cached hash value.  */
148
149 inline hashval_t
150 expr_hasher::hash (const expr *exp)
151 {
152   return exp->hash;
153 }
154
155 /* Callback for hashtab.
156    Return nonzero if exp1 is equivalent to exp2.  */
157
158 inline bool
159 expr_hasher::equal (const expr *exp1, const expr *exp2)
160 {
161   int equiv_p = exp_equiv_p (exp1->expr, exp2->expr, 0, true);
162
163   gcc_assert (!equiv_p || exp1->hash == exp2->hash);
164   return equiv_p;
165 }
166
167 /* The table itself.  */
168 static hash_table<expr_hasher> *expr_table;
169 \f
170
171 static struct obstack expr_obstack;
172
173 /* Occurrence of an expression.
174    There is at most one occurrence per basic block.  If a pattern appears
175    more than once, the last appearance is used.  */
176
177 struct occr
178 {
179   /* Next occurrence of this expression.  */
180   struct occr *next;
181   /* The insn that computes the expression.  */
182   rtx_insn *insn;
183   /* Nonzero if this [anticipatable] occurrence has been deleted.  */
184   char deleted_p;
185 };
186
187 static struct obstack occr_obstack;
188
189 /* The following structure holds the information about the occurrences of
190    the redundant instructions.  */
191 struct unoccr
192 {
193   struct unoccr *next;
194   edge pred;
195   rtx_insn *insn;
196 };
197
198 static struct obstack unoccr_obstack;
199
200 /* Array where each element is the CUID if the insn that last set the hard
201    register with the number of the element, since the start of the current
202    basic block.
203
204    This array is used during the building of the hash table (step 1) to
205    determine if a reg is killed before the end of a basic block.
206
207    It is also used when eliminating partial redundancies (step 2) to see
208    if a reg was modified since the start of a basic block.  */
209 static int *reg_avail_info;
210
211 /* A list of insns that may modify memory within the current basic block.  */
212 struct modifies_mem
213 {
214   rtx_insn *insn;
215   struct modifies_mem *next;
216 };
217 static struct modifies_mem *modifies_mem_list;
218
219 /* The modifies_mem structs also go on an obstack, only this obstack is
220    freed each time after completing the analysis or transformations on
221    a basic block.  So we allocate a dummy modifies_mem_obstack_bottom
222    object on the obstack to keep track of the bottom of the obstack.  */
223 static struct obstack modifies_mem_obstack;
224 static struct modifies_mem  *modifies_mem_obstack_bottom;
225
226 /* Mapping of insn UIDs to CUIDs.
227    CUIDs are like UIDs except they increase monotonically in each basic
228    block, have no gaps, and only apply to real insns.  */
229 static int *uid_cuid;
230 #define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)])
231
232 /* Bitmap of blocks which have memory stores.  */
233 static bitmap modify_mem_list_set;
234
235 /* Bitmap of blocks which have calls.  */
236 static bitmap blocks_with_calls;
237
238 /* Vector indexed by block # with a list of all the insns that
239    modify memory within the block.  */
240 static vec<rtx_insn *> *modify_mem_list;
241
242 /* Vector indexed by block # with a canonicalized list of insns
243    that modify memory in the block.  */
244 static vec<modify_pair> *canon_modify_mem_list;
245
246 /* Vector of simple bitmaps indexed by block number.  Each component sbitmap
247    indicates which expressions are transparent through the block.  */
248 static sbitmap *transp;
249 \f
250
251 /* Helpers for memory allocation/freeing.  */
252 static void alloc_mem (void);
253 static void free_mem (void);
254
255 /* Support for hash table construction and transformations.  */
256 static bool oprs_unchanged_p (rtx, rtx_insn *, bool);
257 static void record_last_reg_set_info (rtx_insn *, rtx);
258 static void record_last_reg_set_info_regno (rtx_insn *, int);
259 static void record_last_mem_set_info (rtx_insn *);
260 static void record_last_set_info (rtx, const_rtx, void *);
261 static void record_opr_changes (rtx_insn *);
262
263 static void find_mem_conflicts (rtx, const_rtx, void *);
264 static int load_killed_in_block_p (int, rtx, bool);
265 static void reset_opr_set_tables (void);
266
267 /* Hash table support.  */
268 static hashval_t hash_expr (rtx, int *);
269 static void insert_expr_in_table (rtx, rtx_insn *);
270 static struct expr *lookup_expr_in_table (rtx);
271 static void dump_hash_table (FILE *);
272
273 /* Helpers for eliminate_partially_redundant_load.  */
274 static bool reg_killed_on_edge (rtx, edge);
275 static bool reg_used_on_edge (rtx, edge);
276
277 static rtx get_avail_load_store_reg (rtx_insn *);
278
279 static bool bb_has_well_behaved_predecessors (basic_block);
280 static struct occr* get_bb_avail_insn (basic_block, struct occr *, int);
281 static void hash_scan_set (rtx_insn *);
282 static void compute_hash_table (void);
283
284 /* The work horses of this pass.  */
285 static void eliminate_partially_redundant_load (basic_block,
286                                                 rtx_insn *,
287                                                 struct expr *);
288 static void eliminate_partially_redundant_loads (void);
289 \f
290
291 /* Allocate memory for the CUID mapping array and register/memory
292    tracking tables.  */
293
294 static void
295 alloc_mem (void)
296 {
297   int i;
298   basic_block bb;
299   rtx_insn *insn;
300
301   /* Find the largest UID and create a mapping from UIDs to CUIDs.  */
302   uid_cuid = XCNEWVEC (int, get_max_uid () + 1);
303   i = 1;
304   FOR_EACH_BB_FN (bb, cfun)
305     FOR_BB_INSNS (bb, insn)
306       {
307         if (INSN_P (insn))
308           uid_cuid[INSN_UID (insn)] = i++;
309         else
310           uid_cuid[INSN_UID (insn)] = i;
311       }
312
313   /* Allocate the available expressions hash table.  We don't want to
314      make the hash table too small, but unnecessarily making it too large
315      also doesn't help.  The i/4 is a gcse.c relic, and seems like a
316      reasonable choice.  */
317   expr_table = new hash_table<expr_hasher> (MAX (i / 4, 13));
318
319   /* We allocate everything on obstacks because we often can roll back
320      the whole obstack to some point.  Freeing obstacks is very fast.  */
321   gcc_obstack_init (&expr_obstack);
322   gcc_obstack_init (&occr_obstack);
323   gcc_obstack_init (&unoccr_obstack);
324   gcc_obstack_init (&modifies_mem_obstack);
325
326   /* Working array used to track the last set for each register
327      in the current block.  */
328   reg_avail_info = (int *) xmalloc (FIRST_PSEUDO_REGISTER * sizeof (int));
329
330   /* Put a dummy modifies_mem object on the modifies_mem_obstack, so we
331      can roll it back in reset_opr_set_tables.  */
332   modifies_mem_obstack_bottom =
333     (struct modifies_mem *) obstack_alloc (&modifies_mem_obstack,
334                                            sizeof (struct modifies_mem));
335
336   blocks_with_calls = BITMAP_ALLOC (NULL);
337   modify_mem_list_set = BITMAP_ALLOC (NULL);
338
339   modify_mem_list = (vec_rtx_heap *) xcalloc (last_basic_block_for_fn (cfun),
340                                               sizeof (vec_rtx_heap));
341   canon_modify_mem_list
342     = (vec_modify_pair_heap *) xcalloc (last_basic_block_for_fn (cfun),
343                                         sizeof (vec_modify_pair_heap));
344 }
345
346 /* Free memory allocated by alloc_mem.  */
347
348 static void
349 free_mem (void)
350 {
351   free (uid_cuid);
352
353   delete expr_table;
354   expr_table = NULL;
355
356   obstack_free (&expr_obstack, NULL);
357   obstack_free (&occr_obstack, NULL);
358   obstack_free (&unoccr_obstack, NULL);
359   obstack_free (&modifies_mem_obstack, NULL);
360
361   unsigned i;
362   bitmap_iterator bi;
363   EXECUTE_IF_SET_IN_BITMAP (modify_mem_list_set, 0, i, bi)
364     {
365       modify_mem_list[i].release ();
366       canon_modify_mem_list[i].release ();
367     }
368
369   BITMAP_FREE (blocks_with_calls);
370   BITMAP_FREE (modify_mem_list_set);
371   free (reg_avail_info);
372 }
373 \f
374
375 /* Insert expression X in INSN in the hash TABLE.
376    If it is already present, record it as the last occurrence in INSN's
377    basic block.  */
378
379 static void
380 insert_expr_in_table (rtx x, rtx_insn *insn)
381 {
382   int do_not_record_p;
383   hashval_t hash;
384   struct expr *cur_expr, **slot;
385   struct occr *avail_occr, *last_occr = NULL;
386
387   hash = hash_expr (x, &do_not_record_p);
388
389   /* Do not insert expression in the table if it contains volatile operands,
390      or if hash_expr determines the expression is something we don't want
391      to or can't handle.  */
392   if (do_not_record_p)
393     return;
394
395   /* We anticipate that redundant expressions are rare, so for convenience
396      allocate a new hash table element here already and set its fields.
397      If we don't do this, we need a hack with a static struct expr.  Anyway,
398      obstack_free is really fast and one more obstack_alloc doesn't hurt if
399      we're going to see more expressions later on.  */
400   cur_expr = (struct expr *) obstack_alloc (&expr_obstack,
401                                             sizeof (struct expr));
402   cur_expr->expr = x;
403   cur_expr->hash = hash;
404   cur_expr->avail_occr = NULL;
405
406   slot = expr_table->find_slot_with_hash (cur_expr, hash, INSERT);
407
408   if (! (*slot))
409     {
410       /* The expression isn't found, so insert it.  */
411       *slot = cur_expr;
412
413       /* Anytime we add an entry to the table, record the index
414          of the new entry.  The bitmap index starts counting
415          at zero.  */
416       cur_expr->bitmap_index = expr_table->elements () - 1;
417     }
418   else
419     {
420       /* The expression is already in the table, so roll back the
421          obstack and use the existing table entry.  */
422       obstack_free (&expr_obstack, cur_expr);
423       cur_expr = *slot;
424     }
425
426   /* Search for another occurrence in the same basic block.  */
427   avail_occr = cur_expr->avail_occr;
428   while (avail_occr
429          && BLOCK_FOR_INSN (avail_occr->insn) != BLOCK_FOR_INSN (insn))
430     {
431       /* If an occurrence isn't found, save a pointer to the end of
432          the list.  */
433       last_occr = avail_occr;
434       avail_occr = avail_occr->next;
435     }
436
437   if (avail_occr)
438     /* Found another instance of the expression in the same basic block.
439        Prefer this occurrence to the currently recorded one.  We want
440        the last one in the block and the block is scanned from start
441        to end.  */
442     avail_occr->insn = insn;
443   else
444     {
445       /* First occurrence of this expression in this basic block.  */
446       avail_occr = (struct occr *) obstack_alloc (&occr_obstack,
447                                                   sizeof (struct occr));
448
449       /* First occurrence of this expression in any block?  */
450       if (cur_expr->avail_occr == NULL)
451         cur_expr->avail_occr = avail_occr;
452       else
453         last_occr->next = avail_occr;
454
455       avail_occr->insn = insn;
456       avail_occr->next = NULL;
457       avail_occr->deleted_p = 0;
458     }
459 }
460 \f
461
462 /* Lookup pattern PAT in the expression hash table.
463    The result is a pointer to the table entry, or NULL if not found.  */
464
465 static struct expr *
466 lookup_expr_in_table (rtx pat)
467 {
468   int do_not_record_p;
469   struct expr **slot, *tmp_expr;
470   hashval_t hash = hash_expr (pat, &do_not_record_p);
471
472   if (do_not_record_p)
473     return NULL;
474
475   tmp_expr = (struct expr *) obstack_alloc (&expr_obstack,
476                                             sizeof (struct expr));
477   tmp_expr->expr = pat;
478   tmp_expr->hash = hash;
479   tmp_expr->avail_occr = NULL;
480
481   slot = expr_table->find_slot_with_hash (tmp_expr, hash, INSERT);
482   obstack_free (&expr_obstack, tmp_expr);
483
484   if (!slot)
485     return NULL;
486   else
487     return (*slot);
488 }
489 \f
490
491 /* Dump all expressions and occurrences that are currently in the
492    expression hash table to FILE.  */
493
494 /* This helper is called via htab_traverse.  */
495 int
496 dump_expr_hash_table_entry (expr **slot, FILE *file)
497 {
498   struct expr *exprs = *slot;
499   struct occr *occr;
500
501   fprintf (file, "expr: ");
502   print_rtl (file, exprs->expr);
503   fprintf (file,"\nhashcode: %u\n", exprs->hash);
504   fprintf (file,"list of occurrences:\n");
505   occr = exprs->avail_occr;
506   while (occr)
507     {
508       rtx_insn *insn = occr->insn;
509       print_rtl_single (file, insn);
510       fprintf (file, "\n");
511       occr = occr->next;
512     }
513   fprintf (file, "\n");
514   return 1;
515 }
516
517 static void
518 dump_hash_table (FILE *file)
519 {
520   fprintf (file, "\n\nexpression hash table\n");
521   fprintf (file, "size %ld, %ld elements, %f collision/search ratio\n",
522            (long) expr_table->size (),
523            (long) expr_table->elements (),
524            expr_table->collisions ());
525   if (expr_table->elements () > 0)
526     {
527       fprintf (file, "\n\ntable entries:\n");
528       expr_table->traverse <FILE *, dump_expr_hash_table_entry> (file);
529     }
530   fprintf (file, "\n");
531 }
532 \f
533 /* Return true if register X is recorded as being set by an instruction
534    whose CUID is greater than the one given.  */
535
536 static bool
537 reg_changed_after_insn_p (rtx x, int cuid)
538 {
539   unsigned int regno, end_regno;
540
541   regno = REGNO (x);
542   end_regno = END_REGNO (x);
543   do
544     if (reg_avail_info[regno] > cuid)
545       return true;
546   while (++regno < end_regno);
547   return false;
548 }
549
550 /* Return nonzero if the operands of expression X are unchanged
551    1) from the start of INSN's basic block up to but not including INSN
552       if AFTER_INSN is false, or
553    2) from INSN to the end of INSN's basic block if AFTER_INSN is true.  */
554
555 static bool
556 oprs_unchanged_p (rtx x, rtx_insn *insn, bool after_insn)
557 {
558   int i, j;
559   enum rtx_code code;
560   const char *fmt;
561
562   if (x == 0)
563     return 1;
564
565   code = GET_CODE (x);
566   switch (code)
567     {
568     case REG:
569       /* We are called after register allocation.  */
570       gcc_assert (REGNO (x) < FIRST_PSEUDO_REGISTER);
571       if (after_insn)
572         return !reg_changed_after_insn_p (x, INSN_CUID (insn) - 1);
573       else
574         return !reg_changed_after_insn_p (x, 0);
575
576     case MEM:
577       if (load_killed_in_block_p (INSN_CUID (insn), x, after_insn))
578         return 0;
579       else
580         return oprs_unchanged_p (XEXP (x, 0), insn, after_insn);
581
582     case PC:
583     case CC0: /*FIXME*/
584     case CONST:
585     CASE_CONST_ANY:
586     case SYMBOL_REF:
587     case LABEL_REF:
588     case ADDR_VEC:
589     case ADDR_DIFF_VEC:
590       return 1;
591
592     case PRE_DEC:
593     case PRE_INC:
594     case POST_DEC:
595     case POST_INC:
596     case PRE_MODIFY:
597     case POST_MODIFY:
598       if (after_insn)
599         return 0;
600       break;
601
602     default:
603       break;
604     }
605
606   for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
607     {
608       if (fmt[i] == 'e')
609         {
610           if (! oprs_unchanged_p (XEXP (x, i), insn, after_insn))
611             return 0;
612         }
613       else if (fmt[i] == 'E')
614         for (j = 0; j < XVECLEN (x, i); j++)
615           if (! oprs_unchanged_p (XVECEXP (x, i, j), insn, after_insn))
616             return 0;
617     }
618
619   return 1;
620 }
621 \f
622
623 /* Used for communication between find_mem_conflicts and
624    load_killed_in_block_p.  Nonzero if find_mem_conflicts finds a
625    conflict between two memory references.
626    This is a bit of a hack to work around the limitations of note_stores.  */
627 static int mems_conflict_p;
628
629 /* DEST is the output of an instruction.  If it is a memory reference, and
630    possibly conflicts with the load found in DATA, then set mems_conflict_p
631    to a nonzero value.  */
632
633 static void
634 find_mem_conflicts (rtx dest, const_rtx setter ATTRIBUTE_UNUSED,
635                     void *data)
636 {
637   rtx mem_op = (rtx) data;
638
639   while (GET_CODE (dest) == SUBREG
640          || GET_CODE (dest) == ZERO_EXTRACT
641          || GET_CODE (dest) == STRICT_LOW_PART)
642     dest = XEXP (dest, 0);
643
644   /* If DEST is not a MEM, then it will not conflict with the load.  Note
645      that function calls are assumed to clobber memory, but are handled
646      elsewhere.  */
647   if (! MEM_P (dest))
648     return;
649
650   if (true_dependence (dest, GET_MODE (dest), mem_op))
651     mems_conflict_p = 1;
652 }
653 \f
654
655 /* Return nonzero if the expression in X (a memory reference) is killed
656    in the current basic block before (if AFTER_INSN is false) or after
657    (if AFTER_INSN is true) the insn with the CUID in UID_LIMIT.
658
659    This function assumes that the modifies_mem table is flushed when
660    the hash table construction or redundancy elimination phases start
661    processing a new basic block.  */
662
663 static int
664 load_killed_in_block_p (int uid_limit, rtx x, bool after_insn)
665 {
666   struct modifies_mem *list_entry = modifies_mem_list;
667
668   while (list_entry)
669     {
670       rtx_insn *setter = list_entry->insn;
671
672       /* Ignore entries in the list that do not apply.  */
673       if ((after_insn
674            && INSN_CUID (setter) < uid_limit)
675           || (! after_insn
676               && INSN_CUID (setter) > uid_limit))
677         {
678           list_entry = list_entry->next;
679           continue;
680         }
681
682       /* If SETTER is a call everything is clobbered.  Note that calls
683          to pure functions are never put on the list, so we need not
684          worry about them.  */
685       if (CALL_P (setter))
686         return 1;
687
688       /* SETTER must be an insn of some kind that sets memory.  Call
689          note_stores to examine each hunk of memory that is modified.
690          It will set mems_conflict_p to nonzero if there may be a
691          conflict between X and SETTER.  */
692       mems_conflict_p = 0;
693       note_stores (PATTERN (setter), find_mem_conflicts, x);
694       if (mems_conflict_p)
695         return 1;
696
697       list_entry = list_entry->next;
698     }
699   return 0;
700 }
701 \f
702
703 /* Record register first/last/block set information for REGNO in INSN.  */
704
705 static inline void
706 record_last_reg_set_info (rtx_insn *insn, rtx reg)
707 {
708   unsigned int regno, end_regno;
709
710   regno = REGNO (reg);
711   end_regno = END_REGNO (reg);
712   do
713     reg_avail_info[regno] = INSN_CUID (insn);
714   while (++regno < end_regno);
715 }
716
717 static inline void
718 record_last_reg_set_info_regno (rtx_insn *insn, int regno)
719 {
720   reg_avail_info[regno] = INSN_CUID (insn);
721 }
722
723
724 /* Record memory modification information for INSN.  We do not actually care
725    about the memory location(s) that are set, or even how they are set (consider
726    a CALL_INSN).  We merely need to record which insns modify memory.  */
727
728 static void
729 record_last_mem_set_info (rtx_insn *insn)
730 {
731   struct modifies_mem *list_entry;
732
733   list_entry = (struct modifies_mem *) obstack_alloc (&modifies_mem_obstack,
734                                                       sizeof (struct modifies_mem));
735   list_entry->insn = insn;
736   list_entry->next = modifies_mem_list;
737   modifies_mem_list = list_entry;
738
739   record_last_mem_set_info_common (insn, modify_mem_list,
740                                    canon_modify_mem_list,
741                                    modify_mem_list_set,
742                                    blocks_with_calls);
743 }
744
745 /* Called from compute_hash_table via note_stores to handle one
746    SET or CLOBBER in an insn.  DATA is really the instruction in which
747    the SET is taking place.  */
748
749 static void
750 record_last_set_info (rtx dest, const_rtx setter ATTRIBUTE_UNUSED, void *data)
751 {
752   rtx_insn *last_set_insn = (rtx_insn *) data;
753
754   if (GET_CODE (dest) == SUBREG)
755     dest = SUBREG_REG (dest);
756
757   if (REG_P (dest))
758     record_last_reg_set_info (last_set_insn, dest);
759   else if (MEM_P (dest))
760     {
761       /* Ignore pushes, they don't clobber memory.  They may still
762          clobber the stack pointer though.  Some targets do argument
763          pushes without adding REG_INC notes.  See e.g. PR25196,
764          where a pushsi2 on i386 doesn't have REG_INC notes.  Note
765          such changes here too.  */
766       if (! push_operand (dest, GET_MODE (dest)))
767         record_last_mem_set_info (last_set_insn);
768       else
769         record_last_reg_set_info_regno (last_set_insn, STACK_POINTER_REGNUM);
770     }
771 }
772
773
774 /* Reset tables used to keep track of what's still available since the
775    start of the block.  */
776
777 static void
778 reset_opr_set_tables (void)
779 {
780   memset (reg_avail_info, 0, FIRST_PSEUDO_REGISTER * sizeof (int));
781   obstack_free (&modifies_mem_obstack, modifies_mem_obstack_bottom);
782   modifies_mem_list = NULL;
783 }
784 \f
785
786 /* Record things set by INSN.
787    This data is used by oprs_unchanged_p.  */
788
789 static void
790 record_opr_changes (rtx_insn *insn)
791 {
792   rtx note;
793
794   /* Find all stores and record them.  */
795   note_stores (PATTERN (insn), record_last_set_info, insn);
796
797   /* Also record autoincremented REGs for this insn as changed.  */
798   for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
799     if (REG_NOTE_KIND (note) == REG_INC)
800       record_last_reg_set_info (insn, XEXP (note, 0));
801
802   /* Finally, if this is a call, record all call clobbers.  */
803   if (CALL_P (insn))
804     {
805       unsigned int regno;
806       rtx link, x;
807       hard_reg_set_iterator hrsi;
808       EXECUTE_IF_SET_IN_HARD_REG_SET (regs_invalidated_by_call, 0, regno, hrsi)
809         record_last_reg_set_info_regno (insn, regno);
810
811       for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
812         if (GET_CODE (XEXP (link, 0)) == CLOBBER)
813           {
814             x = XEXP (XEXP (link, 0), 0);
815             if (REG_P (x))
816               {
817                 gcc_assert (HARD_REGISTER_P (x));
818                 record_last_reg_set_info (insn, x);
819               }
820           }
821
822       if (! RTL_CONST_OR_PURE_CALL_P (insn))
823         record_last_mem_set_info (insn);
824     }
825 }
826 \f
827
828 /* Scan the pattern of INSN and add an entry to the hash TABLE.
829    After reload we are interested in loads/stores only.  */
830
831 static void
832 hash_scan_set (rtx_insn *insn)
833 {
834   rtx pat = PATTERN (insn);
835   rtx src = SET_SRC (pat);
836   rtx dest = SET_DEST (pat);
837
838   /* We are only interested in loads and stores.  */
839   if (! MEM_P (src) && ! MEM_P (dest))
840     return;
841
842   /* Don't mess with jumps and nops.  */
843   if (JUMP_P (insn) || set_noop_p (pat))
844     return;
845
846   if (REG_P (dest))
847     {
848       if (/* Don't CSE something if we can't do a reg/reg copy.  */
849           can_copy_p (GET_MODE (dest))
850           /* Is SET_SRC something we want to gcse?  */
851           && general_operand (src, GET_MODE (src))
852 #ifdef STACK_REGS
853           /* Never consider insns touching the register stack.  It may
854              create situations that reg-stack cannot handle (e.g. a stack
855              register live across an abnormal edge).  */
856           && (REGNO (dest) < FIRST_STACK_REG || REGNO (dest) > LAST_STACK_REG)
857 #endif
858           /* An expression is not available if its operands are
859              subsequently modified, including this insn.  */
860           && oprs_unchanged_p (src, insn, true))
861         {
862           insert_expr_in_table (src, insn);
863         }
864     }
865   else if (REG_P (src))
866     {
867       /* Only record sets of pseudo-regs in the hash table.  */
868       if (/* Don't CSE something if we can't do a reg/reg copy.  */
869           can_copy_p (GET_MODE (src))
870           /* Is SET_DEST something we want to gcse?  */
871           && general_operand (dest, GET_MODE (dest))
872 #ifdef STACK_REGS
873           /* As above for STACK_REGS.  */
874           && (REGNO (src) < FIRST_STACK_REG || REGNO (src) > LAST_STACK_REG)
875 #endif
876           && ! (flag_float_store && FLOAT_MODE_P (GET_MODE (dest)))
877           /* Check if the memory expression is killed after insn.  */
878           && ! load_killed_in_block_p (INSN_CUID (insn) + 1, dest, true)
879           && oprs_unchanged_p (XEXP (dest, 0), insn, true))
880         {
881           insert_expr_in_table (dest, insn);
882         }
883     }
884 }
885 \f
886
887 /* Create hash table of memory expressions available at end of basic
888    blocks.  Basically you should think of this hash table as the
889    representation of AVAIL_OUT.  This is the set of expressions that
890    is generated in a basic block and not killed before the end of the
891    same basic block.  Notice that this is really a local computation.  */
892
893 static void
894 compute_hash_table (void)
895 {
896   basic_block bb;
897
898   FOR_EACH_BB_FN (bb, cfun)
899     {
900       rtx_insn *insn;
901
902       /* First pass over the instructions records information used to
903          determine when registers and memory are last set.
904          Since we compute a "local" AVAIL_OUT, reset the tables that
905          help us keep track of what has been modified since the start
906          of the block.  */
907       reset_opr_set_tables ();
908       FOR_BB_INSNS (bb, insn)
909         {
910           if (INSN_P (insn))
911             record_opr_changes (insn);
912         }
913
914       /* The next pass actually builds the hash table.  */
915       FOR_BB_INSNS (bb, insn)
916         if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == SET)
917           hash_scan_set (insn);
918     }
919 }
920 \f
921
922 /* Check if register REG is killed in any insn waiting to be inserted on
923    edge E.  This function is required to check that our data flow analysis
924    is still valid prior to commit_edge_insertions.  */
925
926 static bool
927 reg_killed_on_edge (rtx reg, edge e)
928 {
929   rtx_insn *insn;
930
931   for (insn = e->insns.r; insn; insn = NEXT_INSN (insn))
932     if (INSN_P (insn) && reg_set_p (reg, insn))
933       return true;
934
935   return false;
936 }
937
938 /* Similar to above - check if register REG is used in any insn waiting
939    to be inserted on edge E.
940    Assumes no such insn can be a CALL_INSN; if so call reg_used_between_p
941    with PREV(insn),NEXT(insn) instead of calling reg_overlap_mentioned_p.  */
942
943 static bool
944 reg_used_on_edge (rtx reg, edge e)
945 {
946   rtx_insn *insn;
947
948   for (insn = e->insns.r; insn; insn = NEXT_INSN (insn))
949     if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn)))
950       return true;
951
952   return false;
953 }
954 \f
955 /* Return the loaded/stored register of a load/store instruction.  */
956
957 static rtx
958 get_avail_load_store_reg (rtx_insn *insn)
959 {
960   if (REG_P (SET_DEST (PATTERN (insn))))
961     /* A load.  */
962     return SET_DEST (PATTERN (insn));
963   else
964     {
965       /* A store.  */
966       gcc_assert (REG_P (SET_SRC (PATTERN (insn))));
967       return SET_SRC (PATTERN (insn));
968     }
969 }
970
971 /* Return nonzero if the predecessors of BB are "well behaved".  */
972
973 static bool
974 bb_has_well_behaved_predecessors (basic_block bb)
975 {
976   edge pred;
977   edge_iterator ei;
978
979   if (EDGE_COUNT (bb->preds) == 0)
980     return false;
981
982   FOR_EACH_EDGE (pred, ei, bb->preds)
983     {
984       if ((pred->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (pred))
985         return false;
986
987       if ((pred->flags & EDGE_ABNORMAL_CALL) && cfun->has_nonlocal_label)
988         return false;
989
990       if (tablejump_p (BB_END (pred->src), NULL, NULL))
991         return false;
992     }
993   return true;
994 }
995
996
997 /* Search for the occurrences of expression in BB.  */
998
999 static struct occr*
1000 get_bb_avail_insn (basic_block bb, struct occr *orig_occr, int bitmap_index)
1001 {
1002   struct occr *occr = orig_occr;
1003
1004   for (; occr != NULL; occr = occr->next)
1005     if (BLOCK_FOR_INSN (occr->insn) == bb)
1006       return occr;
1007
1008   /* If we could not find an occurrence in BB, see if BB
1009      has a single predecessor with an occurrence that is
1010      transparent through BB.  */
1011   if (single_pred_p (bb)
1012       && bitmap_bit_p (transp[bb->index], bitmap_index)
1013       && (occr = get_bb_avail_insn (single_pred (bb), orig_occr, bitmap_index)))
1014     {
1015       rtx avail_reg = get_avail_load_store_reg (occr->insn);
1016       if (!reg_set_between_p (avail_reg,
1017                               PREV_INSN (BB_HEAD (bb)),
1018                               NEXT_INSN (BB_END (bb)))
1019           && !reg_killed_on_edge (avail_reg, single_pred_edge (bb)))
1020         return occr;
1021     }
1022
1023   return NULL;
1024 }
1025
1026
1027 /* This helper is called via htab_traverse.  */
1028 int
1029 compute_expr_transp (expr **slot, FILE *dump_file ATTRIBUTE_UNUSED)
1030 {
1031   struct expr *expr = *slot;
1032
1033   compute_transp (expr->expr, expr->bitmap_index, transp,
1034                   blocks_with_calls, modify_mem_list_set,
1035                   canon_modify_mem_list);
1036   return 1;
1037 }
1038
1039 /* This handles the case where several stores feed a partially redundant
1040    load. It checks if the redundancy elimination is possible and if it's
1041    worth it.
1042
1043    Redundancy elimination is possible if,
1044    1) None of the operands of an insn have been modified since the start
1045       of the current basic block.
1046    2) In any predecessor of the current basic block, the same expression
1047       is generated.
1048
1049    See the function body for the heuristics that determine if eliminating
1050    a redundancy is also worth doing, assuming it is possible.  */
1051
1052 static void
1053 eliminate_partially_redundant_load (basic_block bb, rtx_insn *insn,
1054                                     struct expr *expr)
1055 {
1056   edge pred;
1057   rtx_insn *avail_insn = NULL;
1058   rtx avail_reg;
1059   rtx dest, pat;
1060   struct occr *a_occr;
1061   struct unoccr *occr, *avail_occrs = NULL;
1062   struct unoccr *unoccr, *unavail_occrs = NULL, *rollback_unoccr = NULL;
1063   int npred_ok = 0;
1064   gcov_type ok_count = 0; /* Redundant load execution count.  */
1065   gcov_type critical_count = 0; /* Execution count of critical edges.  */
1066   edge_iterator ei;
1067   bool critical_edge_split = false;
1068
1069   /* The execution count of the loads to be added to make the
1070      load fully redundant.  */
1071   gcov_type not_ok_count = 0;
1072   basic_block pred_bb;
1073
1074   pat = PATTERN (insn);
1075   dest = SET_DEST (pat);
1076
1077   /* Check that the loaded register is not used, set, or killed from the
1078      beginning of the block.  */
1079   if (reg_changed_after_insn_p (dest, 0)
1080       || reg_used_between_p (dest, PREV_INSN (BB_HEAD (bb)), insn))
1081     return;
1082
1083   /* Check potential for replacing load with copy for predecessors.  */
1084   FOR_EACH_EDGE (pred, ei, bb->preds)
1085     {
1086       rtx_insn *next_pred_bb_end;
1087
1088       avail_insn = NULL;
1089       avail_reg = NULL_RTX;
1090       pred_bb = pred->src;
1091       for (a_occr = get_bb_avail_insn (pred_bb,
1092                                        expr->avail_occr,
1093                                        expr->bitmap_index);
1094            a_occr;
1095            a_occr = get_bb_avail_insn (pred_bb,
1096                                        a_occr->next,
1097                                        expr->bitmap_index))
1098         {
1099           /* Check if the loaded register is not used.  */
1100           avail_insn = a_occr->insn;
1101           avail_reg = get_avail_load_store_reg (avail_insn);
1102           gcc_assert (avail_reg);
1103
1104           /* Make sure we can generate a move from register avail_reg to
1105              dest.  */
1106           rtx_insn *move = gen_move_insn (copy_rtx (dest),
1107                                           copy_rtx (avail_reg));
1108           extract_insn (move);
1109           if (! constrain_operands (1, get_preferred_alternatives (insn,
1110                                                                    pred_bb))
1111               || reg_killed_on_edge (avail_reg, pred)
1112               || reg_used_on_edge (dest, pred))
1113             {
1114               avail_insn = NULL;
1115               continue;
1116             }
1117           next_pred_bb_end = NEXT_INSN (BB_END (BLOCK_FOR_INSN (avail_insn)));
1118           if (!reg_set_between_p (avail_reg, avail_insn, next_pred_bb_end))
1119             /* AVAIL_INSN remains non-null.  */
1120             break;
1121           else
1122             avail_insn = NULL;
1123         }
1124
1125       if (EDGE_CRITICAL_P (pred))
1126         critical_count += pred->count;
1127
1128       if (avail_insn != NULL_RTX)
1129         {
1130           npred_ok++;
1131           ok_count += pred->count;
1132           if (! set_noop_p (PATTERN (gen_move_insn (copy_rtx (dest),
1133                                                     copy_rtx (avail_reg)))))
1134             {
1135               /* Check if there is going to be a split.  */
1136               if (EDGE_CRITICAL_P (pred))
1137                 critical_edge_split = true;
1138             }
1139           else /* Its a dead move no need to generate.  */
1140             continue;
1141           occr = (struct unoccr *) obstack_alloc (&unoccr_obstack,
1142                                                   sizeof (struct unoccr));
1143           occr->insn = avail_insn;
1144           occr->pred = pred;
1145           occr->next = avail_occrs;
1146           avail_occrs = occr;
1147           if (! rollback_unoccr)
1148             rollback_unoccr = occr;
1149         }
1150       else
1151         {
1152           /* Adding a load on a critical edge will cause a split.  */
1153           if (EDGE_CRITICAL_P (pred))
1154             critical_edge_split = true;
1155           not_ok_count += pred->count;
1156           unoccr = (struct unoccr *) obstack_alloc (&unoccr_obstack,
1157                                                     sizeof (struct unoccr));
1158           unoccr->insn = NULL;
1159           unoccr->pred = pred;
1160           unoccr->next = unavail_occrs;
1161           unavail_occrs = unoccr;
1162           if (! rollback_unoccr)
1163             rollback_unoccr = unoccr;
1164         }
1165     }
1166
1167   if (/* No load can be replaced by copy.  */
1168       npred_ok == 0
1169       /* Prevent exploding the code.  */
1170       || (optimize_bb_for_size_p (bb) && npred_ok > 1)
1171       /* If we don't have profile information we cannot tell if splitting
1172          a critical edge is profitable or not so don't do it.  */
1173       || ((! profile_info || ! flag_branch_probabilities
1174            || targetm.cannot_modify_jumps_p ())
1175           && critical_edge_split))
1176     goto cleanup;
1177
1178   /* Check if it's worth applying the partial redundancy elimination.  */
1179   if (ok_count < GCSE_AFTER_RELOAD_PARTIAL_FRACTION * not_ok_count)
1180     goto cleanup;
1181   if (ok_count < GCSE_AFTER_RELOAD_CRITICAL_FRACTION * critical_count)
1182     goto cleanup;
1183
1184   /* Generate moves to the loaded register from where
1185      the memory is available.  */
1186   for (occr = avail_occrs; occr; occr = occr->next)
1187     {
1188       avail_insn = occr->insn;
1189       pred = occr->pred;
1190       /* Set avail_reg to be the register having the value of the
1191          memory.  */
1192       avail_reg = get_avail_load_store_reg (avail_insn);
1193       gcc_assert (avail_reg);
1194
1195       insert_insn_on_edge (gen_move_insn (copy_rtx (dest),
1196                                           copy_rtx (avail_reg)),
1197                            pred);
1198       stats.moves_inserted++;
1199
1200       if (dump_file)
1201         fprintf (dump_file,
1202                  "generating move from %d to %d on edge from %d to %d\n",
1203                  REGNO (avail_reg),
1204                  REGNO (dest),
1205                  pred->src->index,
1206                  pred->dest->index);
1207     }
1208
1209   /* Regenerate loads where the memory is unavailable.  */
1210   for (unoccr = unavail_occrs; unoccr; unoccr = unoccr->next)
1211     {
1212       pred = unoccr->pred;
1213       insert_insn_on_edge (copy_insn (PATTERN (insn)), pred);
1214       stats.copies_inserted++;
1215
1216       if (dump_file)
1217         {
1218           fprintf (dump_file,
1219                    "generating on edge from %d to %d a copy of load: ",
1220                    pred->src->index,
1221                    pred->dest->index);
1222           print_rtl (dump_file, PATTERN (insn));
1223           fprintf (dump_file, "\n");
1224         }
1225     }
1226
1227   /* Delete the insn if it is not available in this block and mark it
1228      for deletion if it is available. If insn is available it may help
1229      discover additional redundancies, so mark it for later deletion.  */
1230   for (a_occr = get_bb_avail_insn (bb, expr->avail_occr, expr->bitmap_index);
1231        a_occr && (a_occr->insn != insn);
1232        a_occr = get_bb_avail_insn (bb, a_occr->next, expr->bitmap_index))
1233     ;
1234
1235   if (!a_occr)
1236     {
1237       stats.insns_deleted++;
1238
1239       if (dump_file)
1240         {
1241           fprintf (dump_file, "deleting insn:\n");
1242           print_rtl_single (dump_file, insn);
1243           fprintf (dump_file, "\n");
1244         }
1245       delete_insn (insn);
1246     }
1247   else
1248     a_occr->deleted_p = 1;
1249
1250 cleanup:
1251   if (rollback_unoccr)
1252     obstack_free (&unoccr_obstack, rollback_unoccr);
1253 }
1254
1255 /* Performing the redundancy elimination as described before.  */
1256
1257 static void
1258 eliminate_partially_redundant_loads (void)
1259 {
1260   rtx_insn *insn;
1261   basic_block bb;
1262
1263   /* Note we start at block 1.  */
1264
1265   if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
1266     return;
1267
1268   FOR_BB_BETWEEN (bb,
1269                   ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->next_bb,
1270                   EXIT_BLOCK_PTR_FOR_FN (cfun),
1271                   next_bb)
1272     {
1273       /* Don't try anything on basic blocks with strange predecessors.  */
1274       if (! bb_has_well_behaved_predecessors (bb))
1275         continue;
1276
1277       /* Do not try anything on cold basic blocks.  */
1278       if (optimize_bb_for_size_p (bb))
1279         continue;
1280
1281       /* Reset the table of things changed since the start of the current
1282          basic block.  */
1283       reset_opr_set_tables ();
1284
1285       /* Look at all insns in the current basic block and see if there are
1286          any loads in it that we can record.  */
1287       FOR_BB_INSNS (bb, insn)
1288         {
1289           /* Is it a load - of the form (set (reg) (mem))?  */
1290           if (NONJUMP_INSN_P (insn)
1291               && GET_CODE (PATTERN (insn)) == SET
1292               && REG_P (SET_DEST (PATTERN (insn)))
1293               && MEM_P (SET_SRC (PATTERN (insn))))
1294             {
1295               rtx pat = PATTERN (insn);
1296               rtx src = SET_SRC (pat);
1297               struct expr *expr;
1298
1299               if (!MEM_VOLATILE_P (src)
1300                   && GET_MODE (src) != BLKmode
1301                   && general_operand (src, GET_MODE (src))
1302                   /* Are the operands unchanged since the start of the
1303                      block?  */
1304                   && oprs_unchanged_p (src, insn, false)
1305                   && !(cfun->can_throw_non_call_exceptions && may_trap_p (src))
1306                   && !side_effects_p (src)
1307                   /* Is the expression recorded?  */
1308                   && (expr = lookup_expr_in_table (src)) != NULL)
1309                 {
1310                   /* We now have a load (insn) and an available memory at
1311                      its BB start (expr). Try to remove the loads if it is
1312                      redundant.  */
1313                   eliminate_partially_redundant_load (bb, insn, expr);
1314                 }
1315             }
1316
1317           /* Keep track of everything modified by this insn, so that we
1318              know what has been modified since the start of the current
1319              basic block.  */
1320           if (INSN_P (insn))
1321             record_opr_changes (insn);
1322         }
1323     }
1324
1325   commit_edge_insertions ();
1326 }
1327
1328 /* Go over the expression hash table and delete insns that were
1329    marked for later deletion.  */
1330
1331 /* This helper is called via htab_traverse.  */
1332 int
1333 delete_redundant_insns_1 (expr **slot, void *data ATTRIBUTE_UNUSED)
1334 {
1335   struct expr *exprs = *slot;
1336   struct occr *occr;
1337
1338   for (occr = exprs->avail_occr; occr != NULL; occr = occr->next)
1339     {
1340       if (occr->deleted_p && dbg_cnt (gcse2_delete))
1341         {
1342           delete_insn (occr->insn);
1343           stats.insns_deleted++;
1344
1345           if (dump_file)
1346             {
1347               fprintf (dump_file, "deleting insn:\n");
1348               print_rtl_single (dump_file, occr->insn);
1349               fprintf (dump_file, "\n");
1350             }
1351         }
1352     }
1353
1354   return 1;
1355 }
1356
1357 static void
1358 delete_redundant_insns (void)
1359 {
1360   expr_table->traverse <void *, delete_redundant_insns_1> (NULL);
1361   if (dump_file)
1362     fprintf (dump_file, "\n");
1363 }
1364
1365 /* Main entry point of the GCSE after reload - clean some redundant loads
1366    due to spilling.  */
1367
1368 static void
1369 gcse_after_reload_main (rtx f ATTRIBUTE_UNUSED)
1370 {
1371
1372   memset (&stats, 0, sizeof (stats));
1373
1374   /* Allocate memory for this pass.
1375      Also computes and initializes the insns' CUIDs.  */
1376   alloc_mem ();
1377
1378   /* We need alias analysis.  */
1379   init_alias_analysis ();
1380
1381   compute_hash_table ();
1382
1383   if (dump_file)
1384     dump_hash_table (dump_file);
1385
1386   if (expr_table->elements () > 0)
1387     {
1388       /* Knowing which MEMs are transparent through a block can signifiantly
1389          increase the number of redundant loads found.  So compute transparency
1390          information for each memory expression in the hash table.  */
1391       df_analyze ();
1392       /* This can not be part of the normal allocation routine because
1393          we have to know the number of elements in the hash table.  */
1394       transp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
1395                                      expr_table->elements ());
1396       bitmap_vector_ones (transp, last_basic_block_for_fn (cfun));
1397       expr_table->traverse <FILE *, compute_expr_transp> (dump_file);
1398       eliminate_partially_redundant_loads ();
1399       delete_redundant_insns ();
1400       sbitmap_vector_free (transp);
1401
1402       if (dump_file)
1403         {
1404           fprintf (dump_file, "GCSE AFTER RELOAD stats:\n");
1405           fprintf (dump_file, "copies inserted: %d\n", stats.copies_inserted);
1406           fprintf (dump_file, "moves inserted:  %d\n", stats.moves_inserted);
1407           fprintf (dump_file, "insns deleted:   %d\n", stats.insns_deleted);
1408           fprintf (dump_file, "\n\n");
1409         }
1410
1411       statistics_counter_event (cfun, "copies inserted",
1412                                 stats.copies_inserted);
1413       statistics_counter_event (cfun, "moves inserted",
1414                                 stats.moves_inserted);
1415       statistics_counter_event (cfun, "insns deleted",
1416                                 stats.insns_deleted);
1417     }
1418
1419   /* We are finished with alias.  */
1420   end_alias_analysis ();
1421
1422   free_mem ();
1423 }
1424
1425 \f
1426
1427 static unsigned int
1428 rest_of_handle_gcse2 (void)
1429 {
1430   gcse_after_reload_main (get_insns ());
1431   rebuild_jump_labels (get_insns ());
1432   return 0;
1433 }
1434
1435 namespace {
1436
1437 const pass_data pass_data_gcse2 =
1438 {
1439   RTL_PASS, /* type */
1440   "gcse2", /* name */
1441   OPTGROUP_NONE, /* optinfo_flags */
1442   TV_GCSE_AFTER_RELOAD, /* tv_id */
1443   0, /* properties_required */
1444   0, /* properties_provided */
1445   0, /* properties_destroyed */
1446   0, /* todo_flags_start */
1447   0, /* todo_flags_finish */
1448 };
1449
1450 class pass_gcse2 : public rtl_opt_pass
1451 {
1452 public:
1453   pass_gcse2 (gcc::context *ctxt)
1454     : rtl_opt_pass (pass_data_gcse2, ctxt)
1455   {}
1456
1457   /* opt_pass methods: */
1458   virtual bool gate (function *fun)
1459     {
1460       return (optimize > 0 && flag_gcse_after_reload
1461               && optimize_function_for_speed_p (fun));
1462     }
1463
1464   virtual unsigned int execute (function *) { return rest_of_handle_gcse2 (); }
1465
1466 }; // class pass_gcse2
1467
1468 } // anon namespace
1469
1470 rtl_opt_pass *
1471 make_pass_gcse2 (gcc::context *ctxt)
1472 {
1473   return new pass_gcse2 (ctxt);
1474 }