OSDN Git Service

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