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