152284Sobrien/* Global common subexpression elimination/Partial redundancy elimination
250397Sobrien   and global constant/copy propagation for GNU compiler.
3169689Skan   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
490075Sobrien   Free Software Foundation, Inc.
550397Sobrien
690075SobrienThis file is part of GCC.
750397Sobrien
890075SobrienGCC is free software; you can redistribute it and/or modify it under
990075Sobrienthe terms of the GNU General Public License as published by the Free
1090075SobrienSoftware Foundation; either version 2, or (at your option) any later
1190075Sobrienversion.
1250397Sobrien
1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1590075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1690075Sobrienfor more details.
1750397Sobrien
1850397SobrienYou should have received a copy of the GNU General Public License
1990075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169689Skan02110-1301, USA.  */
2250397Sobrien
2350397Sobrien/* TODO
2450397Sobrien   - reordering of memory allocation and freeing to be more space efficient
2550397Sobrien   - do rough calc of how many regs are needed in each block, and a rough
2650397Sobrien     calc of how many regs are available in each class and use that to
2750397Sobrien     throttle back the code in cases where RTX_COST is minimal.
2852284Sobrien   - a store to the same address as a load does not kill the load if the
2952284Sobrien     source of the store is also the destination of the load.  Handling this
3052284Sobrien     allows more load motion, particularly out of loops.
3150397Sobrien   - ability to realloc sbitmap vectors would allow one initial computation
3250397Sobrien     of reg_set_in_block with only subsequent additions, rather than
3350397Sobrien     recomputing it for each pass
3450397Sobrien
3550397Sobrien*/
3650397Sobrien
3750397Sobrien/* References searched while implementing this.
3850397Sobrien
3950397Sobrien   Compilers Principles, Techniques and Tools
4050397Sobrien   Aho, Sethi, Ullman
4150397Sobrien   Addison-Wesley, 1988
4250397Sobrien
4350397Sobrien   Global Optimization by Suppression of Partial Redundancies
4450397Sobrien   E. Morel, C. Renvoise
4550397Sobrien   communications of the acm, Vol. 22, Num. 2, Feb. 1979
4650397Sobrien
4750397Sobrien   A Portable Machine-Independent Global Optimizer - Design and Measurements
4850397Sobrien   Frederick Chow
4950397Sobrien   Stanford Ph.D. thesis, Dec. 1983
5050397Sobrien
5150397Sobrien   A Fast Algorithm for Code Movement Optimization
5250397Sobrien   D.M. Dhamdhere
5350397Sobrien   SIGPLAN Notices, Vol. 23, Num. 10, Oct. 1988
5450397Sobrien
5550397Sobrien   A Solution to a Problem with Morel and Renvoise's
5650397Sobrien   Global Optimization by Suppression of Partial Redundancies
5750397Sobrien   K-H Drechsler, M.P. Stadel
5850397Sobrien   ACM TOPLAS, Vol. 10, Num. 4, Oct. 1988
5950397Sobrien
6050397Sobrien   Practical Adaptation of the Global Optimization
6150397Sobrien   Algorithm of Morel and Renvoise
6250397Sobrien   D.M. Dhamdhere
6350397Sobrien   ACM TOPLAS, Vol. 13, Num. 2. Apr. 1991
6450397Sobrien
6550397Sobrien   Efficiently Computing Static Single Assignment Form and the Control
6650397Sobrien   Dependence Graph
6750397Sobrien   R. Cytron, J. Ferrante, B.K. Rosen, M.N. Wegman, and F.K. Zadeck
6850397Sobrien   ACM TOPLAS, Vol. 13, Num. 4, Oct. 1991
6950397Sobrien
7050397Sobrien   Lazy Code Motion
7150397Sobrien   J. Knoop, O. Ruthing, B. Steffen
7250397Sobrien   ACM SIGPLAN Notices Vol. 27, Num. 7, Jul. 1992, '92 Conference on PLDI
7350397Sobrien
7450397Sobrien   What's In a Region?  Or Computing Control Dependence Regions in Near-Linear
7550397Sobrien   Time for Reducible Flow Control
7650397Sobrien   Thomas Ball
7750397Sobrien   ACM Letters on Programming Languages and Systems,
7850397Sobrien   Vol. 2, Num. 1-4, Mar-Dec 1993
7950397Sobrien
8050397Sobrien   An Efficient Representation for Sparse Sets
8150397Sobrien   Preston Briggs, Linda Torczon
8250397Sobrien   ACM Letters on Programming Languages and Systems,
8350397Sobrien   Vol. 2, Num. 1-4, Mar-Dec 1993
8450397Sobrien
8550397Sobrien   A Variation of Knoop, Ruthing, and Steffen's Lazy Code Motion
8650397Sobrien   K-H Drechsler, M.P. Stadel
8750397Sobrien   ACM SIGPLAN Notices, Vol. 28, Num. 5, May 1993
8850397Sobrien
8950397Sobrien   Partial Dead Code Elimination
9050397Sobrien   J. Knoop, O. Ruthing, B. Steffen
9150397Sobrien   ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994
9250397Sobrien
9350397Sobrien   Effective Partial Redundancy Elimination
9450397Sobrien   P. Briggs, K.D. Cooper
9550397Sobrien   ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994
9650397Sobrien
9750397Sobrien   The Program Structure Tree: Computing Control Regions in Linear Time
9850397Sobrien   R. Johnson, D. Pearson, K. Pingali
9950397Sobrien   ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994
10050397Sobrien
10150397Sobrien   Optimal Code Motion: Theory and Practice
10250397Sobrien   J. Knoop, O. Ruthing, B. Steffen
10350397Sobrien   ACM TOPLAS, Vol. 16, Num. 4, Jul. 1994
10450397Sobrien
10550397Sobrien   The power of assignment motion
10650397Sobrien   J. Knoop, O. Ruthing, B. Steffen
10750397Sobrien   ACM SIGPLAN Notices Vol. 30, Num. 6, Jun. 1995, '95 Conference on PLDI
10850397Sobrien
10950397Sobrien   Global code motion / global value numbering
11050397Sobrien   C. Click
11150397Sobrien   ACM SIGPLAN Notices Vol. 30, Num. 6, Jun. 1995, '95 Conference on PLDI
11250397Sobrien
11350397Sobrien   Value Driven Redundancy Elimination
11450397Sobrien   L.T. Simpson
11550397Sobrien   Rice University Ph.D. thesis, Apr. 1996
11650397Sobrien
11750397Sobrien   Value Numbering
11850397Sobrien   L.T. Simpson
11950397Sobrien   Massively Scalar Compiler Project, Rice University, Sep. 1996
12050397Sobrien
12150397Sobrien   High Performance Compilers for Parallel Computing
12250397Sobrien   Michael Wolfe
12350397Sobrien   Addison-Wesley, 1996
12450397Sobrien
12552284Sobrien   Advanced Compiler Design and Implementation
12652284Sobrien   Steven Muchnick
12752284Sobrien   Morgan Kaufmann, 1997
12852284Sobrien
12990075Sobrien   Building an Optimizing Compiler
13090075Sobrien   Robert Morgan
13190075Sobrien   Digital Press, 1998
13290075Sobrien
13352284Sobrien   People wishing to speed up the code here should read:
13452284Sobrien     Elimination Algorithms for Data Flow Analysis
13552284Sobrien     B.G. Ryder, M.C. Paull
13652284Sobrien     ACM Computing Surveys, Vol. 18, Num. 3, Sep. 1986
13752284Sobrien
13852284Sobrien     How to Analyze Large Programs Efficiently and Informatively
13952284Sobrien     D.M. Dhamdhere, B.K. Rosen, F.K. Zadeck
14052284Sobrien     ACM SIGPLAN Notices Vol. 27, Num. 7, Jul. 1992, '92 Conference on PLDI
14152284Sobrien
14250397Sobrien   People wishing to do something different can find various possibilities
14350397Sobrien   in the above papers and elsewhere.
14450397Sobrien*/
14550397Sobrien
14650397Sobrien#include "config.h"
14750397Sobrien#include "system.h"
148132718Skan#include "coretypes.h"
149132718Skan#include "tm.h"
15052284Sobrien#include "toplev.h"
15150397Sobrien
15250397Sobrien#include "rtl.h"
153132718Skan#include "tree.h"
15490075Sobrien#include "tm_p.h"
15550397Sobrien#include "regs.h"
15650397Sobrien#include "hard-reg-set.h"
15750397Sobrien#include "flags.h"
15850397Sobrien#include "real.h"
15950397Sobrien#include "insn-config.h"
16050397Sobrien#include "recog.h"
16150397Sobrien#include "basic-block.h"
16250397Sobrien#include "output.h"
16390075Sobrien#include "function.h"
164117395Skan#include "expr.h"
16596263Sobrien#include "except.h"
16690075Sobrien#include "ggc.h"
16790075Sobrien#include "params.h"
168117395Skan#include "cselib.h"
169132718Skan#include "intl.h"
17050397Sobrien#include "obstack.h"
171169689Skan#include "timevar.h"
172169689Skan#include "tree-pass.h"
173169689Skan#include "hashtab.h"
17450397Sobrien
17550397Sobrien/* Propagate flow information through back edges and thus enable PRE's
17650397Sobrien   moving loop invariant calculations out of loops.
17750397Sobrien
17850397Sobrien   Originally this tended to create worse overall code, but several
17950397Sobrien   improvements during the development of PRE seem to have made following
18050397Sobrien   back edges generally a win.
18150397Sobrien
18250397Sobrien   Note much of the loop invariant code motion done here would normally
18350397Sobrien   be done by loop.c, which has more heuristics for when to move invariants
18450397Sobrien   out of loops.  At some point we might need to move some of those
18550397Sobrien   heuristics into gcse.c.  */
18650397Sobrien
18752284Sobrien/* We support GCSE via Partial Redundancy Elimination.  PRE optimizations
18852284Sobrien   are a superset of those done by GCSE.
18950397Sobrien
19052284Sobrien   We perform the following steps:
19150397Sobrien
19250397Sobrien   1) Compute basic block information.
19350397Sobrien
19450397Sobrien   2) Compute table of places where registers are set.
19550397Sobrien
19650397Sobrien   3) Perform copy/constant propagation.
19750397Sobrien
198169689Skan   4) Perform global cse using lazy code motion if not optimizing
199169689Skan      for size, or code hoisting if we are.
20050397Sobrien
20152284Sobrien   5) Perform another pass of copy/constant propagation.
20250397Sobrien
20350397Sobrien   Two passes of copy/constant propagation are done because the first one
20450397Sobrien   enables more GCSE and the second one helps to clean up the copies that
20550397Sobrien   GCSE creates.  This is needed more for PRE than for Classic because Classic
20650397Sobrien   GCSE will try to use an existing register containing the common
20750397Sobrien   subexpression rather than create a new one.  This is harder to do for PRE
20850397Sobrien   because of the code motion (which Classic GCSE doesn't do).
20950397Sobrien
21050397Sobrien   Expressions we are interested in GCSE-ing are of the form
21150397Sobrien   (set (pseudo-reg) (expression)).
21250397Sobrien   Function want_to_gcse_p says what these are.
21350397Sobrien
21450397Sobrien   PRE handles moving invariant expressions out of loops (by treating them as
21552284Sobrien   partially redundant).
21650397Sobrien
21750397Sobrien   Eventually it would be nice to replace cse.c/gcse.c with SSA (static single
21850397Sobrien   assignment) based GVN (global value numbering).  L. T. Simpson's paper
21950397Sobrien   (Rice University) on value numbering is a useful reference for this.
22050397Sobrien
22150397Sobrien   **********************
22250397Sobrien
22350397Sobrien   We used to support multiple passes but there are diminishing returns in
22450397Sobrien   doing so.  The first pass usually makes 90% of the changes that are doable.
22550397Sobrien   A second pass can make a few more changes made possible by the first pass.
22650397Sobrien   Experiments show any further passes don't make enough changes to justify
22750397Sobrien   the expense.
22850397Sobrien
22950397Sobrien   A study of spec92 using an unlimited number of passes:
23050397Sobrien   [1 pass] = 1208 substitutions, [2] = 577, [3] = 202, [4] = 192, [5] = 83,
23150397Sobrien   [6] = 34, [7] = 17, [8] = 9, [9] = 4, [10] = 4, [11] = 2,
23250397Sobrien   [12] = 2, [13] = 1, [15] = 1, [16] = 2, [41] = 1
23350397Sobrien
23450397Sobrien   It was found doing copy propagation between each pass enables further
23550397Sobrien   substitutions.
23650397Sobrien
23750397Sobrien   PRE is quite expensive in complicated functions because the DFA can take
238169689Skan   a while to converge.  Hence we only perform one pass.  The parameter
239169689Skan   max-gcse-passes can be modified if one wants to experiment.
24050397Sobrien
24150397Sobrien   **********************
24250397Sobrien
24350397Sobrien   The steps for PRE are:
24450397Sobrien
24550397Sobrien   1) Build the hash table of expressions we wish to GCSE (expr_hash_table).
24650397Sobrien
24750397Sobrien   2) Perform the data flow analysis for PRE.
24850397Sobrien
24950397Sobrien   3) Delete the redundant instructions
25050397Sobrien
25150397Sobrien   4) Insert the required copies [if any] that make the partially
25250397Sobrien      redundant instructions fully redundant.
25350397Sobrien
25450397Sobrien   5) For other reaching expressions, insert an instruction to copy the value
25550397Sobrien      to a newly created pseudo that will reach the redundant instruction.
25650397Sobrien
25750397Sobrien   The deletion is done first so that when we do insertions we
25850397Sobrien   know which pseudo reg to use.
25950397Sobrien
26050397Sobrien   Various papers have argued that PRE DFA is expensive (O(n^2)) and others
26150397Sobrien   argue it is not.  The number of iterations for the algorithm to converge
26250397Sobrien   is typically 2-4 so I don't view it as that expensive (relatively speaking).
26350397Sobrien
26452284Sobrien   PRE GCSE depends heavily on the second CSE pass to clean up the copies
26550397Sobrien   we create.  To make an expression reach the place where it's redundant,
26650397Sobrien   the result of the expression is copied to a new register, and the redundant
26750397Sobrien   expression is deleted by replacing it with this new register.  Classic GCSE
26850397Sobrien   doesn't have this problem as much as it computes the reaching defs of
269169689Skan   each register in each block and thus can try to use an existing
270169689Skan   register.  */
27150397Sobrien
27250397Sobrien/* GCSE global vars.  */
27350397Sobrien
27452284Sobrien/* Note whether or not we should run jump optimization after gcse.  We
27552284Sobrien   want to do this for two cases.
27652284Sobrien
27752284Sobrien    * If we changed any jumps via cprop.
27852284Sobrien
27952284Sobrien    * If we added any labels via edge splitting.  */
28052284Sobrienstatic int run_jump_opt_after_gcse;
28152284Sobrien
28250397Sobrien/* An obstack for our working variables.  */
28350397Sobrienstatic struct obstack gcse_obstack;
28450397Sobrien
28590075Sobrienstruct reg_use {rtx reg_rtx; };
28690075Sobrien
28750397Sobrien/* Hash table of expressions.  */
28850397Sobrien
28950397Sobrienstruct expr
29050397Sobrien{
29150397Sobrien  /* The expression (SET_SRC for expressions, PATTERN for assignments).  */
29250397Sobrien  rtx expr;
29350397Sobrien  /* Index in the available expression bitmaps.  */
29450397Sobrien  int bitmap_index;
29550397Sobrien  /* Next entry with the same hash.  */
29650397Sobrien  struct expr *next_same_hash;
29750397Sobrien  /* List of anticipatable occurrences in basic blocks in the function.
29850397Sobrien     An "anticipatable occurrence" is one that is the first occurrence in the
29952284Sobrien     basic block, the operands are not modified in the basic block prior
30052284Sobrien     to the occurrence and the output is not used between the start of
30152284Sobrien     the block and the occurrence.  */
30250397Sobrien  struct occr *antic_occr;
30350397Sobrien  /* List of available occurrence in basic blocks in the function.
30450397Sobrien     An "available occurrence" is one that is the last occurrence in the
30550397Sobrien     basic block and the operands are not modified by following statements in
30650397Sobrien     the basic block [including this insn].  */
30750397Sobrien  struct occr *avail_occr;
30850397Sobrien  /* Non-null if the computation is PRE redundant.
30950397Sobrien     The value is the newly created pseudo-reg to record a copy of the
31050397Sobrien     expression in all the places that reach the redundant copy.  */
31150397Sobrien  rtx reaching_reg;
31250397Sobrien};
31350397Sobrien
31450397Sobrien/* Occurrence of an expression.
31550397Sobrien   There is one per basic block.  If a pattern appears more than once the
31650397Sobrien   last appearance is used [or first for anticipatable expressions].  */
31750397Sobrien
31850397Sobrienstruct occr
31950397Sobrien{
32050397Sobrien  /* Next occurrence of this expression.  */
32150397Sobrien  struct occr *next;
32250397Sobrien  /* The insn that computes the expression.  */
32350397Sobrien  rtx insn;
324117395Skan  /* Nonzero if this [anticipatable] occurrence has been deleted.  */
32550397Sobrien  char deleted_p;
326117395Skan  /* Nonzero if this [available] occurrence has been copied to
32750397Sobrien     reaching_reg.  */
32850397Sobrien  /* ??? This is mutually exclusive with deleted_p, so they could share
32950397Sobrien     the same byte.  */
33050397Sobrien  char copied_p;
33150397Sobrien};
33250397Sobrien
33350397Sobrien/* Expression and copy propagation hash tables.
33450397Sobrien   Each hash table is an array of buckets.
33550397Sobrien   ??? It is known that if it were an array of entries, structure elements
33650397Sobrien   `next_same_hash' and `bitmap_index' wouldn't be necessary.  However, it is
33750397Sobrien   not clear whether in the final analysis a sufficient amount of memory would
33850397Sobrien   be saved as the size of the available expression bitmaps would be larger
33950397Sobrien   [one could build a mapping table without holes afterwards though].
34090075Sobrien   Someday I'll perform the computation and figure it out.  */
34150397Sobrien
342117395Skanstruct hash_table
343117395Skan{
344117395Skan  /* The table itself.
345117395Skan     This is an array of `expr_hash_table_size' elements.  */
346117395Skan  struct expr **table;
34790075Sobrien
348117395Skan  /* Size of the hash table, in elements.  */
349117395Skan  unsigned int size;
35050397Sobrien
351117395Skan  /* Number of hash table elements.  */
352117395Skan  unsigned int n_elems;
35390075Sobrien
354117395Skan  /* Whether the table is expression of copy propagation one.  */
355117395Skan  int set_p;
356117395Skan};
35750397Sobrien
358117395Skan/* Expression hash table.  */
359117395Skanstatic struct hash_table expr_hash_table;
360117395Skan
361117395Skan/* Copy propagation hash table.  */
362117395Skanstatic struct hash_table set_hash_table;
363117395Skan
36450397Sobrien/* Mapping of uids to cuids.
36550397Sobrien   Only real insns get cuids.  */
36650397Sobrienstatic int *uid_cuid;
36750397Sobrien
36850397Sobrien/* Highest UID in UID_CUID.  */
36950397Sobrienstatic int max_uid;
37050397Sobrien
37150397Sobrien/* Get the cuid of an insn.  */
37290075Sobrien#ifdef ENABLE_CHECKING
373169689Skan#define INSN_CUID(INSN) \
374169689Skan  (gcc_assert (INSN_UID (INSN) <= max_uid), uid_cuid[INSN_UID (INSN)])
37590075Sobrien#else
37650397Sobrien#define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)])
37790075Sobrien#endif
37850397Sobrien
37950397Sobrien/* Number of cuids.  */
38050397Sobrienstatic int max_cuid;
38150397Sobrien
38250397Sobrien/* Mapping of cuids to insns.  */
38350397Sobrienstatic rtx *cuid_insn;
38450397Sobrien
38550397Sobrien/* Get insn from cuid.  */
38650397Sobrien#define CUID_INSN(CUID) (cuid_insn[CUID])
38750397Sobrien
38850397Sobrien/* Maximum register number in function prior to doing gcse + 1.
38950397Sobrien   Registers created during this pass have regno >= max_gcse_regno.
39050397Sobrien   This is named with "gcse" to not collide with global of same name.  */
39190075Sobrienstatic unsigned int max_gcse_regno;
39250397Sobrien
39350397Sobrien/* Table of registers that are modified.
39490075Sobrien
39550397Sobrien   For each register, each element is a list of places where the pseudo-reg
39650397Sobrien   is set.
39750397Sobrien
39850397Sobrien   For simplicity, GCSE is done on sets of pseudo-regs only.  PRE GCSE only
39950397Sobrien   requires knowledge of which blocks kill which regs [and thus could use
40052284Sobrien   a bitmap instead of the lists `reg_set_table' uses].
40150397Sobrien
40290075Sobrien   `reg_set_table' and could be turned into an array of bitmaps (num-bbs x
40390075Sobrien   num-regs) [however perhaps it may be useful to keep the data as is].  One
40490075Sobrien   advantage of recording things this way is that `reg_set_table' is fairly
40590075Sobrien   sparse with respect to pseudo regs but for hard regs could be fairly dense
40690075Sobrien   [relatively speaking].  And recording sets of pseudo-regs in lists speeds
40750397Sobrien   up functions like compute_transp since in the case of pseudo-regs we only
40850397Sobrien   need to iterate over the number of times a pseudo-reg is set, not over the
40950397Sobrien   number of basic blocks [clearly there is a bit of a slow down in the cases
41050397Sobrien   where a pseudo is set more than once in a block, however it is believed
41150397Sobrien   that the net effect is to speed things up].  This isn't done for hard-regs
41250397Sobrien   because recording call-clobbered hard-regs in `reg_set_table' at each
41390075Sobrien   function call can consume a fair bit of memory, and iterating over
41490075Sobrien   hard-regs stored this way in compute_transp will be more expensive.  */
41550397Sobrien
41690075Sobrientypedef struct reg_set
41790075Sobrien{
41850397Sobrien  /* The next setting of this register.  */
41950397Sobrien  struct reg_set *next;
420169689Skan  /* The index of the block where it was set.  */
421169689Skan  int bb_index;
42250397Sobrien} reg_set;
42390075Sobrien
42450397Sobrienstatic reg_set **reg_set_table;
42590075Sobrien
42650397Sobrien/* Size of `reg_set_table'.
42750397Sobrien   The table starts out at max_gcse_regno + slop, and is enlarged as
42850397Sobrien   necessary.  */
42950397Sobrienstatic int reg_set_table_size;
43090075Sobrien
43150397Sobrien/* Amount to grow `reg_set_table' by when it's full.  */
43250397Sobrien#define REG_SET_TABLE_SLOP 100
43350397Sobrien
43490075Sobrien/* This is a list of expressions which are MEMs and will be used by load
435117395Skan   or store motion.
43690075Sobrien   Load motion tracks MEMs which aren't killed by
437169689Skan   anything except itself. (i.e., loads and stores to a single location).
438117395Skan   We can then allow movement of these MEM refs with a little special
43990075Sobrien   allowance. (all stores copy the same value to the reaching reg used
44090075Sobrien   for the loads).  This means all values used to store into memory must have
441117395Skan   no side effects so we can re-issue the setter value.
44290075Sobrien   Store Motion uses this structure as an expression table to track stores
44390075Sobrien   which look interesting, and might be moveable towards the exit block.  */
44490075Sobrien
44590075Sobrienstruct ls_expr
44690075Sobrien{
44790075Sobrien  struct expr * expr;		/* Gcse expression reference for LM.  */
44890075Sobrien  rtx pattern;			/* Pattern of this mem.  */
449132718Skan  rtx pattern_regs;		/* List of registers mentioned by the mem.  */
45090075Sobrien  rtx loads;			/* INSN list of loads seen.  */
45190075Sobrien  rtx stores;			/* INSN list of stores seen.  */
45290075Sobrien  struct ls_expr * next;	/* Next in the list.  */
45390075Sobrien  int invalid;			/* Invalid for some reason.  */
45490075Sobrien  int index;			/* If it maps to a bitmap index.  */
455132718Skan  unsigned int hash_index;	/* Index when in a hash table.  */
45690075Sobrien  rtx reaching_reg;		/* Register to use when re-writing.  */
45790075Sobrien};
45890075Sobrien
459132718Skan/* Array of implicit set patterns indexed by basic block index.  */
460132718Skanstatic rtx *implicit_sets;
461132718Skan
46290075Sobrien/* Head of the list of load/store memory refs.  */
46390075Sobrienstatic struct ls_expr * pre_ldst_mems = NULL;
46490075Sobrien
465169689Skan/* Hashtable for the load/store memory refs.  */
466169689Skanstatic htab_t pre_ldst_table = NULL;
467169689Skan
46850397Sobrien/* Bitmap containing one bit for each register in the program.
46950397Sobrien   Used when performing GCSE to track which registers have been set since
47050397Sobrien   the start of the basic block.  */
47190075Sobrienstatic regset reg_set_bitmap;
47250397Sobrien
47350397Sobrien/* For each block, a bitmap of registers set in the block.
474169689Skan   This is used by compute_transp.
47550397Sobrien   It is computed during hash table computation and not by compute_sets
47650397Sobrien   as it includes registers added since the last pass (or between cprop and
47750397Sobrien   gcse) and it's currently not easy to realloc sbitmap vectors.  */
47850397Sobrienstatic sbitmap *reg_set_in_block;
47950397Sobrien
48090075Sobrien/* Array, indexed by basic block number for a list of insns which modify
48190075Sobrien   memory within that block.  */
48290075Sobrienstatic rtx * modify_mem_list;
483169689Skanstatic bitmap modify_mem_list_set;
48450397Sobrien
48590075Sobrien/* This array parallels modify_mem_list, but is kept canonicalized.  */
48690075Sobrienstatic rtx * canon_modify_mem_list;
487169689Skan
488169689Skan/* Bitmap indexed by block numbers to record which blocks contain
489169689Skan   function calls.  */
490169689Skanstatic bitmap blocks_with_calls;
491169689Skan
49250397Sobrien/* Various variables for statistics gathering.  */
49350397Sobrien
49450397Sobrien/* Memory used in a pass.
49550397Sobrien   This isn't intended to be absolutely precise.  Its intent is only
49650397Sobrien   to keep an eye on memory usage.  */
49750397Sobrienstatic int bytes_used;
49890075Sobrien
49950397Sobrien/* GCSE substitutions made.  */
50050397Sobrienstatic int gcse_subst_count;
50150397Sobrien/* Number of copy instructions created.  */
50250397Sobrienstatic int gcse_create_count;
503169689Skan/* Number of local constants propagated.  */
504169689Skanstatic int local_const_prop_count;
505169689Skan/* Number of local copies propagated.  */
506169689Skanstatic int local_copy_prop_count;
507169689Skan/* Number of global constants propagated.  */
508169689Skanstatic int global_const_prop_count;
509169689Skan/* Number of global copies propagated.  */
510169689Skanstatic int global_copy_prop_count;
51150397Sobrien
512169689Skan/* For available exprs */
513169689Skanstatic sbitmap *ae_kill, *ae_gen;
51450397Sobrien
515132718Skanstatic void compute_can_copy (void);
516132718Skanstatic void *gmalloc (size_t) ATTRIBUTE_MALLOC;
517132718Skanstatic void *gcalloc (size_t, size_t) ATTRIBUTE_MALLOC;
518132718Skanstatic void *grealloc (void *, size_t);
519132718Skanstatic void *gcse_alloc (unsigned long);
520169689Skanstatic void alloc_gcse_mem (void);
521132718Skanstatic void free_gcse_mem (void);
522132718Skanstatic void alloc_reg_set_mem (int);
523132718Skanstatic void free_reg_set_mem (void);
524132718Skanstatic void record_one_set (int, rtx);
525132718Skanstatic void record_set_info (rtx, rtx, void *);
526169689Skanstatic void compute_sets (void);
527132718Skanstatic void hash_scan_insn (rtx, struct hash_table *, int);
528132718Skanstatic void hash_scan_set (rtx, rtx, struct hash_table *);
529132718Skanstatic void hash_scan_clobber (rtx, rtx, struct hash_table *);
530132718Skanstatic void hash_scan_call (rtx, rtx, struct hash_table *);
531132718Skanstatic int want_to_gcse_p (rtx);
532169689Skanstatic bool can_assign_to_reg_p (rtx);
533132718Skanstatic bool gcse_constant_p (rtx);
534132718Skanstatic int oprs_unchanged_p (rtx, rtx, int);
535132718Skanstatic int oprs_anticipatable_p (rtx, rtx);
536132718Skanstatic int oprs_available_p (rtx, rtx);
537132718Skanstatic void insert_expr_in_table (rtx, enum machine_mode, rtx, int, int,
538132718Skan				  struct hash_table *);
539132718Skanstatic void insert_set_in_table (rtx, rtx, struct hash_table *);
540132718Skanstatic unsigned int hash_expr (rtx, enum machine_mode, int *, int);
541132718Skanstatic unsigned int hash_set (int, int);
542132718Skanstatic int expr_equiv_p (rtx, rtx);
543132718Skanstatic void record_last_reg_set_info (rtx, int);
544132718Skanstatic void record_last_mem_set_info (rtx);
545132718Skanstatic void record_last_set_info (rtx, rtx, void *);
546132718Skanstatic void compute_hash_table (struct hash_table *);
547132718Skanstatic void alloc_hash_table (int, struct hash_table *, int);
548132718Skanstatic void free_hash_table (struct hash_table *);
549132718Skanstatic void compute_hash_table_work (struct hash_table *);
550132718Skanstatic void dump_hash_table (FILE *, const char *, struct hash_table *);
551132718Skanstatic struct expr *lookup_set (unsigned int, struct hash_table *);
552132718Skanstatic struct expr *next_set (unsigned int, struct expr *);
553132718Skanstatic void reset_opr_set_tables (void);
554132718Skanstatic int oprs_not_set_p (rtx, rtx);
555132718Skanstatic void mark_call (rtx);
556132718Skanstatic void mark_set (rtx, rtx);
557132718Skanstatic void mark_clobber (rtx, rtx);
558132718Skanstatic void mark_oprs_set (rtx);
559132718Skanstatic void alloc_cprop_mem (int, int);
560132718Skanstatic void free_cprop_mem (void);
561132718Skanstatic void compute_transp (rtx, int, sbitmap *, int);
562132718Skanstatic void compute_transpout (void);
563132718Skanstatic void compute_local_properties (sbitmap *, sbitmap *, sbitmap *,
564132718Skan				      struct hash_table *);
565132718Skanstatic void compute_cprop_data (void);
566132718Skanstatic void find_used_regs (rtx *, void *);
567132718Skanstatic int try_replace_reg (rtx, rtx, rtx);
568132718Skanstatic struct expr *find_avail_set (int, rtx);
569132718Skanstatic int cprop_jump (basic_block, rtx, rtx, rtx, rtx);
570132718Skanstatic void mems_conflict_for_gcse_p (rtx, rtx, void *);
571132718Skanstatic int load_killed_in_block_p (basic_block, int, rtx, int);
572132718Skanstatic void canon_list_insert (rtx, rtx, void *);
573132718Skanstatic int cprop_insn (rtx, int);
574132718Skanstatic int cprop (int);
575132718Skanstatic void find_implicit_sets (void);
576169689Skanstatic int one_cprop_pass (int, bool, bool);
577169689Skanstatic bool constprop_register (rtx, rtx, rtx, bool);
578132718Skanstatic struct expr *find_bypass_set (int, int);
579132718Skanstatic bool reg_killed_on_edge (rtx, edge);
580132718Skanstatic int bypass_block (basic_block, rtx, rtx);
581132718Skanstatic int bypass_conditional_jumps (void);
582132718Skanstatic void alloc_pre_mem (int, int);
583132718Skanstatic void free_pre_mem (void);
584132718Skanstatic void compute_pre_data (void);
585132718Skanstatic int pre_expr_reaches_here_p (basic_block, struct expr *,
586132718Skan				    basic_block);
587132718Skanstatic void insert_insn_end_bb (struct expr *, basic_block, int);
588132718Skanstatic void pre_insert_copy_insn (struct expr *, rtx);
589132718Skanstatic void pre_insert_copies (void);
590132718Skanstatic int pre_delete (void);
591132718Skanstatic int pre_gcse (void);
592132718Skanstatic int one_pre_gcse_pass (int);
593132718Skanstatic void add_label_notes (rtx, rtx);
594132718Skanstatic void alloc_code_hoist_mem (int, int);
595132718Skanstatic void free_code_hoist_mem (void);
596132718Skanstatic void compute_code_hoist_vbeinout (void);
597132718Skanstatic void compute_code_hoist_data (void);
598132718Skanstatic int hoist_expr_reaches_here_p (basic_block, int, basic_block, char *);
599132718Skanstatic void hoist_code (void);
600132718Skanstatic int one_code_hoisting_pass (void);
601132718Skanstatic rtx process_insert_insn (struct expr *);
602132718Skanstatic int pre_edge_insert (struct edge_list *, struct expr **);
603132718Skanstatic int pre_expr_reaches_here_p_work (basic_block, struct expr *,
604132718Skan					 basic_block, char *);
605132718Skanstatic struct ls_expr * ldst_entry (rtx);
606132718Skanstatic void free_ldst_entry (struct ls_expr *);
607132718Skanstatic void free_ldst_mems (void);
608132718Skanstatic void print_ldst_list (FILE *);
609132718Skanstatic struct ls_expr * find_rtx_in_ldst (rtx);
610132718Skanstatic int enumerate_ldsts (void);
611132718Skanstatic inline struct ls_expr * first_ls_expr (void);
612132718Skanstatic inline struct ls_expr * next_ls_expr (struct ls_expr *);
613132718Skanstatic int simple_mem (rtx);
614132718Skanstatic void invalidate_any_buried_refs (rtx);
615132718Skanstatic void compute_ld_motion_mems (void);
616132718Skanstatic void trim_ld_motion_mems (void);
617132718Skanstatic void update_ld_motion_stores (struct expr *);
618132718Skanstatic void reg_set_info (rtx, rtx, void *);
619132718Skanstatic void reg_clear_last_set (rtx, rtx, void *);
620132718Skanstatic bool store_ops_ok (rtx, int *);
621132718Skanstatic rtx extract_mentioned_regs (rtx);
622132718Skanstatic rtx extract_mentioned_regs_helper (rtx, rtx);
623132718Skanstatic void find_moveable_store (rtx, int *, int *);
624132718Skanstatic int compute_store_table (void);
625132718Skanstatic bool load_kills_store (rtx, rtx, int);
626132718Skanstatic bool find_loads (rtx, rtx, int);
627132718Skanstatic bool store_killed_in_insn (rtx, rtx, rtx, int);
628132718Skanstatic bool store_killed_after (rtx, rtx, rtx, basic_block, int *, rtx *);
629132718Skanstatic bool store_killed_before (rtx, rtx, rtx, basic_block, int *);
630132718Skanstatic void build_store_vectors (void);
631132718Skanstatic void insert_insn_start_bb (rtx, basic_block);
632132718Skanstatic int insert_store (struct ls_expr *, edge);
633132718Skanstatic void remove_reachable_equiv_notes (basic_block, struct ls_expr *);
634132718Skanstatic void replace_store_insn (rtx, rtx, basic_block, struct ls_expr *);
635132718Skanstatic void delete_store (struct ls_expr *, basic_block);
636132718Skanstatic void free_store_memory (void);
637132718Skanstatic void store_motion (void);
638132718Skanstatic void free_insn_expr_list_list (rtx *);
639132718Skanstatic void clear_modify_mem_tables (void);
640132718Skanstatic void free_modify_mem_tables (void);
641132718Skanstatic rtx gcse_emit_move_after (rtx, rtx, rtx);
642132718Skanstatic void local_cprop_find_used_regs (rtx *, void *);
643169689Skanstatic bool do_local_cprop (rtx, rtx, bool, rtx*);
644132718Skanstatic bool adjust_libcall_notes (rtx, rtx, rtx, rtx*);
645169689Skanstatic void local_cprop_pass (bool);
646132718Skanstatic bool is_too_expensive (const char *);
64750397Sobrien
648132718Skan
64950397Sobrien/* Entry point for global common subexpression elimination.
650169689Skan   F is the first instruction in the function.  Return nonzero if a
651169689Skan   change is mode.  */
65250397Sobrien
653169689Skanstatic int
654169689Skangcse_main (rtx f ATTRIBUTE_UNUSED)
65550397Sobrien{
65650397Sobrien  int changed, pass;
65750397Sobrien  /* Bytes used at start of pass.  */
65850397Sobrien  int initial_bytes_used;
65950397Sobrien  /* Maximum number of bytes used by a pass.  */
66050397Sobrien  int max_pass_bytes;
66150397Sobrien  /* Point to release obstack data from for each pass.  */
66250397Sobrien  char *gcse_obstack_bottom;
66350397Sobrien
66452284Sobrien  /* We do not construct an accurate cfg in functions which call
66552284Sobrien     setjmp, so just punt to be safe.  */
66650397Sobrien  if (current_function_calls_setjmp)
66752284Sobrien    return 0;
668117395Skan
66952284Sobrien  /* Assume that we do not need to run jump optimizations after gcse.  */
67052284Sobrien  run_jump_opt_after_gcse = 0;
67152284Sobrien
67252284Sobrien  /* Identify the basic block information for this function, including
67352284Sobrien     successors and predecessors.  */
67450397Sobrien  max_gcse_regno = max_reg_num ();
67550397Sobrien
676169689Skan  if (dump_file)
677169689Skan    dump_flow_info (dump_file, dump_flags);
67890075Sobrien
679132718Skan  /* Return if there's nothing to do, or it is too expensive.  */
680169689Skan  if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1
681169689Skan      || is_too_expensive (_("GCSE disabled")))
68290075Sobrien    return 0;
683169689Skan
68450397Sobrien  gcc_obstack_init (&gcse_obstack);
68590075Sobrien  bytes_used = 0;
68650397Sobrien
68790075Sobrien  /* We need alias.  */
68890075Sobrien  init_alias_analysis ();
68990075Sobrien  /* Record where pseudo-registers are set.  This data is kept accurate
69090075Sobrien     during each pass.  ??? We could also record hard-reg information here
69190075Sobrien     [since it's unchanging], however it is currently done during hash table
69290075Sobrien     computation.
69350397Sobrien
69490075Sobrien     It may be tempting to compute MEM set information here too, but MEM sets
69590075Sobrien     will be subject to code motion one day and thus we need to compute
69652284Sobrien     information about memory sets when we build the hash tables.  */
69752284Sobrien
69850397Sobrien  alloc_reg_set_mem (max_gcse_regno);
699169689Skan  compute_sets ();
70050397Sobrien
70150397Sobrien  pass = 0;
70250397Sobrien  initial_bytes_used = bytes_used;
70350397Sobrien  max_pass_bytes = 0;
70450397Sobrien  gcse_obstack_bottom = gcse_alloc (1);
70550397Sobrien  changed = 1;
70690075Sobrien  while (changed && pass < MAX_GCSE_PASSES)
70750397Sobrien    {
70850397Sobrien      changed = 0;
709169689Skan      if (dump_file)
710169689Skan	fprintf (dump_file, "GCSE pass %d\n\n", pass + 1);
71150397Sobrien
71250397Sobrien      /* Initialize bytes_used to the space for the pred/succ lists,
71350397Sobrien	 and the reg_set_table data.  */
71450397Sobrien      bytes_used = initial_bytes_used;
71550397Sobrien
71650397Sobrien      /* Each pass may create new registers, so recalculate each time.  */
71750397Sobrien      max_gcse_regno = max_reg_num ();
71850397Sobrien
719169689Skan      alloc_gcse_mem ();
72050397Sobrien
72152284Sobrien      /* Don't allow constant propagation to modify jumps
72252284Sobrien	 during this pass.  */
723169689Skan      timevar_push (TV_CPROP1);
724169689Skan      changed = one_cprop_pass (pass + 1, false, false);
725169689Skan      timevar_pop (TV_CPROP1);
72650397Sobrien
72750397Sobrien      if (optimize_size)
728169689Skan	/* Do nothing.  */ ;
72950397Sobrien      else
730117395Skan	{
731169689Skan	  timevar_push (TV_PRE);
73290075Sobrien	  changed |= one_pre_gcse_pass (pass + 1);
73390075Sobrien	  /* We may have just created new basic blocks.  Release and
73490075Sobrien	     recompute various things which are sized on the number of
73590075Sobrien	     basic blocks.  */
73690075Sobrien	  if (changed)
73790075Sobrien	    {
73890075Sobrien	      free_modify_mem_tables ();
739132718Skan	      modify_mem_list = gcalloc (last_basic_block, sizeof (rtx));
740132718Skan	      canon_modify_mem_list = gcalloc (last_basic_block, sizeof (rtx));
74190075Sobrien	    }
74290075Sobrien	  free_reg_set_mem ();
74390075Sobrien	  alloc_reg_set_mem (max_reg_num ());
744169689Skan	  compute_sets ();
74590075Sobrien	  run_jump_opt_after_gcse = 1;
746169689Skan	  timevar_pop (TV_PRE);
74790075Sobrien	}
74850397Sobrien
74950397Sobrien      if (max_pass_bytes < bytes_used)
75050397Sobrien	max_pass_bytes = bytes_used;
75150397Sobrien
75290075Sobrien      /* Free up memory, then reallocate for code hoisting.  We can
75390075Sobrien	 not re-use the existing allocated memory because the tables
75490075Sobrien	 will not have info for the insns or registers created by
75590075Sobrien	 partial redundancy elimination.  */
75650397Sobrien      free_gcse_mem ();
75750397Sobrien
758132718Skan      /* It does not make sense to run code hoisting unless we are optimizing
75990075Sobrien	 for code size -- it rarely makes programs faster, and can make
76090075Sobrien	 them bigger if we did partial redundancy elimination (when optimizing
761169689Skan	 for space, we don't run the partial redundancy algorithms).  */
76290075Sobrien      if (optimize_size)
763117395Skan	{
764169689Skan	  timevar_push (TV_HOIST);
76590075Sobrien	  max_gcse_regno = max_reg_num ();
766169689Skan	  alloc_gcse_mem ();
76790075Sobrien	  changed |= one_code_hoisting_pass ();
76890075Sobrien	  free_gcse_mem ();
76990075Sobrien
77090075Sobrien	  if (max_pass_bytes < bytes_used)
77190075Sobrien	    max_pass_bytes = bytes_used;
772169689Skan	  timevar_pop (TV_HOIST);
773117395Skan	}
77490075Sobrien
775169689Skan      if (dump_file)
77650397Sobrien	{
777169689Skan	  fprintf (dump_file, "\n");
778169689Skan	  fflush (dump_file);
77950397Sobrien	}
78090075Sobrien
78150397Sobrien      obstack_free (&gcse_obstack, gcse_obstack_bottom);
78250397Sobrien      pass++;
78350397Sobrien    }
78450397Sobrien
78552284Sobrien  /* Do one last pass of copy propagation, including cprop into
78652284Sobrien     conditional jumps.  */
78750397Sobrien
78852284Sobrien  max_gcse_regno = max_reg_num ();
789169689Skan  alloc_gcse_mem ();
79052284Sobrien  /* This time, go ahead and allow cprop to alter jumps.  */
791169689Skan  timevar_push (TV_CPROP2);
792169689Skan  one_cprop_pass (pass + 1, true, false);
793169689Skan  timevar_pop (TV_CPROP2);
79452284Sobrien  free_gcse_mem ();
79552284Sobrien
796169689Skan  if (dump_file)
79750397Sobrien    {
798169689Skan      fprintf (dump_file, "GCSE of %s: %d basic blocks, ",
799132718Skan	       current_function_name (), n_basic_blocks);
800169689Skan      fprintf (dump_file, "%d pass%s, %d bytes\n\n",
80150397Sobrien	       pass, pass > 1 ? "es" : "", max_pass_bytes);
80250397Sobrien    }
80350397Sobrien
80490075Sobrien  obstack_free (&gcse_obstack, NULL);
80550397Sobrien  free_reg_set_mem ();
806169689Skan
80790075Sobrien  /* We are finished with alias.  */
80890075Sobrien  end_alias_analysis ();
80990075Sobrien  allocate_reg_info (max_reg_num (), FALSE, FALSE);
81090075Sobrien
811132718Skan  if (!optimize_size && flag_gcse_sm)
812169689Skan    {
813169689Skan      timevar_push (TV_LSM);
814169689Skan      store_motion ();
815169689Skan      timevar_pop (TV_LSM);
816169689Skan    }
817132718Skan
81890075Sobrien  /* Record where pseudo-registers are set.  */
81952284Sobrien  return run_jump_opt_after_gcse;
82050397Sobrien}
82150397Sobrien
82250397Sobrien/* Misc. utilities.  */
82350397Sobrien
824132718Skan/* Nonzero for each mode that supports (set (reg) (reg)).
825132718Skan   This is trivially true for integer and floating point values.
826132718Skan   It may or may not be true for condition codes.  */
827132718Skanstatic char can_copy[(int) NUM_MACHINE_MODES];
828132718Skan
82950397Sobrien/* Compute which modes support reg/reg copy operations.  */
83050397Sobrien
83150397Sobrienstatic void
832132718Skancompute_can_copy (void)
83350397Sobrien{
83450397Sobrien  int i;
83550397Sobrien#ifndef AVOID_CCMODE_COPIES
83690075Sobrien  rtx reg, insn;
83750397Sobrien#endif
838132718Skan  memset (can_copy, 0, NUM_MACHINE_MODES);
83950397Sobrien
84050397Sobrien  start_sequence ();
84150397Sobrien  for (i = 0; i < NUM_MACHINE_MODES; i++)
84290075Sobrien    if (GET_MODE_CLASS (i) == MODE_CC)
84390075Sobrien      {
84450397Sobrien#ifdef AVOID_CCMODE_COPIES
845132718Skan	can_copy[i] = 0;
84650397Sobrien#else
84790075Sobrien	reg = gen_rtx_REG ((enum machine_mode) i, LAST_VIRTUAL_REGISTER + 1);
84890075Sobrien	insn = emit_insn (gen_rtx_SET (VOIDmode, reg, reg));
84990075Sobrien	if (recog (PATTERN (insn), insn, NULL) >= 0)
850132718Skan	  can_copy[i] = 1;
85150397Sobrien#endif
85290075Sobrien      }
85390075Sobrien    else
854132718Skan      can_copy[i] = 1;
85590075Sobrien
85650397Sobrien  end_sequence ();
85750397Sobrien}
858132718Skan
859132718Skan/* Returns whether the mode supports reg/reg copy operations.  */
860132718Skan
861132718Skanbool
862132718Skancan_copy_p (enum machine_mode mode)
863132718Skan{
864132718Skan  static bool can_copy_init_p = false;
865132718Skan
866132718Skan  if (! can_copy_init_p)
867132718Skan    {
868132718Skan      compute_can_copy ();
869132718Skan      can_copy_init_p = true;
870132718Skan    }
871132718Skan
872132718Skan  return can_copy[mode] != 0;
873132718Skan}
87450397Sobrien
87550397Sobrien/* Cover function to xmalloc to record bytes allocated.  */
87650397Sobrien
877132718Skanstatic void *
878132718Skangmalloc (size_t size)
87950397Sobrien{
88050397Sobrien  bytes_used += size;
88150397Sobrien  return xmalloc (size);
88250397Sobrien}
88350397Sobrien
884132718Skan/* Cover function to xcalloc to record bytes allocated.  */
885132718Skan
886132718Skanstatic void *
887132718Skangcalloc (size_t nelem, size_t elsize)
888132718Skan{
889132718Skan  bytes_used += nelem * elsize;
890132718Skan  return xcalloc (nelem, elsize);
891132718Skan}
892132718Skan
89350397Sobrien/* Cover function to xrealloc.
89450397Sobrien   We don't record the additional size since we don't know it.
89550397Sobrien   It won't affect memory usage stats much anyway.  */
89650397Sobrien
897132718Skanstatic void *
898132718Skangrealloc (void *ptr, size_t size)
89950397Sobrien{
90050397Sobrien  return xrealloc (ptr, size);
90150397Sobrien}
90250397Sobrien
903117395Skan/* Cover function to obstack_alloc.  */
90450397Sobrien
905132718Skanstatic void *
906132718Skangcse_alloc (unsigned long size)
90750397Sobrien{
908117395Skan  bytes_used += size;
909132718Skan  return obstack_alloc (&gcse_obstack, size);
91050397Sobrien}
91150397Sobrien
91250397Sobrien/* Allocate memory for the cuid mapping array,
91350397Sobrien   and reg/memory set tracking tables.
91450397Sobrien
91550397Sobrien   This is called at the start of each pass.  */
91650397Sobrien
91750397Sobrienstatic void
918169689Skanalloc_gcse_mem (void)
91950397Sobrien{
920132718Skan  int i;
921169689Skan  basic_block bb;
92250397Sobrien  rtx insn;
92350397Sobrien
92450397Sobrien  /* Find the largest UID and create a mapping from UIDs to CUIDs.
92550397Sobrien     CUIDs are like UIDs except they increase monotonically, have no gaps,
926169689Skan     and only apply to real insns.
927169689Skan     (Actually, there are gaps, for insn that are not inside a basic block.
928169689Skan     but we should never see those anyway, so this is OK.)  */
92950397Sobrien
93050397Sobrien  max_uid = get_max_uid ();
931132718Skan  uid_cuid = gcalloc (max_uid + 1, sizeof (int));
932169689Skan  i = 0;
933169689Skan  FOR_EACH_BB (bb)
934169689Skan    FOR_BB_INSNS (bb, insn)
935169689Skan      {
936169689Skan	if (INSN_P (insn))
937169689Skan	  uid_cuid[INSN_UID (insn)] = i++;
938169689Skan	else
939169689Skan	  uid_cuid[INSN_UID (insn)] = i;
940169689Skan      }
94150397Sobrien
94250397Sobrien  /* Create a table mapping cuids to insns.  */
94350397Sobrien
94450397Sobrien  max_cuid = i;
945132718Skan  cuid_insn = gcalloc (max_cuid + 1, sizeof (rtx));
946169689Skan  i = 0;
947169689Skan  FOR_EACH_BB (bb)
948169689Skan    FOR_BB_INSNS (bb, insn)
949169689Skan      if (INSN_P (insn))
950169689Skan	CUID_INSN (i++) = insn;
95150397Sobrien
95250397Sobrien  /* Allocate vars to track sets of regs.  */
953169689Skan  reg_set_bitmap = BITMAP_ALLOC (NULL);
95450397Sobrien
95550397Sobrien  /* Allocate vars to track sets of regs, memory per block.  */
956132718Skan  reg_set_in_block = sbitmap_vector_alloc (last_basic_block, max_gcse_regno);
95790075Sobrien  /* Allocate array to keep a list of insns which modify memory in each
95890075Sobrien     basic block.  */
959132718Skan  modify_mem_list = gcalloc (last_basic_block, sizeof (rtx));
960132718Skan  canon_modify_mem_list = gcalloc (last_basic_block, sizeof (rtx));
961169689Skan  modify_mem_list_set = BITMAP_ALLOC (NULL);
962169689Skan  blocks_with_calls = BITMAP_ALLOC (NULL);
96350397Sobrien}
96450397Sobrien
96550397Sobrien/* Free memory allocated by alloc_gcse_mem.  */
96650397Sobrien
96750397Sobrienstatic void
968132718Skanfree_gcse_mem (void)
96950397Sobrien{
97050397Sobrien  free (uid_cuid);
97150397Sobrien  free (cuid_insn);
97250397Sobrien
973169689Skan  BITMAP_FREE (reg_set_bitmap);
97450397Sobrien
97590075Sobrien  sbitmap_vector_free (reg_set_in_block);
97690075Sobrien  free_modify_mem_tables ();
977169689Skan  BITMAP_FREE (modify_mem_list_set);
978169689Skan  BITMAP_FREE (blocks_with_calls);
97950397Sobrien}
98052284Sobrien
98152284Sobrien/* Compute the local properties of each recorded expression.
98252284Sobrien
98390075Sobrien   Local properties are those that are defined by the block, irrespective of
98490075Sobrien   other blocks.
98590075Sobrien
98652284Sobrien   An expression is transparent in a block if its operands are not modified
98752284Sobrien   in the block.
98852284Sobrien
98952284Sobrien   An expression is computed (locally available) in a block if it is computed
99052284Sobrien   at least once and expression would contain the same value if the
99152284Sobrien   computation was moved to the end of the block.
99252284Sobrien
99352284Sobrien   An expression is locally anticipatable in a block if it is computed at
99452284Sobrien   least once and expression would contain the same value if the computation
99552284Sobrien   was moved to the beginning of the block.
99652284Sobrien
99790075Sobrien   We call this routine for cprop, pre and code hoisting.  They all compute
99890075Sobrien   basically the same information and thus can easily share this code.
99952284Sobrien
100090075Sobrien   TRANSP, COMP, and ANTLOC are destination sbitmaps for recording local
100190075Sobrien   properties.  If NULL, then it is not necessary to compute or record that
100290075Sobrien   particular property.
100352284Sobrien
1004117395Skan   TABLE controls which hash table to look at.  If it is  set hash table,
1005117395Skan   additionally, TRANSP is computed as ~TRANSP, since this is really cprop's
100690075Sobrien   ABSALTERED.  */
1007117395Skan
100852284Sobrienstatic void
1009169689Skancompute_local_properties (sbitmap *transp, sbitmap *comp, sbitmap *antloc,
1010169689Skan			  struct hash_table *table)
101150397Sobrien{
1012117395Skan  unsigned int i;
1013117395Skan
101452284Sobrien  /* Initialize any bitmaps that were passed in.  */
101552284Sobrien  if (transp)
101652284Sobrien    {
1017117395Skan      if (table->set_p)
1018117395Skan	sbitmap_vector_zero (transp, last_basic_block);
101952284Sobrien      else
1020117395Skan	sbitmap_vector_ones (transp, last_basic_block);
102152284Sobrien    }
102290075Sobrien
102352284Sobrien  if (comp)
1024117395Skan    sbitmap_vector_zero (comp, last_basic_block);
102552284Sobrien  if (antloc)
1026117395Skan    sbitmap_vector_zero (antloc, last_basic_block);
102750397Sobrien
1028117395Skan  for (i = 0; i < table->size; i++)
102950397Sobrien    {
103052284Sobrien      struct expr *expr;
103152284Sobrien
1032117395Skan      for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
103352284Sobrien	{
103490075Sobrien	  int indx = expr->bitmap_index;
103552284Sobrien	  struct occr *occr;
103652284Sobrien
103752284Sobrien	  /* The expression is transparent in this block if it is not killed.
103852284Sobrien	     We start by assuming all are transparent [none are killed], and
103952284Sobrien	     then reset the bits for those that are.  */
104052284Sobrien	  if (transp)
1041117395Skan	    compute_transp (expr->expr, indx, transp, table->set_p);
104252284Sobrien
104352284Sobrien	  /* The occurrences recorded in antic_occr are exactly those that
1044117395Skan	     we want to set to nonzero in ANTLOC.  */
104552284Sobrien	  if (antloc)
104690075Sobrien	    for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
104790075Sobrien	      {
104890075Sobrien		SET_BIT (antloc[BLOCK_NUM (occr->insn)], indx);
104952284Sobrien
105090075Sobrien		/* While we're scanning the table, this is a good place to
105190075Sobrien		   initialize this.  */
105290075Sobrien		occr->deleted_p = 0;
105390075Sobrien	      }
105452284Sobrien
105552284Sobrien	  /* The occurrences recorded in avail_occr are exactly those that
1056117395Skan	     we want to set to nonzero in COMP.  */
105752284Sobrien	  if (comp)
105890075Sobrien	    for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
105990075Sobrien	      {
106090075Sobrien		SET_BIT (comp[BLOCK_NUM (occr->insn)], indx);
106152284Sobrien
106290075Sobrien		/* While we're scanning the table, this is a good place to
106390075Sobrien		   initialize this.  */
106490075Sobrien		occr->copied_p = 0;
106590075Sobrien	      }
106652284Sobrien
106752284Sobrien	  /* While we're scanning the table, this is a good place to
106852284Sobrien	     initialize this.  */
106952284Sobrien	  expr->reaching_reg = 0;
107052284Sobrien	}
107150397Sobrien    }
107250397Sobrien}
107350397Sobrien
107450397Sobrien/* Register set information.
107550397Sobrien
107650397Sobrien   `reg_set_table' records where each register is set or otherwise
107750397Sobrien   modified.  */
107850397Sobrien
107950397Sobrienstatic struct obstack reg_set_obstack;
108050397Sobrien
108150397Sobrienstatic void
1082132718Skanalloc_reg_set_mem (int n_regs)
108350397Sobrien{
108450397Sobrien  reg_set_table_size = n_regs + REG_SET_TABLE_SLOP;
1085132718Skan  reg_set_table = gcalloc (reg_set_table_size, sizeof (struct reg_set *));
108650397Sobrien
108750397Sobrien  gcc_obstack_init (&reg_set_obstack);
108850397Sobrien}
108950397Sobrien
109050397Sobrienstatic void
1091132718Skanfree_reg_set_mem (void)
109250397Sobrien{
109350397Sobrien  free (reg_set_table);
109490075Sobrien  obstack_free (&reg_set_obstack, NULL);
109550397Sobrien}
109650397Sobrien
109750397Sobrien/* Record REGNO in the reg_set table.  */
109850397Sobrien
109950397Sobrienstatic void
1100132718Skanrecord_one_set (int regno, rtx insn)
110150397Sobrien{
110290075Sobrien  /* Allocate a new reg_set element and link it onto the list.  */
110390075Sobrien  struct reg_set *new_reg_info;
110450397Sobrien
110550397Sobrien  /* If the table isn't big enough, enlarge it.  */
110650397Sobrien  if (regno >= reg_set_table_size)
110750397Sobrien    {
110850397Sobrien      int new_size = regno + REG_SET_TABLE_SLOP;
110990075Sobrien
1110132718Skan      reg_set_table = grealloc (reg_set_table,
1111132718Skan				new_size * sizeof (struct reg_set *));
1112132718Skan      memset (reg_set_table + reg_set_table_size, 0,
111390075Sobrien	      (new_size - reg_set_table_size) * sizeof (struct reg_set *));
111450397Sobrien      reg_set_table_size = new_size;
111550397Sobrien    }
111650397Sobrien
1117132718Skan  new_reg_info = obstack_alloc (&reg_set_obstack, sizeof (struct reg_set));
111850397Sobrien  bytes_used += sizeof (struct reg_set);
1119169689Skan  new_reg_info->bb_index = BLOCK_NUM (insn);
112090075Sobrien  new_reg_info->next = reg_set_table[regno];
112190075Sobrien  reg_set_table[regno] = new_reg_info;
112250397Sobrien}
112350397Sobrien
112490075Sobrien/* Called from compute_sets via note_stores to handle one SET or CLOBBER in
112590075Sobrien   an insn.  The DATA is really the instruction in which the SET is
112690075Sobrien   occurring.  */
112750397Sobrien
112850397Sobrienstatic void
1129132718Skanrecord_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, void *data)
113050397Sobrien{
113190075Sobrien  rtx record_set_insn = (rtx) data;
113250397Sobrien
1133169689Skan  if (REG_P (dest) && REGNO (dest) >= FIRST_PSEUDO_REGISTER)
113490075Sobrien    record_one_set (REGNO (dest), record_set_insn);
113550397Sobrien}
113650397Sobrien
113750397Sobrien/* Scan the function and record each set of each pseudo-register.
113850397Sobrien
113990075Sobrien   This is called once, at the start of the gcse pass.  See the comments for
1140132718Skan   `reg_set_table' for further documentation.  */
114150397Sobrien
114250397Sobrienstatic void
1143169689Skancompute_sets (void)
114450397Sobrien{
1145169689Skan  basic_block bb;
114690075Sobrien  rtx insn;
114750397Sobrien
1148169689Skan  FOR_EACH_BB (bb)
1149169689Skan    FOR_BB_INSNS (bb, insn)
1150169689Skan      if (INSN_P (insn))
1151169689Skan	note_stores (PATTERN (insn), record_set_info, insn);
115250397Sobrien}
115350397Sobrien
115450397Sobrien/* Hash table support.  */
115550397Sobrien
115690075Sobrienstruct reg_avail_info
115790075Sobrien{
1158117395Skan  basic_block last_bb;
115990075Sobrien  int first_set;
116090075Sobrien  int last_set;
116190075Sobrien};
116250397Sobrien
116390075Sobrienstatic struct reg_avail_info *reg_avail_info;
1164117395Skanstatic basic_block current_bb;
116550397Sobrien
116650397Sobrien
116790075Sobrien/* See whether X, the source of a set, is something we want to consider for
116890075Sobrien   GCSE.  */
116990075Sobrien
117050397Sobrienstatic int
1171132718Skanwant_to_gcse_p (rtx x)
117250397Sobrien{
1173169689Skan#ifdef STACK_REGS
1174169689Skan  /* On register stack architectures, don't GCSE constants from the
1175169689Skan     constant pool, as the benefits are often swamped by the overhead
1176169689Skan     of shuffling the register stack between basic blocks.  */
1177169689Skan  if (IS_STACK_MODE (GET_MODE (x)))
1178169689Skan    x = avoid_constant_pool_reference (x);
1179169689Skan#endif
118050397Sobrien
118190075Sobrien  switch (GET_CODE (x))
118250397Sobrien    {
118350397Sobrien    case REG:
118450397Sobrien    case SUBREG:
118550397Sobrien    case CONST_INT:
118650397Sobrien    case CONST_DOUBLE:
118796263Sobrien    case CONST_VECTOR:
118850397Sobrien    case CALL:
118950397Sobrien      return 0;
119050397Sobrien
119150397Sobrien    default:
1192169689Skan      return can_assign_to_reg_p (x);
119350397Sobrien    }
1194169689Skan}
119550397Sobrien
1196169689Skan/* Used internally by can_assign_to_reg_p.  */
1197169689Skan
1198169689Skanstatic GTY(()) rtx test_insn;
1199169689Skan
1200169689Skan/* Return true if we can assign X to a pseudo register.  */
1201169689Skan
1202169689Skanstatic bool
1203169689Skancan_assign_to_reg_p (rtx x)
1204169689Skan{
1205169689Skan  int num_clobbers = 0;
1206169689Skan  int icode;
1207169689Skan
120890075Sobrien  /* If this is a valid operand, we are OK.  If it's VOIDmode, we aren't.  */
120990075Sobrien  if (general_operand (x, GET_MODE (x)))
121090075Sobrien    return 1;
121190075Sobrien  else if (GET_MODE (x) == VOIDmode)
121290075Sobrien    return 0;
121390075Sobrien
121490075Sobrien  /* Otherwise, check if we can make a valid insn from it.  First initialize
121590075Sobrien     our test insn if we haven't already.  */
121690075Sobrien  if (test_insn == 0)
121790075Sobrien    {
121890075Sobrien      test_insn
121990075Sobrien	= make_insn_raw (gen_rtx_SET (VOIDmode,
122090075Sobrien				      gen_rtx_REG (word_mode,
122190075Sobrien						   FIRST_PSEUDO_REGISTER * 2),
122290075Sobrien				      const0_rtx));
122390075Sobrien      NEXT_INSN (test_insn) = PREV_INSN (test_insn) = 0;
122490075Sobrien    }
122590075Sobrien
122690075Sobrien  /* Now make an insn like the one we would make when GCSE'ing and see if
122790075Sobrien     valid.  */
122890075Sobrien  PUT_MODE (SET_DEST (PATTERN (test_insn)), GET_MODE (x));
122990075Sobrien  SET_SRC (PATTERN (test_insn)) = x;
123090075Sobrien  return ((icode = recog (PATTERN (test_insn), test_insn, &num_clobbers)) >= 0
123190075Sobrien	  && (num_clobbers == 0 || ! added_clobbers_hard_reg_p (icode)));
123250397Sobrien}
123350397Sobrien
1234117395Skan/* Return nonzero if the operands of expression X are unchanged from the
123550397Sobrien   start of INSN's basic block up to but not including INSN (if AVAIL_P == 0),
123650397Sobrien   or from INSN to the end of INSN's basic block (if AVAIL_P != 0).  */
123750397Sobrien
123850397Sobrienstatic int
1239132718Skanoprs_unchanged_p (rtx x, rtx insn, int avail_p)
124050397Sobrien{
124190075Sobrien  int i, j;
124250397Sobrien  enum rtx_code code;
124390075Sobrien  const char *fmt;
124450397Sobrien
124550397Sobrien  if (x == 0)
124650397Sobrien    return 1;
124750397Sobrien
124850397Sobrien  code = GET_CODE (x);
124950397Sobrien  switch (code)
125050397Sobrien    {
125150397Sobrien    case REG:
125290075Sobrien      {
125390075Sobrien	struct reg_avail_info *info = &reg_avail_info[REGNO (x)];
125450397Sobrien
125590075Sobrien	if (info->last_bb != current_bb)
125690075Sobrien	  return 1;
1257117395Skan	if (avail_p)
125890075Sobrien	  return info->last_set < INSN_CUID (insn);
125990075Sobrien	else
126090075Sobrien	  return info->first_set >= INSN_CUID (insn);
126190075Sobrien      }
126290075Sobrien
126350397Sobrien    case MEM:
1264117395Skan      if (load_killed_in_block_p (current_bb, INSN_CUID (insn),
126590075Sobrien				  x, avail_p))
126690075Sobrien	return 0;
126750397Sobrien      else
126890075Sobrien	return oprs_unchanged_p (XEXP (x, 0), insn, avail_p);
126950397Sobrien
127050397Sobrien    case PRE_DEC:
127150397Sobrien    case PRE_INC:
127250397Sobrien    case POST_DEC:
127350397Sobrien    case POST_INC:
127490075Sobrien    case PRE_MODIFY:
127590075Sobrien    case POST_MODIFY:
127650397Sobrien      return 0;
127750397Sobrien
127850397Sobrien    case PC:
127950397Sobrien    case CC0: /*FIXME*/
128050397Sobrien    case CONST:
128150397Sobrien    case CONST_INT:
128250397Sobrien    case CONST_DOUBLE:
128396263Sobrien    case CONST_VECTOR:
128450397Sobrien    case SYMBOL_REF:
128550397Sobrien    case LABEL_REF:
128650397Sobrien    case ADDR_VEC:
128750397Sobrien    case ADDR_DIFF_VEC:
128850397Sobrien      return 1;
128950397Sobrien
129050397Sobrien    default:
129150397Sobrien      break;
129250397Sobrien    }
129350397Sobrien
129490075Sobrien  for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
129550397Sobrien    {
129650397Sobrien      if (fmt[i] == 'e')
129750397Sobrien	{
129890075Sobrien	  /* If we are about to do the last recursive call needed at this
129990075Sobrien	     level, change it into iteration.  This function is called enough
130090075Sobrien	     to be worth it.  */
130190075Sobrien	  if (i == 0)
130290075Sobrien	    return oprs_unchanged_p (XEXP (x, i), insn, avail_p);
130350397Sobrien
130490075Sobrien	  else if (! oprs_unchanged_p (XEXP (x, i), insn, avail_p))
130550397Sobrien	    return 0;
130650397Sobrien	}
130750397Sobrien      else if (fmt[i] == 'E')
130890075Sobrien	for (j = 0; j < XVECLEN (x, i); j++)
130990075Sobrien	  if (! oprs_unchanged_p (XVECEXP (x, i, j), insn, avail_p))
131090075Sobrien	    return 0;
131150397Sobrien    }
131250397Sobrien
131350397Sobrien  return 1;
131450397Sobrien}
131550397Sobrien
131690075Sobrien/* Used for communication between mems_conflict_for_gcse_p and
131790075Sobrien   load_killed_in_block_p.  Nonzero if mems_conflict_for_gcse_p finds a
131890075Sobrien   conflict between two memory references.  */
131990075Sobrienstatic int gcse_mems_conflict_p;
132090075Sobrien
132190075Sobrien/* Used for communication between mems_conflict_for_gcse_p and
132290075Sobrien   load_killed_in_block_p.  A memory reference for a load instruction,
132390075Sobrien   mems_conflict_for_gcse_p will see if a memory store conflicts with
132490075Sobrien   this memory load.  */
132590075Sobrienstatic rtx gcse_mem_operand;
132690075Sobrien
132790075Sobrien/* DEST is the output of an instruction.  If it is a memory reference, and
132890075Sobrien   possibly conflicts with the load found in gcse_mem_operand, then set
132990075Sobrien   gcse_mems_conflict_p to a nonzero value.  */
133090075Sobrien
133190075Sobrienstatic void
1332132718Skanmems_conflict_for_gcse_p (rtx dest, rtx setter ATTRIBUTE_UNUSED,
1333132718Skan			  void *data ATTRIBUTE_UNUSED)
133490075Sobrien{
133590075Sobrien  while (GET_CODE (dest) == SUBREG
133690075Sobrien	 || GET_CODE (dest) == ZERO_EXTRACT
133790075Sobrien	 || GET_CODE (dest) == STRICT_LOW_PART)
133890075Sobrien    dest = XEXP (dest, 0);
133990075Sobrien
134090075Sobrien  /* If DEST is not a MEM, then it will not conflict with the load.  Note
134190075Sobrien     that function calls are assumed to clobber memory, but are handled
134290075Sobrien     elsewhere.  */
1343169689Skan  if (! MEM_P (dest))
134490075Sobrien    return;
134590075Sobrien
134690075Sobrien  /* If we are setting a MEM in our list of specially recognized MEMs,
1347117395Skan     don't mark as killed this time.  */
1348117395Skan
1349132718Skan  if (expr_equiv_p (dest, gcse_mem_operand) && pre_ldst_mems != NULL)
135090075Sobrien    {
135190075Sobrien      if (!find_rtx_in_ldst (dest))
135290075Sobrien	gcse_mems_conflict_p = 1;
135390075Sobrien      return;
135490075Sobrien    }
135590075Sobrien
135690075Sobrien  if (true_dependence (dest, GET_MODE (dest), gcse_mem_operand,
135790075Sobrien		       rtx_addr_varies_p))
135890075Sobrien    gcse_mems_conflict_p = 1;
135990075Sobrien}
136090075Sobrien
136190075Sobrien/* Return nonzero if the expression in X (a memory reference) is killed
136290075Sobrien   in block BB before or after the insn with the CUID in UID_LIMIT.
136390075Sobrien   AVAIL_P is nonzero for kills after UID_LIMIT, and zero for kills
136490075Sobrien   before UID_LIMIT.
136590075Sobrien
136690075Sobrien   To check the entire block, set UID_LIMIT to max_uid + 1 and
136790075Sobrien   AVAIL_P to 0.  */
136890075Sobrien
136990075Sobrienstatic int
1370132718Skanload_killed_in_block_p (basic_block bb, int uid_limit, rtx x, int avail_p)
137190075Sobrien{
137290075Sobrien  rtx list_entry = modify_mem_list[bb->index];
1373169689Skan
1374169689Skan  /* If this is a readonly then we aren't going to be changing it.  */
1375169689Skan  if (MEM_READONLY_P (x))
1376169689Skan    return 0;
1377169689Skan
137890075Sobrien  while (list_entry)
137990075Sobrien    {
138090075Sobrien      rtx setter;
138190075Sobrien      /* Ignore entries in the list that do not apply.  */
138290075Sobrien      if ((avail_p
138390075Sobrien	   && INSN_CUID (XEXP (list_entry, 0)) < uid_limit)
138490075Sobrien	  || (! avail_p
138590075Sobrien	      && INSN_CUID (XEXP (list_entry, 0)) > uid_limit))
138690075Sobrien	{
138790075Sobrien	  list_entry = XEXP (list_entry, 1);
138890075Sobrien	  continue;
138990075Sobrien	}
139090075Sobrien
139190075Sobrien      setter = XEXP (list_entry, 0);
139290075Sobrien
139390075Sobrien      /* If SETTER is a call everything is clobbered.  Note that calls
139490075Sobrien	 to pure functions are never put on the list, so we need not
139590075Sobrien	 worry about them.  */
1396169689Skan      if (CALL_P (setter))
139790075Sobrien	return 1;
139890075Sobrien
139990075Sobrien      /* SETTER must be an INSN of some kind that sets memory.  Call
1400117395Skan	 note_stores to examine each hunk of memory that is modified.
140190075Sobrien
140290075Sobrien	 The note_stores interface is pretty limited, so we have to
140390075Sobrien	 communicate via global variables.  Yuk.  */
140490075Sobrien      gcse_mem_operand = x;
140590075Sobrien      gcse_mems_conflict_p = 0;
140690075Sobrien      note_stores (PATTERN (setter), mems_conflict_for_gcse_p, NULL);
140790075Sobrien      if (gcse_mems_conflict_p)
140890075Sobrien	return 1;
140990075Sobrien      list_entry = XEXP (list_entry, 1);
141090075Sobrien    }
141190075Sobrien  return 0;
141290075Sobrien}
141390075Sobrien
1414117395Skan/* Return nonzero if the operands of expression X are unchanged from
141550397Sobrien   the start of INSN's basic block up to but not including INSN.  */
141650397Sobrien
141750397Sobrienstatic int
1418132718Skanoprs_anticipatable_p (rtx x, rtx insn)
141950397Sobrien{
142050397Sobrien  return oprs_unchanged_p (x, insn, 0);
142150397Sobrien}
142250397Sobrien
1423117395Skan/* Return nonzero if the operands of expression X are unchanged from
142450397Sobrien   INSN to the end of INSN's basic block.  */
142550397Sobrien
142650397Sobrienstatic int
1427132718Skanoprs_available_p (rtx x, rtx insn)
142850397Sobrien{
142950397Sobrien  return oprs_unchanged_p (x, insn, 1);
143050397Sobrien}
143150397Sobrien
143250397Sobrien/* Hash expression X.
143350397Sobrien
143490075Sobrien   MODE is only used if X is a CONST_INT.  DO_NOT_RECORD_P is a boolean
143590075Sobrien   indicating if a volatile operand is found or if the expression contains
1436132718Skan   something we don't want to insert in the table.  HASH_TABLE_SIZE is
1437169689Skan   the current size of the hash table to be probed.  */
143890075Sobrien
143950397Sobrienstatic unsigned int
1440132718Skanhash_expr (rtx x, enum machine_mode mode, int *do_not_record_p,
1441132718Skan	   int hash_table_size)
144250397Sobrien{
144350397Sobrien  unsigned int hash;
144450397Sobrien
144550397Sobrien  *do_not_record_p = 0;
144650397Sobrien
1447169689Skan  hash = hash_rtx (x, mode, do_not_record_p,
1448169689Skan		   NULL,  /*have_reg_qty=*/false);
144950397Sobrien  return hash % hash_table_size;
145050397Sobrien}
145150397Sobrien
145250397Sobrien/* Hash a set of register REGNO.
145350397Sobrien
145490075Sobrien   Sets are hashed on the register that is set.  This simplifies the PRE copy
145590075Sobrien   propagation code.
145650397Sobrien
145750397Sobrien   ??? May need to make things more elaborate.  Later, as necessary.  */
145850397Sobrien
145950397Sobrienstatic unsigned int
1460132718Skanhash_set (int regno, int hash_table_size)
146150397Sobrien{
146250397Sobrien  unsigned int hash;
146350397Sobrien
146450397Sobrien  hash = regno;
146550397Sobrien  return hash % hash_table_size;
146650397Sobrien}
146750397Sobrien
1468169689Skan/* Return nonzero if exp1 is equivalent to exp2.  */
146950397Sobrien
147050397Sobrienstatic int
1471132718Skanexpr_equiv_p (rtx x, rtx y)
147250397Sobrien{
1473169689Skan  return exp_equiv_p (x, y, 0, true);
147450397Sobrien}
147550397Sobrien
1476117395Skan/* Insert expression X in INSN in the hash TABLE.
147750397Sobrien   If it is already present, record it as the last occurrence in INSN's
147850397Sobrien   basic block.
147950397Sobrien
148050397Sobrien   MODE is the mode of the value X is being stored into.
148150397Sobrien   It is only used if X is a CONST_INT.
148250397Sobrien
1483117395Skan   ANTIC_P is nonzero if X is an anticipatable expression.
1484117395Skan   AVAIL_P is nonzero if X is an available expression.  */
148550397Sobrien
148650397Sobrienstatic void
1487132718Skaninsert_expr_in_table (rtx x, enum machine_mode mode, rtx insn, int antic_p,
1488132718Skan		      int avail_p, struct hash_table *table)
148950397Sobrien{
149050397Sobrien  int found, do_not_record_p;
149150397Sobrien  unsigned int hash;
149250397Sobrien  struct expr *cur_expr, *last_expr = NULL;
149350397Sobrien  struct occr *antic_occr, *avail_occr;
149450397Sobrien
1495117395Skan  hash = hash_expr (x, mode, &do_not_record_p, table->size);
149650397Sobrien
149750397Sobrien  /* Do not insert expression in table if it contains volatile operands,
149850397Sobrien     or if hash_expr determines the expression is something we don't want
149950397Sobrien     to or can't handle.  */
150050397Sobrien  if (do_not_record_p)
150150397Sobrien    return;
150250397Sobrien
1503117395Skan  cur_expr = table->table[hash];
150450397Sobrien  found = 0;
150550397Sobrien
150690075Sobrien  while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
150750397Sobrien    {
150850397Sobrien      /* If the expression isn't found, save a pointer to the end of
150950397Sobrien	 the list.  */
151050397Sobrien      last_expr = cur_expr;
151150397Sobrien      cur_expr = cur_expr->next_same_hash;
151250397Sobrien    }
151350397Sobrien
151450397Sobrien  if (! found)
151550397Sobrien    {
1516132718Skan      cur_expr = gcse_alloc (sizeof (struct expr));
151750397Sobrien      bytes_used += sizeof (struct expr);
1518117395Skan      if (table->table[hash] == NULL)
151990075Sobrien	/* This is the first pattern that hashed to this index.  */
1520117395Skan	table->table[hash] = cur_expr;
152150397Sobrien      else
152290075Sobrien	/* Add EXPR to end of this hash chain.  */
152390075Sobrien	last_expr->next_same_hash = cur_expr;
152490075Sobrien
1525117395Skan      /* Set the fields of the expr element.  */
152650397Sobrien      cur_expr->expr = x;
1527117395Skan      cur_expr->bitmap_index = table->n_elems++;
152850397Sobrien      cur_expr->next_same_hash = NULL;
152950397Sobrien      cur_expr->antic_occr = NULL;
153050397Sobrien      cur_expr->avail_occr = NULL;
153150397Sobrien    }
153250397Sobrien
153350397Sobrien  /* Now record the occurrence(s).  */
153450397Sobrien  if (antic_p)
153550397Sobrien    {
153650397Sobrien      antic_occr = cur_expr->antic_occr;
153750397Sobrien
1538169689Skan      if (antic_occr && BLOCK_NUM (antic_occr->insn) != BLOCK_NUM (insn))
1539169689Skan	antic_occr = NULL;
154050397Sobrien
154150397Sobrien      if (antic_occr)
154290075Sobrien	/* Found another instance of the expression in the same basic block.
154390075Sobrien	   Prefer the currently recorded one.  We want the first one in the
154490075Sobrien	   block and the block is scanned from start to end.  */
154590075Sobrien	; /* nothing to do */
154650397Sobrien      else
154750397Sobrien	{
154850397Sobrien	  /* First occurrence of this expression in this basic block.  */
1549132718Skan	  antic_occr = gcse_alloc (sizeof (struct occr));
155050397Sobrien	  bytes_used += sizeof (struct occr);
155150397Sobrien	  antic_occr->insn = insn;
1552169689Skan	  antic_occr->next = cur_expr->antic_occr;
1553169689Skan	  antic_occr->deleted_p = 0;
1554169689Skan	  cur_expr->antic_occr = antic_occr;
155550397Sobrien	}
155650397Sobrien    }
155750397Sobrien
155850397Sobrien  if (avail_p)
155950397Sobrien    {
156050397Sobrien      avail_occr = cur_expr->avail_occr;
156150397Sobrien
1562169689Skan      if (avail_occr && BLOCK_NUM (avail_occr->insn) == BLOCK_NUM (insn))
156350397Sobrien	{
1564169689Skan	  /* Found another instance of the expression in the same basic block.
1565169689Skan	     Prefer this occurrence to the currently recorded one.  We want
1566169689Skan	     the last one in the block and the block is scanned from start
1567169689Skan	     to end.  */
1568169689Skan	  avail_occr->insn = insn;
156950397Sobrien	}
157050397Sobrien      else
157150397Sobrien	{
157250397Sobrien	  /* First occurrence of this expression in this basic block.  */
1573132718Skan	  avail_occr = gcse_alloc (sizeof (struct occr));
157450397Sobrien	  bytes_used += sizeof (struct occr);
157550397Sobrien	  avail_occr->insn = insn;
1576169689Skan	  avail_occr->next = cur_expr->avail_occr;
1577169689Skan	  avail_occr->deleted_p = 0;
1578169689Skan	  cur_expr->avail_occr = avail_occr;
157950397Sobrien	}
158050397Sobrien    }
158150397Sobrien}
158250397Sobrien
158350397Sobrien/* Insert pattern X in INSN in the hash table.
158450397Sobrien   X is a SET of a reg to either another reg or a constant.
158550397Sobrien   If it is already present, record it as the last occurrence in INSN's
158650397Sobrien   basic block.  */
158750397Sobrien
158850397Sobrienstatic void
1589132718Skaninsert_set_in_table (rtx x, rtx insn, struct hash_table *table)
159050397Sobrien{
159150397Sobrien  int found;
159250397Sobrien  unsigned int hash;
159350397Sobrien  struct expr *cur_expr, *last_expr = NULL;
1594169689Skan  struct occr *cur_occr;
159550397Sobrien
1596169689Skan  gcc_assert (GET_CODE (x) == SET && REG_P (SET_DEST (x)));
159750397Sobrien
1598117395Skan  hash = hash_set (REGNO (SET_DEST (x)), table->size);
159950397Sobrien
1600117395Skan  cur_expr = table->table[hash];
160150397Sobrien  found = 0;
160250397Sobrien
160390075Sobrien  while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
160450397Sobrien    {
160550397Sobrien      /* If the expression isn't found, save a pointer to the end of
160650397Sobrien	 the list.  */
160750397Sobrien      last_expr = cur_expr;
160850397Sobrien      cur_expr = cur_expr->next_same_hash;
160950397Sobrien    }
161050397Sobrien
161150397Sobrien  if (! found)
161250397Sobrien    {
1613132718Skan      cur_expr = gcse_alloc (sizeof (struct expr));
161450397Sobrien      bytes_used += sizeof (struct expr);
1615117395Skan      if (table->table[hash] == NULL)
161690075Sobrien	/* This is the first pattern that hashed to this index.  */
1617117395Skan	table->table[hash] = cur_expr;
161850397Sobrien      else
161990075Sobrien	/* Add EXPR to end of this hash chain.  */
162090075Sobrien	last_expr->next_same_hash = cur_expr;
162190075Sobrien
162250397Sobrien      /* Set the fields of the expr element.
162350397Sobrien	 We must copy X because it can be modified when copy propagation is
162450397Sobrien	 performed on its operands.  */
162550397Sobrien      cur_expr->expr = copy_rtx (x);
1626117395Skan      cur_expr->bitmap_index = table->n_elems++;
162750397Sobrien      cur_expr->next_same_hash = NULL;
162850397Sobrien      cur_expr->antic_occr = NULL;
162950397Sobrien      cur_expr->avail_occr = NULL;
163050397Sobrien    }
163150397Sobrien
163250397Sobrien  /* Now record the occurrence.  */
163350397Sobrien  cur_occr = cur_expr->avail_occr;
163450397Sobrien
1635169689Skan  if (cur_occr && BLOCK_NUM (cur_occr->insn) == BLOCK_NUM (insn))
163650397Sobrien    {
1637169689Skan      /* Found another instance of the expression in the same basic block.
1638169689Skan	 Prefer this occurrence to the currently recorded one.  We want
1639169689Skan	 the last one in the block and the block is scanned from start
1640169689Skan	 to end.  */
1641169689Skan      cur_occr->insn = insn;
164250397Sobrien    }
164350397Sobrien  else
164450397Sobrien    {
164550397Sobrien      /* First occurrence of this expression in this basic block.  */
1646132718Skan      cur_occr = gcse_alloc (sizeof (struct occr));
164750397Sobrien      bytes_used += sizeof (struct occr);
164890075Sobrien
1649169689Skan	  cur_occr->insn = insn;
1650169689Skan	  cur_occr->next = cur_expr->avail_occr;
1651169689Skan	  cur_occr->deleted_p = 0;
1652169689Skan	  cur_expr->avail_occr = cur_occr;
165350397Sobrien    }
165450397Sobrien}
165550397Sobrien
1656132718Skan/* Determine whether the rtx X should be treated as a constant for
1657132718Skan   the purposes of GCSE's constant propagation.  */
1658132718Skan
1659132718Skanstatic bool
1660132718Skangcse_constant_p (rtx x)
1661132718Skan{
1662132718Skan  /* Consider a COMPARE of two integers constant.  */
1663132718Skan  if (GET_CODE (x) == COMPARE
1664132718Skan      && GET_CODE (XEXP (x, 0)) == CONST_INT
1665132718Skan      && GET_CODE (XEXP (x, 1)) == CONST_INT)
1666132718Skan    return true;
1667132718Skan
1668132718Skan  /* Consider a COMPARE of the same registers is a constant
1669169689Skan     if they are not floating point registers.  */
1670132718Skan  if (GET_CODE(x) == COMPARE
1671169689Skan      && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1))
1672132718Skan      && REGNO (XEXP (x, 0)) == REGNO (XEXP (x, 1))
1673132718Skan      && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))
1674132718Skan      && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 1))))
1675132718Skan    return true;
1676132718Skan
1677132718Skan  return CONSTANT_P (x);
1678132718Skan}
1679132718Skan
1680117395Skan/* Scan pattern PAT of INSN and add an entry to the hash TABLE (set or
1681117395Skan   expression one).  */
168250397Sobrien
168350397Sobrienstatic void
1684132718Skanhash_scan_set (rtx pat, rtx insn, struct hash_table *table)
168550397Sobrien{
168650397Sobrien  rtx src = SET_SRC (pat);
168750397Sobrien  rtx dest = SET_DEST (pat);
168890075Sobrien  rtx note;
168950397Sobrien
169050397Sobrien  if (GET_CODE (src) == CALL)
1691117395Skan    hash_scan_call (src, insn, table);
169250397Sobrien
1693169689Skan  else if (REG_P (dest))
169450397Sobrien    {
169590075Sobrien      unsigned int regno = REGNO (dest);
169650397Sobrien      rtx tmp;
169750397Sobrien
1698169689Skan      /* See if a REG_NOTE shows this equivalent to a simpler expression.
1699169689Skan	 This allows us to do a single GCSE pass and still eliminate
1700169689Skan	 redundant constants, addresses or other expressions that are
1701169689Skan	 constructed with multiple instructions.  */
1702169689Skan      note = find_reg_equal_equiv_note (insn);
1703169689Skan      if (note != 0
1704169689Skan	  && (table->set_p
1705169689Skan	      ? gcse_constant_p (XEXP (note, 0))
1706169689Skan	      : want_to_gcse_p (XEXP (note, 0))))
170790075Sobrien	src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src);
170890075Sobrien
170950397Sobrien      /* Only record sets of pseudo-regs in the hash table.  */
1710117395Skan      if (! table->set_p
171150397Sobrien	  && regno >= FIRST_PSEUDO_REGISTER
171250397Sobrien	  /* Don't GCSE something if we can't do a reg/reg copy.  */
1713132718Skan	  && can_copy_p (GET_MODE (dest))
171496263Sobrien	  /* GCSE commonly inserts instruction after the insn.  We can't
171596263Sobrien	     do that easily for EH_REGION notes so disable GCSE on these
171696263Sobrien	     for now.  */
1717117395Skan	  && !find_reg_note (insn, REG_EH_REGION, NULL_RTX)
171850397Sobrien	  /* Is SET_SRC something we want to gcse?  */
171990075Sobrien	  && want_to_gcse_p (src)
172090075Sobrien	  /* Don't CSE a nop.  */
172190075Sobrien	  && ! set_noop_p (pat)
172290075Sobrien	  /* Don't GCSE if it has attached REG_EQUIV note.
172390075Sobrien	     At this point this only function parameters should have
172490075Sobrien	     REG_EQUIV notes and if the argument slot is used somewhere
172590075Sobrien	     explicitly, it means address of parameter has been taken,
172690075Sobrien	     so we should not extend the lifetime of the pseudo.  */
1727169689Skan	  && (note == NULL_RTX || ! MEM_P (XEXP (note, 0))))
172850397Sobrien	{
172950397Sobrien	  /* An expression is not anticipatable if its operands are
173090075Sobrien	     modified before this insn or if this is not the only SET in
173190075Sobrien	     this insn.  */
173290075Sobrien	  int antic_p = oprs_anticipatable_p (src, insn) && single_set (insn);
173350397Sobrien	  /* An expression is not available if its operands are
173490075Sobrien	     subsequently modified, including this insn.  It's also not
173590075Sobrien	     available if this is a branch, because we can't insert
173690075Sobrien	     a set after the branch.  */
173790075Sobrien	  int avail_p = (oprs_available_p (src, insn)
173890075Sobrien			 && ! JUMP_P (insn));
173990075Sobrien
1740117395Skan	  insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p, table);
174150397Sobrien	}
174290075Sobrien
174350397Sobrien      /* Record sets for constant/copy propagation.  */
1744117395Skan      else if (table->set_p
174550397Sobrien	       && regno >= FIRST_PSEUDO_REGISTER
1746169689Skan	       && ((REG_P (src)
174750397Sobrien		    && REGNO (src) >= FIRST_PSEUDO_REGISTER
1748132718Skan		    && can_copy_p (GET_MODE (dest))
174990075Sobrien		    && REGNO (src) != regno)
1750132718Skan		   || gcse_constant_p (src))
175150397Sobrien	       /* A copy is not available if its src or dest is subsequently
175250397Sobrien		  modified.  Here we want to search from INSN+1 on, but
175350397Sobrien		  oprs_available_p searches from INSN on.  */
1754132718Skan	       && (insn == BB_END (BLOCK_FOR_INSN (insn))
175550397Sobrien		   || ((tmp = next_nonnote_insn (insn)) != NULL_RTX
175650397Sobrien		       && oprs_available_p (pat, tmp))))
1757117395Skan	insert_set_in_table (pat, insn, table);
175850397Sobrien    }
1759132718Skan  /* In case of store we want to consider the memory value as available in
1760132718Skan     the REG stored in that memory. This makes it possible to remove
1761132718Skan     redundant loads from due to stores to the same location.  */
1762169689Skan  else if (flag_gcse_las && REG_P (src) && MEM_P (dest))
1763132718Skan      {
1764132718Skan        unsigned int regno = REGNO (src);
1765132718Skan
1766132718Skan        /* Do not do this for constant/copy propagation.  */
1767132718Skan        if (! table->set_p
1768132718Skan            /* Only record sets of pseudo-regs in the hash table.  */
1769132718Skan	    && regno >= FIRST_PSEUDO_REGISTER
1770132718Skan	   /* Don't GCSE something if we can't do a reg/reg copy.  */
1771132718Skan	   && can_copy_p (GET_MODE (src))
1772132718Skan	   /* GCSE commonly inserts instruction after the insn.  We can't
1773132718Skan	      do that easily for EH_REGION notes so disable GCSE on these
1774132718Skan	      for now.  */
1775132718Skan	   && ! find_reg_note (insn, REG_EH_REGION, NULL_RTX)
1776132718Skan	   /* Is SET_DEST something we want to gcse?  */
1777132718Skan	   && want_to_gcse_p (dest)
1778132718Skan	   /* Don't CSE a nop.  */
1779132718Skan	   && ! set_noop_p (pat)
1780132718Skan	   /* Don't GCSE if it has attached REG_EQUIV note.
1781132718Skan	      At this point this only function parameters should have
1782132718Skan	      REG_EQUIV notes and if the argument slot is used somewhere
1783132718Skan	      explicitly, it means address of parameter has been taken,
1784132718Skan	      so we should not extend the lifetime of the pseudo.  */
1785132718Skan	   && ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) == 0
1786169689Skan	       || ! MEM_P (XEXP (note, 0))))
1787132718Skan             {
1788132718Skan               /* Stores are never anticipatable.  */
1789132718Skan               int antic_p = 0;
1790132718Skan	       /* An expression is not available if its operands are
1791132718Skan	          subsequently modified, including this insn.  It's also not
1792132718Skan	          available if this is a branch, because we can't insert
1793132718Skan	          a set after the branch.  */
1794132718Skan               int avail_p = oprs_available_p (dest, insn)
1795132718Skan			     && ! JUMP_P (insn);
1796132718Skan
1797132718Skan	       /* Record the memory expression (DEST) in the hash table.  */
1798132718Skan	       insert_expr_in_table (dest, GET_MODE (dest), insn,
1799132718Skan				     antic_p, avail_p, table);
1800132718Skan             }
1801132718Skan      }
180250397Sobrien}
180350397Sobrien
180450397Sobrienstatic void
1805132718Skanhash_scan_clobber (rtx x ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED,
1806132718Skan		   struct hash_table *table ATTRIBUTE_UNUSED)
180750397Sobrien{
180850397Sobrien  /* Currently nothing to do.  */
180950397Sobrien}
181050397Sobrien
181150397Sobrienstatic void
1812132718Skanhash_scan_call (rtx x ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED,
1813132718Skan		struct hash_table *table ATTRIBUTE_UNUSED)
181450397Sobrien{
181550397Sobrien  /* Currently nothing to do.  */
181650397Sobrien}
181750397Sobrien
181850397Sobrien/* Process INSN and add hash table entries as appropriate.
181950397Sobrien
182050397Sobrien   Only available expressions that set a single pseudo-reg are recorded.
182150397Sobrien
182250397Sobrien   Single sets in a PARALLEL could be handled, but it's an extra complication
182350397Sobrien   that isn't dealt with right now.  The trick is handling the CLOBBERs that
182450397Sobrien   are also in the PARALLEL.  Later.
182550397Sobrien
1826117395Skan   If SET_P is nonzero, this is for the assignment hash table,
182750397Sobrien   otherwise it is for the expression hash table.
182850397Sobrien   If IN_LIBCALL_BLOCK nonzero, we are in a libcall block, and should
182950397Sobrien   not record any expressions.  */
183050397Sobrien
183150397Sobrienstatic void
1832132718Skanhash_scan_insn (rtx insn, struct hash_table *table, int in_libcall_block)
183350397Sobrien{
183450397Sobrien  rtx pat = PATTERN (insn);
183590075Sobrien  int i;
183650397Sobrien
183790075Sobrien  if (in_libcall_block)
183890075Sobrien    return;
183990075Sobrien
184050397Sobrien  /* Pick out the sets of INSN and for other forms of instructions record
184150397Sobrien     what's been modified.  */
184250397Sobrien
184390075Sobrien  if (GET_CODE (pat) == SET)
1844117395Skan    hash_scan_set (pat, insn, table);
184550397Sobrien  else if (GET_CODE (pat) == PARALLEL)
184690075Sobrien    for (i = 0; i < XVECLEN (pat, 0); i++)
184790075Sobrien      {
184890075Sobrien	rtx x = XVECEXP (pat, 0, i);
184950397Sobrien
185090075Sobrien	if (GET_CODE (x) == SET)
1851117395Skan	  hash_scan_set (x, insn, table);
185290075Sobrien	else if (GET_CODE (x) == CLOBBER)
1853117395Skan	  hash_scan_clobber (x, insn, table);
185490075Sobrien	else if (GET_CODE (x) == CALL)
1855117395Skan	  hash_scan_call (x, insn, table);
185690075Sobrien      }
185750397Sobrien
185850397Sobrien  else if (GET_CODE (pat) == CLOBBER)
1859117395Skan    hash_scan_clobber (pat, insn, table);
186050397Sobrien  else if (GET_CODE (pat) == CALL)
1861117395Skan    hash_scan_call (pat, insn, table);
186250397Sobrien}
186350397Sobrien
186450397Sobrienstatic void
1865132718Skandump_hash_table (FILE *file, const char *name, struct hash_table *table)
186650397Sobrien{
186750397Sobrien  int i;
186850397Sobrien  /* Flattened out table, so it's printed in proper order.  */
186990075Sobrien  struct expr **flat_table;
187090075Sobrien  unsigned int *hash_val;
187190075Sobrien  struct expr *expr;
187250397Sobrien
1873132718Skan  flat_table = xcalloc (table->n_elems, sizeof (struct expr *));
1874132718Skan  hash_val = xmalloc (table->n_elems * sizeof (unsigned int));
187590075Sobrien
1876117395Skan  for (i = 0; i < (int) table->size; i++)
1877117395Skan    for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
187890075Sobrien      {
187990075Sobrien	flat_table[expr->bitmap_index] = expr;
188090075Sobrien	hash_val[expr->bitmap_index] = i;
188190075Sobrien      }
188250397Sobrien
188350397Sobrien  fprintf (file, "%s hash table (%d buckets, %d entries)\n",
1884117395Skan	   name, table->size, table->n_elems);
188550397Sobrien
1886117395Skan  for (i = 0; i < (int) table->n_elems; i++)
188790075Sobrien    if (flat_table[i] != 0)
188890075Sobrien      {
188990075Sobrien	expr = flat_table[i];
189090075Sobrien	fprintf (file, "Index %d (hash value %d)\n  ",
189190075Sobrien		 expr->bitmap_index, hash_val[i]);
189290075Sobrien	print_rtl (file, expr->expr);
189390075Sobrien	fprintf (file, "\n");
189490075Sobrien      }
189550397Sobrien
189690075Sobrien  fprintf (file, "\n");
189750397Sobrien
189890075Sobrien  free (flat_table);
189990075Sobrien  free (hash_val);
190050397Sobrien}
190150397Sobrien
190250397Sobrien/* Record register first/last/block set information for REGNO in INSN.
190390075Sobrien
190490075Sobrien   first_set records the first place in the block where the register
190550397Sobrien   is set and is used to compute "anticipatability".
190690075Sobrien
190790075Sobrien   last_set records the last place in the block where the register
190850397Sobrien   is set and is used to compute "availability".
190990075Sobrien
191090075Sobrien   last_bb records the block for which first_set and last_set are
191190075Sobrien   valid, as a quick test to invalidate them.
191290075Sobrien
191350397Sobrien   reg_set_in_block records whether the register is set in the block
191450397Sobrien   and is used to compute "transparency".  */
191550397Sobrien
191650397Sobrienstatic void
1917132718Skanrecord_last_reg_set_info (rtx insn, int regno)
191850397Sobrien{
191990075Sobrien  struct reg_avail_info *info = &reg_avail_info[regno];
192090075Sobrien  int cuid = INSN_CUID (insn);
192190075Sobrien
192290075Sobrien  info->last_set = cuid;
192390075Sobrien  if (info->last_bb != current_bb)
192490075Sobrien    {
192590075Sobrien      info->last_bb = current_bb;
192690075Sobrien      info->first_set = cuid;
1927117395Skan      SET_BIT (reg_set_in_block[current_bb->index], regno);
192890075Sobrien    }
192950397Sobrien}
193050397Sobrien
193150397Sobrien
193290075Sobrien/* Record all of the canonicalized MEMs of record_last_mem_set_info's insn.
193390075Sobrien   Note we store a pair of elements in the list, so they have to be
193490075Sobrien   taken off pairwise.  */
193590075Sobrien
1936117395Skanstatic void
1937132718Skancanon_list_insert (rtx dest ATTRIBUTE_UNUSED, rtx unused1 ATTRIBUTE_UNUSED,
1938132718Skan		   void * v_insn)
193990075Sobrien{
194090075Sobrien  rtx dest_addr, insn;
194196263Sobrien  int bb;
194290075Sobrien
194390075Sobrien  while (GET_CODE (dest) == SUBREG
194490075Sobrien      || GET_CODE (dest) == ZERO_EXTRACT
194590075Sobrien      || GET_CODE (dest) == STRICT_LOW_PART)
194690075Sobrien    dest = XEXP (dest, 0);
194790075Sobrien
194890075Sobrien  /* If DEST is not a MEM, then it will not conflict with a load.  Note
194990075Sobrien     that function calls are assumed to clobber memory, but are handled
195090075Sobrien     elsewhere.  */
195190075Sobrien
1952169689Skan  if (! MEM_P (dest))
195390075Sobrien    return;
195490075Sobrien
195590075Sobrien  dest_addr = get_addr (XEXP (dest, 0));
195690075Sobrien  dest_addr = canon_rtx (dest_addr);
1957117395Skan  insn = (rtx) v_insn;
195896263Sobrien  bb = BLOCK_NUM (insn);
195990075Sobrien
1960117395Skan  canon_modify_mem_list[bb] =
196196263Sobrien    alloc_EXPR_LIST (VOIDmode, dest_addr, canon_modify_mem_list[bb]);
1962117395Skan  canon_modify_mem_list[bb] =
196396263Sobrien    alloc_EXPR_LIST (VOIDmode, dest, canon_modify_mem_list[bb]);
196490075Sobrien}
196590075Sobrien
196690075Sobrien/* Record memory modification information for INSN.  We do not actually care
196790075Sobrien   about the memory location(s) that are set, or even how they are set (consider
196890075Sobrien   a CALL_INSN).  We merely need to record which insns modify memory.  */
196990075Sobrien
197050397Sobrienstatic void
1971132718Skanrecord_last_mem_set_info (rtx insn)
197250397Sobrien{
197396263Sobrien  int bb = BLOCK_NUM (insn);
197496263Sobrien
197590075Sobrien  /* load_killed_in_block_p will handle the case of calls clobbering
197690075Sobrien     everything.  */
197796263Sobrien  modify_mem_list[bb] = alloc_INSN_LIST (insn, modify_mem_list[bb]);
197896263Sobrien  bitmap_set_bit (modify_mem_list_set, bb);
197990075Sobrien
1980169689Skan  if (CALL_P (insn))
198190075Sobrien    {
198290075Sobrien      /* Note that traversals of this loop (other than for free-ing)
198390075Sobrien	 will break after encountering a CALL_INSN.  So, there's no
198490075Sobrien	 need to insert a pair of items, as canon_list_insert does.  */
1985117395Skan      canon_modify_mem_list[bb] =
1986117395Skan	alloc_INSN_LIST (insn, canon_modify_mem_list[bb]);
1987169689Skan      bitmap_set_bit (blocks_with_calls, bb);
198890075Sobrien    }
198990075Sobrien  else
199096263Sobrien    note_stores (PATTERN (insn), canon_list_insert, (void*) insn);
199150397Sobrien}
199250397Sobrien
199350397Sobrien/* Called from compute_hash_table via note_stores to handle one
199490075Sobrien   SET or CLOBBER in an insn.  DATA is really the instruction in which
199590075Sobrien   the SET is taking place.  */
199650397Sobrien
199750397Sobrienstatic void
1998132718Skanrecord_last_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, void *data)
199950397Sobrien{
200090075Sobrien  rtx last_set_insn = (rtx) data;
200190075Sobrien
200250397Sobrien  if (GET_CODE (dest) == SUBREG)
200350397Sobrien    dest = SUBREG_REG (dest);
200450397Sobrien
2005169689Skan  if (REG_P (dest))
200650397Sobrien    record_last_reg_set_info (last_set_insn, REGNO (dest));
2007169689Skan  else if (MEM_P (dest)
200850397Sobrien	   /* Ignore pushes, they clobber nothing.  */
200950397Sobrien	   && ! push_operand (dest, GET_MODE (dest)))
201050397Sobrien    record_last_mem_set_info (last_set_insn);
201150397Sobrien}
201250397Sobrien
201350397Sobrien/* Top level function to create an expression or assignment hash table.
201450397Sobrien
201550397Sobrien   Expression entries are placed in the hash table if
201650397Sobrien   - they are of the form (set (pseudo-reg) src),
201750397Sobrien   - src is something we want to perform GCSE on,
201850397Sobrien   - none of the operands are subsequently modified in the block
201950397Sobrien
202050397Sobrien   Assignment entries are placed in the hash table if
202150397Sobrien   - they are of the form (set (pseudo-reg) src),
202250397Sobrien   - src is something we want to perform const/copy propagation on,
202350397Sobrien   - none of the operands or target are subsequently modified in the block
202490075Sobrien
202550397Sobrien   Currently src must be a pseudo-reg or a const_int.
202650397Sobrien
2027117395Skan   TABLE is the table computed.  */
202850397Sobrien
202950397Sobrienstatic void
2030132718Skancompute_hash_table_work (struct hash_table *table)
203150397Sobrien{
203290075Sobrien  unsigned int i;
203350397Sobrien
203450397Sobrien  /* While we compute the hash table we also compute a bit array of which
203550397Sobrien     registers are set in which blocks.
203650397Sobrien     ??? This isn't needed during const/copy propagation, but it's cheap to
203750397Sobrien     compute.  Later.  */
2038117395Skan  sbitmap_vector_zero (reg_set_in_block, last_basic_block);
203950397Sobrien
204090075Sobrien  /* re-Cache any INSN_LIST nodes we have allocated.  */
204190075Sobrien  clear_modify_mem_tables ();
204250397Sobrien  /* Some working arrays used to track first and last set in each block.  */
2043132718Skan  reg_avail_info = gmalloc (max_gcse_regno * sizeof (struct reg_avail_info));
204450397Sobrien
204590075Sobrien  for (i = 0; i < max_gcse_regno; ++i)
2046117395Skan    reg_avail_info[i].last_bb = NULL;
204790075Sobrien
2048117395Skan  FOR_EACH_BB (current_bb)
204950397Sobrien    {
205050397Sobrien      rtx insn;
205190075Sobrien      unsigned int regno;
205250397Sobrien      int in_libcall_block;
205350397Sobrien
205450397Sobrien      /* First pass over the instructions records information used to
205550397Sobrien	 determine when registers and memory are first and last set.
205690075Sobrien	 ??? hard-reg reg_set_in_block computation
205750397Sobrien	 could be moved to compute_sets since they currently don't change.  */
205850397Sobrien
2059169689Skan      FOR_BB_INSNS (current_bb, insn)
206050397Sobrien	{
206190075Sobrien	  if (! INSN_P (insn))
206250397Sobrien	    continue;
206350397Sobrien
2064169689Skan	  if (CALL_P (insn))
206550397Sobrien	    {
206690075Sobrien	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
2067169689Skan		if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
206850397Sobrien		  record_last_reg_set_info (insn, regno);
206990075Sobrien
207090075Sobrien	      mark_call (insn);
207150397Sobrien	    }
207250397Sobrien
207390075Sobrien	  note_stores (PATTERN (insn), record_last_set_info, insn);
207450397Sobrien	}
207550397Sobrien
2076132718Skan      /* Insert implicit sets in the hash table.  */
2077132718Skan      if (table->set_p
2078132718Skan	  && implicit_sets[current_bb->index] != NULL_RTX)
2079132718Skan	hash_scan_set (implicit_sets[current_bb->index],
2080132718Skan		       BB_HEAD (current_bb), table);
2081132718Skan
208250397Sobrien      /* The next pass builds the hash table.  */
2083169689Skan      in_libcall_block = 0;
2084169689Skan      FOR_BB_INSNS (current_bb, insn)
208590075Sobrien	if (INSN_P (insn))
208690075Sobrien	  {
208790075Sobrien	    if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
2088117395Skan	      in_libcall_block = 1;
2089117395Skan	    else if (table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
2090117395Skan	      in_libcall_block = 0;
2091117395Skan	    hash_scan_insn (insn, table, in_libcall_block);
2092117395Skan	    if (!table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
2093117395Skan	      in_libcall_block = 0;
209490075Sobrien	  }
209550397Sobrien    }
209650397Sobrien
209790075Sobrien  free (reg_avail_info);
209890075Sobrien  reg_avail_info = NULL;
209950397Sobrien}
210050397Sobrien
2101117395Skan/* Allocate space for the set/expr hash TABLE.
210250397Sobrien   N_INSNS is the number of instructions in the function.
2103117395Skan   It is used to determine the number of buckets to use.
2104117395Skan   SET_P determines whether set or expression table will
2105117395Skan   be created.  */
210650397Sobrien
210750397Sobrienstatic void
2108132718Skanalloc_hash_table (int n_insns, struct hash_table *table, int set_p)
210950397Sobrien{
211050397Sobrien  int n;
211150397Sobrien
2112117395Skan  table->size = n_insns / 4;
2113117395Skan  if (table->size < 11)
2114117395Skan    table->size = 11;
211590075Sobrien
211650397Sobrien  /* Attempt to maintain efficient use of hash table.
211750397Sobrien     Making it an odd number is simplest for now.
211850397Sobrien     ??? Later take some measurements.  */
2119117395Skan  table->size |= 1;
2120117395Skan  n = table->size * sizeof (struct expr *);
2121132718Skan  table->table = gmalloc (n);
2122117395Skan  table->set_p = set_p;
212350397Sobrien}
212450397Sobrien
2125117395Skan/* Free things allocated by alloc_hash_table.  */
212650397Sobrien
212750397Sobrienstatic void
2128132718Skanfree_hash_table (struct hash_table *table)
212950397Sobrien{
2130117395Skan  free (table->table);
213150397Sobrien}
213250397Sobrien
2133117395Skan/* Compute the hash TABLE for doing copy/const propagation or
2134117395Skan   expression hash table.  */
213550397Sobrien
213650397Sobrienstatic void
2137132718Skancompute_hash_table (struct hash_table *table)
213850397Sobrien{
213950397Sobrien  /* Initialize count of number of entries in hash table.  */
2140117395Skan  table->n_elems = 0;
2141132718Skan  memset (table->table, 0, table->size * sizeof (struct expr *));
214250397Sobrien
2143117395Skan  compute_hash_table_work (table);
214450397Sobrien}
214550397Sobrien
214650397Sobrien/* Expression tracking support.  */
214750397Sobrien
2148132718Skan/* Lookup REGNO in the set TABLE.  The result is a pointer to the
2149132718Skan   table entry, or NULL if not found.  */
215050397Sobrien
215150397Sobrienstatic struct expr *
2152132718Skanlookup_set (unsigned int regno, struct hash_table *table)
215350397Sobrien{
2154117395Skan  unsigned int hash = hash_set (regno, table->size);
215550397Sobrien  struct expr *expr;
215650397Sobrien
2157117395Skan  expr = table->table[hash];
215850397Sobrien
2159132718Skan  while (expr && REGNO (SET_DEST (expr->expr)) != regno)
2160132718Skan    expr = expr->next_same_hash;
216150397Sobrien
216250397Sobrien  return expr;
216350397Sobrien}
216450397Sobrien
216550397Sobrien/* Return the next entry for REGNO in list EXPR.  */
216650397Sobrien
216750397Sobrienstatic struct expr *
2168132718Skannext_set (unsigned int regno, struct expr *expr)
216950397Sobrien{
217050397Sobrien  do
217150397Sobrien    expr = expr->next_same_hash;
217250397Sobrien  while (expr && REGNO (SET_DEST (expr->expr)) != regno);
217390075Sobrien
217450397Sobrien  return expr;
217550397Sobrien}
217650397Sobrien
217796263Sobrien/* Like free_INSN_LIST_list or free_EXPR_LIST_list, except that the node
217896263Sobrien   types may be mixed.  */
217996263Sobrien
218096263Sobrienstatic void
2181132718Skanfree_insn_expr_list_list (rtx *listp)
218296263Sobrien{
218396263Sobrien  rtx list, next;
218496263Sobrien
218596263Sobrien  for (list = *listp; list ; list = next)
218696263Sobrien    {
218796263Sobrien      next = XEXP (list, 1);
218896263Sobrien      if (GET_CODE (list) == EXPR_LIST)
218996263Sobrien	free_EXPR_LIST_node (list);
219096263Sobrien      else
219196263Sobrien	free_INSN_LIST_node (list);
219296263Sobrien    }
219396263Sobrien
219496263Sobrien  *listp = NULL;
219596263Sobrien}
219696263Sobrien
219790075Sobrien/* Clear canon_modify_mem_list and modify_mem_list tables.  */
219890075Sobrienstatic void
2199132718Skanclear_modify_mem_tables (void)
220090075Sobrien{
2201169689Skan  unsigned i;
2202169689Skan  bitmap_iterator bi;
220390075Sobrien
2204169689Skan  EXECUTE_IF_SET_IN_BITMAP (modify_mem_list_set, 0, i, bi)
2205169689Skan    {
2206169689Skan      free_INSN_LIST_list (modify_mem_list + i);
2207169689Skan      free_insn_expr_list_list (canon_modify_mem_list + i);
2208169689Skan    }
220996263Sobrien  bitmap_clear (modify_mem_list_set);
2210169689Skan  bitmap_clear (blocks_with_calls);
221190075Sobrien}
221290075Sobrien
2213169689Skan/* Release memory used by modify_mem_list_set.  */
221490075Sobrien
221590075Sobrienstatic void
2216132718Skanfree_modify_mem_tables (void)
221790075Sobrien{
221890075Sobrien  clear_modify_mem_tables ();
221990075Sobrien  free (modify_mem_list);
222090075Sobrien  free (canon_modify_mem_list);
222190075Sobrien  modify_mem_list = 0;
222290075Sobrien  canon_modify_mem_list = 0;
222390075Sobrien}
222490075Sobrien
222550397Sobrien/* Reset tables used to keep track of what's still available [since the
222650397Sobrien   start of the block].  */
222750397Sobrien
222850397Sobrienstatic void
2229132718Skanreset_opr_set_tables (void)
223050397Sobrien{
223150397Sobrien  /* Maintain a bitmap of which regs have been set since beginning of
223250397Sobrien     the block.  */
223390075Sobrien  CLEAR_REG_SET (reg_set_bitmap);
223490075Sobrien
223550397Sobrien  /* Also keep a record of the last instruction to modify memory.
223650397Sobrien     For now this is very trivial, we only record whether any memory
223750397Sobrien     location has been modified.  */
223890075Sobrien  clear_modify_mem_tables ();
223950397Sobrien}
224050397Sobrien
2241117395Skan/* Return nonzero if the operands of X are not set before INSN in
224250397Sobrien   INSN's basic block.  */
224350397Sobrien
224450397Sobrienstatic int
2245132718Skanoprs_not_set_p (rtx x, rtx insn)
224650397Sobrien{
224790075Sobrien  int i, j;
224850397Sobrien  enum rtx_code code;
224990075Sobrien  const char *fmt;
225050397Sobrien
225150397Sobrien  if (x == 0)
225250397Sobrien    return 1;
225350397Sobrien
225450397Sobrien  code = GET_CODE (x);
225550397Sobrien  switch (code)
225650397Sobrien    {
225750397Sobrien    case PC:
225850397Sobrien    case CC0:
225950397Sobrien    case CONST:
226050397Sobrien    case CONST_INT:
226150397Sobrien    case CONST_DOUBLE:
226296263Sobrien    case CONST_VECTOR:
226350397Sobrien    case SYMBOL_REF:
226450397Sobrien    case LABEL_REF:
226550397Sobrien    case ADDR_VEC:
226650397Sobrien    case ADDR_DIFF_VEC:
226750397Sobrien      return 1;
226850397Sobrien
226950397Sobrien    case MEM:
2270117395Skan      if (load_killed_in_block_p (BLOCK_FOR_INSN (insn),
227190075Sobrien				  INSN_CUID (insn), x, 0))
227250397Sobrien	return 0;
227390075Sobrien      else
227490075Sobrien	return oprs_not_set_p (XEXP (x, 0), insn);
227550397Sobrien
227650397Sobrien    case REG:
227790075Sobrien      return ! REGNO_REG_SET_P (reg_set_bitmap, REGNO (x));
227850397Sobrien
227950397Sobrien    default:
228050397Sobrien      break;
228150397Sobrien    }
228250397Sobrien
228390075Sobrien  for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
228450397Sobrien    {
228550397Sobrien      if (fmt[i] == 'e')
228650397Sobrien	{
228750397Sobrien	  /* If we are about to do the last recursive call
228850397Sobrien	     needed at this level, change it into iteration.
228950397Sobrien	     This function is called enough to be worth it.  */
229050397Sobrien	  if (i == 0)
229190075Sobrien	    return oprs_not_set_p (XEXP (x, i), insn);
229290075Sobrien
229390075Sobrien	  if (! oprs_not_set_p (XEXP (x, i), insn))
229450397Sobrien	    return 0;
229550397Sobrien	}
229650397Sobrien      else if (fmt[i] == 'E')
229790075Sobrien	for (j = 0; j < XVECLEN (x, i); j++)
229890075Sobrien	  if (! oprs_not_set_p (XVECEXP (x, i, j), insn))
229990075Sobrien	    return 0;
230050397Sobrien    }
230150397Sobrien
230250397Sobrien  return 1;
230350397Sobrien}
230450397Sobrien
230550397Sobrien/* Mark things set by a CALL.  */
230650397Sobrien
230750397Sobrienstatic void
2308132718Skanmark_call (rtx insn)
230950397Sobrien{
231090075Sobrien  if (! CONST_OR_PURE_CALL_P (insn))
231190075Sobrien    record_last_mem_set_info (insn);
231250397Sobrien}
231350397Sobrien
231450397Sobrien/* Mark things set by a SET.  */
231550397Sobrien
231650397Sobrienstatic void
2317132718Skanmark_set (rtx pat, rtx insn)
231850397Sobrien{
231950397Sobrien  rtx dest = SET_DEST (pat);
232050397Sobrien
232150397Sobrien  while (GET_CODE (dest) == SUBREG
232250397Sobrien	 || GET_CODE (dest) == ZERO_EXTRACT
232350397Sobrien	 || GET_CODE (dest) == STRICT_LOW_PART)
232450397Sobrien    dest = XEXP (dest, 0);
232550397Sobrien
2326169689Skan  if (REG_P (dest))
232790075Sobrien    SET_REGNO_REG_SET (reg_set_bitmap, REGNO (dest));
2328169689Skan  else if (MEM_P (dest))
232990075Sobrien    record_last_mem_set_info (insn);
233050397Sobrien
233150397Sobrien  if (GET_CODE (SET_SRC (pat)) == CALL)
233252284Sobrien    mark_call (insn);
233350397Sobrien}
233450397Sobrien
233550397Sobrien/* Record things set by a CLOBBER.  */
233650397Sobrien
233750397Sobrienstatic void
2338132718Skanmark_clobber (rtx pat, rtx insn)
233950397Sobrien{
234050397Sobrien  rtx clob = XEXP (pat, 0);
234150397Sobrien
234250397Sobrien  while (GET_CODE (clob) == SUBREG || GET_CODE (clob) == STRICT_LOW_PART)
234350397Sobrien    clob = XEXP (clob, 0);
234450397Sobrien
2345169689Skan  if (REG_P (clob))
234690075Sobrien    SET_REGNO_REG_SET (reg_set_bitmap, REGNO (clob));
234750397Sobrien  else
234890075Sobrien    record_last_mem_set_info (insn);
234950397Sobrien}
235050397Sobrien
235150397Sobrien/* Record things set by INSN.
235250397Sobrien   This data is used by oprs_not_set_p.  */
235350397Sobrien
235450397Sobrienstatic void
2355132718Skanmark_oprs_set (rtx insn)
235650397Sobrien{
235750397Sobrien  rtx pat = PATTERN (insn);
235890075Sobrien  int i;
235950397Sobrien
236050397Sobrien  if (GET_CODE (pat) == SET)
236150397Sobrien    mark_set (pat, insn);
236250397Sobrien  else if (GET_CODE (pat) == PARALLEL)
236390075Sobrien    for (i = 0; i < XVECLEN (pat, 0); i++)
236490075Sobrien      {
236590075Sobrien	rtx x = XVECEXP (pat, 0, i);
236650397Sobrien
236790075Sobrien	if (GET_CODE (x) == SET)
236890075Sobrien	  mark_set (x, insn);
236990075Sobrien	else if (GET_CODE (x) == CLOBBER)
237090075Sobrien	  mark_clobber (x, insn);
237190075Sobrien	else if (GET_CODE (x) == CALL)
237290075Sobrien	  mark_call (insn);
237390075Sobrien      }
237450397Sobrien
237550397Sobrien  else if (GET_CODE (pat) == CLOBBER)
237650397Sobrien    mark_clobber (pat, insn);
237750397Sobrien  else if (GET_CODE (pat) == CALL)
237852284Sobrien    mark_call (insn);
237950397Sobrien}
238052284Sobrien
238150397Sobrien
238250397Sobrien/* Compute copy/constant propagation working variables.  */
238350397Sobrien
238450397Sobrien/* Local properties of assignments.  */
238550397Sobrienstatic sbitmap *cprop_pavloc;
238650397Sobrienstatic sbitmap *cprop_absaltered;
238750397Sobrien
238850397Sobrien/* Global properties of assignments (computed from the local properties).  */
238950397Sobrienstatic sbitmap *cprop_avin;
239050397Sobrienstatic sbitmap *cprop_avout;
239150397Sobrien
239290075Sobrien/* Allocate vars used for copy/const propagation.  N_BLOCKS is the number of
239390075Sobrien   basic blocks.  N_SETS is the number of sets.  */
239450397Sobrien
239550397Sobrienstatic void
2396132718Skanalloc_cprop_mem (int n_blocks, int n_sets)
239750397Sobrien{
239850397Sobrien  cprop_pavloc = sbitmap_vector_alloc (n_blocks, n_sets);
239950397Sobrien  cprop_absaltered = sbitmap_vector_alloc (n_blocks, n_sets);
240050397Sobrien
240150397Sobrien  cprop_avin = sbitmap_vector_alloc (n_blocks, n_sets);
240250397Sobrien  cprop_avout = sbitmap_vector_alloc (n_blocks, n_sets);
240350397Sobrien}
240450397Sobrien
240550397Sobrien/* Free vars used by copy/const propagation.  */
240650397Sobrien
240750397Sobrienstatic void
2408132718Skanfree_cprop_mem (void)
240950397Sobrien{
241090075Sobrien  sbitmap_vector_free (cprop_pavloc);
241190075Sobrien  sbitmap_vector_free (cprop_absaltered);
241290075Sobrien  sbitmap_vector_free (cprop_avin);
241390075Sobrien  sbitmap_vector_free (cprop_avout);
241450397Sobrien}
241550397Sobrien
241690075Sobrien/* For each block, compute whether X is transparent.  X is either an
241790075Sobrien   expression or an assignment [though we don't care which, for this context
241890075Sobrien   an assignment is treated as an expression].  For each block where an
241990075Sobrien   element of X is modified, set (SET_P == 1) or reset (SET_P == 0) the INDX
242090075Sobrien   bit in BMAP.  */
242150397Sobrien
242250397Sobrienstatic void
2423132718Skancompute_transp (rtx x, int indx, sbitmap *bmap, int set_p)
242450397Sobrien{
2425117395Skan  int i, j;
2426117395Skan  basic_block bb;
242750397Sobrien  enum rtx_code code;
242890075Sobrien  reg_set *r;
242990075Sobrien  const char *fmt;
243050397Sobrien
243190075Sobrien  /* repeat is used to turn tail-recursion into iteration since GCC
243290075Sobrien     can't do it when there's no return value.  */
243350397Sobrien repeat:
243450397Sobrien
243550397Sobrien  if (x == 0)
243650397Sobrien    return;
243750397Sobrien
243850397Sobrien  code = GET_CODE (x);
243950397Sobrien  switch (code)
244050397Sobrien    {
244150397Sobrien    case REG:
244250397Sobrien      if (set_p)
244350397Sobrien	{
244490075Sobrien	  if (REGNO (x) < FIRST_PSEUDO_REGISTER)
244590075Sobrien	    {
2446117395Skan	      FOR_EACH_BB (bb)
2447117395Skan		if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x)))
2448117395Skan		  SET_BIT (bmap[bb->index], indx);
244990075Sobrien	    }
245090075Sobrien	  else
245190075Sobrien	    {
245290075Sobrien	      for (r = reg_set_table[REGNO (x)]; r != NULL; r = r->next)
2453169689Skan		SET_BIT (bmap[r->bb_index], indx);
245490075Sobrien	    }
245550397Sobrien	}
245650397Sobrien      else
245750397Sobrien	{
245890075Sobrien	  if (REGNO (x) < FIRST_PSEUDO_REGISTER)
245990075Sobrien	    {
2460117395Skan	      FOR_EACH_BB (bb)
2461117395Skan		if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x)))
2462117395Skan		  RESET_BIT (bmap[bb->index], indx);
246390075Sobrien	    }
246490075Sobrien	  else
246590075Sobrien	    {
246690075Sobrien	      for (r = reg_set_table[REGNO (x)]; r != NULL; r = r->next)
2467169689Skan		RESET_BIT (bmap[r->bb_index], indx);
246890075Sobrien	    }
246950397Sobrien	}
247090075Sobrien
247190075Sobrien      return;
247290075Sobrien
247390075Sobrien    case MEM:
2474169689Skan      if (! MEM_READONLY_P (x))
247590075Sobrien	{
2476169689Skan	  bitmap_iterator bi;
2477169689Skan	  unsigned bb_index;
247890075Sobrien
2479169689Skan	  /* First handle all the blocks with calls.  We don't need to
2480169689Skan	     do any list walking for them.  */
2481169689Skan	  EXECUTE_IF_SET_IN_BITMAP (blocks_with_calls, 0, bb_index, bi)
248290075Sobrien	    {
2483169689Skan	      if (set_p)
2484169689Skan		SET_BIT (bmap[bb_index], indx);
2485169689Skan	      else
2486169689Skan		RESET_BIT (bmap[bb_index], indx);
2487169689Skan	    }
248890075Sobrien
2489169689Skan	    /* Now iterate over the blocks which have memory modifications
2490169689Skan	       but which do not have any calls.  */
2491169689Skan	    EXECUTE_IF_AND_COMPL_IN_BITMAP (modify_mem_list_set,
2492169689Skan					    blocks_with_calls,
2493169689Skan					    0, bb_index, bi)
2494169689Skan	      {
2495169689Skan		rtx list_entry = canon_modify_mem_list[bb_index];
249690075Sobrien
2497169689Skan		while (list_entry)
2498169689Skan		  {
2499169689Skan		    rtx dest, dest_addr;
2500117395Skan
2501169689Skan		    /* LIST_ENTRY must be an INSN of some kind that sets memory.
2502169689Skan		       Examine each hunk of memory that is modified.  */
2503169689Skan
2504169689Skan		    dest = XEXP (list_entry, 0);
2505169689Skan		    list_entry = XEXP (list_entry, 1);
2506169689Skan		    dest_addr = XEXP (list_entry, 0);
2507169689Skan
2508169689Skan		    if (canon_true_dependence (dest, GET_MODE (dest), dest_addr,
2509169689Skan					       x, rtx_addr_varies_p))
2510169689Skan		      {
2511169689Skan			if (set_p)
2512169689Skan			  SET_BIT (bmap[bb_index], indx);
2513169689Skan			else
2514169689Skan			  RESET_BIT (bmap[bb_index], indx);
2515169689Skan			break;
2516169689Skan		      }
2517169689Skan		    list_entry = XEXP (list_entry, 1);
2518169689Skan	          }
2519169689Skan	      }
252090075Sobrien	}
252190075Sobrien
252250397Sobrien      x = XEXP (x, 0);
252350397Sobrien      goto repeat;
252450397Sobrien
252550397Sobrien    case PC:
252650397Sobrien    case CC0: /*FIXME*/
252750397Sobrien    case CONST:
252850397Sobrien    case CONST_INT:
252950397Sobrien    case CONST_DOUBLE:
253096263Sobrien    case CONST_VECTOR:
253150397Sobrien    case SYMBOL_REF:
253250397Sobrien    case LABEL_REF:
253350397Sobrien    case ADDR_VEC:
253450397Sobrien    case ADDR_DIFF_VEC:
253550397Sobrien      return;
253650397Sobrien
253750397Sobrien    default:
253850397Sobrien      break;
253950397Sobrien    }
254050397Sobrien
254190075Sobrien  for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
254250397Sobrien    {
254350397Sobrien      if (fmt[i] == 'e')
254450397Sobrien	{
254550397Sobrien	  /* If we are about to do the last recursive call
254650397Sobrien	     needed at this level, change it into iteration.
254750397Sobrien	     This function is called enough to be worth it.  */
254850397Sobrien	  if (i == 0)
254950397Sobrien	    {
255090075Sobrien	      x = XEXP (x, i);
255150397Sobrien	      goto repeat;
255250397Sobrien	    }
255390075Sobrien
255490075Sobrien	  compute_transp (XEXP (x, i), indx, bmap, set_p);
255550397Sobrien	}
255650397Sobrien      else if (fmt[i] == 'E')
255790075Sobrien	for (j = 0; j < XVECLEN (x, i); j++)
255890075Sobrien	  compute_transp (XVECEXP (x, i, j), indx, bmap, set_p);
255950397Sobrien    }
256050397Sobrien}
256150397Sobrien
256250397Sobrien/* Top level routine to do the dataflow analysis needed by copy/const
256350397Sobrien   propagation.  */
256450397Sobrien
256550397Sobrienstatic void
2566132718Skancompute_cprop_data (void)
256750397Sobrien{
2568117395Skan  compute_local_properties (cprop_absaltered, cprop_pavloc, NULL, &set_hash_table);
256990075Sobrien  compute_available (cprop_pavloc, cprop_absaltered,
257090075Sobrien		     cprop_avout, cprop_avin);
257150397Sobrien}
257250397Sobrien
257350397Sobrien/* Copy/constant propagation.  */
257450397Sobrien
257550397Sobrien/* Maximum number of register uses in an insn that we handle.  */
257650397Sobrien#define MAX_USES 8
257750397Sobrien
257850397Sobrien/* Table of uses found in an insn.
257950397Sobrien   Allocated statically to avoid alloc/free complexity and overhead.  */
258050397Sobrienstatic struct reg_use reg_use_table[MAX_USES];
258150397Sobrien
258250397Sobrien/* Index into `reg_use_table' while building it.  */
258350397Sobrienstatic int reg_use_count;
258450397Sobrien
258590075Sobrien/* Set up a list of register numbers used in INSN.  The found uses are stored
258690075Sobrien   in `reg_use_table'.  `reg_use_count' is initialized to zero before entry,
258790075Sobrien   and contains the number of uses in the table upon exit.
258850397Sobrien
258990075Sobrien   ??? If a register appears multiple times we will record it multiple times.
259090075Sobrien   This doesn't hurt anything but it will slow things down.  */
259150397Sobrien
259250397Sobrienstatic void
2593132718Skanfind_used_regs (rtx *xptr, void *data ATTRIBUTE_UNUSED)
259450397Sobrien{
259590075Sobrien  int i, j;
259650397Sobrien  enum rtx_code code;
259790075Sobrien  const char *fmt;
259890075Sobrien  rtx x = *xptr;
259950397Sobrien
260090075Sobrien  /* repeat is used to turn tail-recursion into iteration since GCC
260190075Sobrien     can't do it when there's no return value.  */
260250397Sobrien repeat:
260350397Sobrien  if (x == 0)
260450397Sobrien    return;
260550397Sobrien
260650397Sobrien  code = GET_CODE (x);
260790075Sobrien  if (REG_P (x))
260850397Sobrien    {
260950397Sobrien      if (reg_use_count == MAX_USES)
261050397Sobrien	return;
261190075Sobrien
261250397Sobrien      reg_use_table[reg_use_count].reg_rtx = x;
261350397Sobrien      reg_use_count++;
261450397Sobrien    }
261550397Sobrien
261650397Sobrien  /* Recursively scan the operands of this expression.  */
261750397Sobrien
261890075Sobrien  for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
261950397Sobrien    {
262050397Sobrien      if (fmt[i] == 'e')
262150397Sobrien	{
262250397Sobrien	  /* If we are about to do the last recursive call
262350397Sobrien	     needed at this level, change it into iteration.
262450397Sobrien	     This function is called enough to be worth it.  */
262550397Sobrien	  if (i == 0)
262650397Sobrien	    {
262750397Sobrien	      x = XEXP (x, 0);
262850397Sobrien	      goto repeat;
262950397Sobrien	    }
263090075Sobrien
263190075Sobrien	  find_used_regs (&XEXP (x, i), data);
263250397Sobrien	}
263350397Sobrien      else if (fmt[i] == 'E')
263490075Sobrien	for (j = 0; j < XVECLEN (x, i); j++)
263590075Sobrien	  find_used_regs (&XVECEXP (x, i, j), data);
263650397Sobrien    }
263750397Sobrien}
263850397Sobrien
263950397Sobrien/* Try to replace all non-SET_DEST occurrences of FROM in INSN with TO.
2640117395Skan   Returns nonzero is successful.  */
264150397Sobrien
264250397Sobrienstatic int
2643132718Skantry_replace_reg (rtx from, rtx to, rtx insn)
264450397Sobrien{
264590075Sobrien  rtx note = find_reg_equal_equiv_note (insn);
264690075Sobrien  rtx src = 0;
264790075Sobrien  int success = 0;
264890075Sobrien  rtx set = single_set (insn);
264952284Sobrien
2650117395Skan  validate_replace_src_group (from, to, insn);
2651117395Skan  if (num_changes_pending () && apply_change_group ())
2652117395Skan    success = 1;
265390075Sobrien
2654117395Skan  /* Try to simplify SET_SRC if we have substituted a constant.  */
2655117395Skan  if (success && set && CONSTANT_P (to))
265690075Sobrien    {
2657117395Skan      src = simplify_rtx (SET_SRC (set));
2658117395Skan
2659117395Skan      if (src)
2660117395Skan	validate_change (insn, &SET_SRC (set), src, 0);
2661117395Skan    }
2662117395Skan
2663169689Skan  /* If there is already a REG_EQUAL note, update the expression in it
2664169689Skan     with our replacement.  */
2665169689Skan  if (note != 0 && REG_NOTE_KIND (note) == REG_EQUAL)
2666132718Skan    XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), from, to);
2667132718Skan
2668117395Skan  if (!success && set && reg_mentioned_p (from, SET_SRC (set)))
2669117395Skan    {
2670117395Skan      /* If above failed and this is a single set, try to simplify the source of
2671117395Skan	 the set given our substitution.  We could perhaps try this for multiple
2672117395Skan	 SETs, but it probably won't buy us anything.  */
267390075Sobrien      src = simplify_replace_rtx (SET_SRC (set), from, to);
267490075Sobrien
267590075Sobrien      if (!rtx_equal_p (src, SET_SRC (set))
267690075Sobrien	  && validate_change (insn, &SET_SRC (set), src, 0))
267790075Sobrien	success = 1;
2678117395Skan
2679119256Skan      /* If we've failed to do replacement, have a single SET, don't already
2680119256Skan	 have a note, and have no special SET, add a REG_EQUAL note to not
2681119256Skan	 lose information.  */
2682119256Skan      if (!success && note == 0 && set != 0
2683169689Skan	  && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
2684169689Skan	  && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
2685117395Skan	note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src));
268690075Sobrien    }
268790075Sobrien
268890075Sobrien  /* REG_EQUAL may get simplified into register.
268990075Sobrien     We don't allow that. Remove that note. This code ought
2690132718Skan     not to happen, because previous code ought to synthesize
269190075Sobrien     reg-reg move, but be on the safe side.  */
2692169689Skan  if (note && REG_NOTE_KIND (note) == REG_EQUAL && REG_P (XEXP (note, 0)))
269390075Sobrien    remove_note (insn, note);
269490075Sobrien
269590075Sobrien  return success;
269650397Sobrien}
269750397Sobrien
269890075Sobrien/* Find a set of REGNOs that are available on entry to INSN's block.  Returns
269990075Sobrien   NULL no such set is found.  */
270050397Sobrien
270150397Sobrienstatic struct expr *
2702132718Skanfind_avail_set (int regno, rtx insn)
270350397Sobrien{
270490075Sobrien  /* SET1 contains the last set found that can be returned to the caller for
270590075Sobrien     use in a substitution.  */
270690075Sobrien  struct expr *set1 = 0;
2707117395Skan
270890075Sobrien  /* Loops are not possible here.  To get a loop we would need two sets
2709169689Skan     available at the start of the block containing INSN.  i.e. we would
271090075Sobrien     need two sets like this available at the start of the block:
271150397Sobrien
271290075Sobrien       (set (reg X) (reg Y))
271390075Sobrien       (set (reg Y) (reg X))
271490075Sobrien
271590075Sobrien     This can not happen since the set of (reg Y) would have killed the
271690075Sobrien     set of (reg X) making it unavailable at the start of this block.  */
271790075Sobrien  while (1)
271850397Sobrien    {
271990075Sobrien      rtx src;
2720132718Skan      struct expr *set = lookup_set (regno, &set_hash_table);
272190075Sobrien
272290075Sobrien      /* Find a set that is available at the start of the block
272390075Sobrien	 which contains INSN.  */
272490075Sobrien      while (set)
272590075Sobrien	{
272690075Sobrien	  if (TEST_BIT (cprop_avin[BLOCK_NUM (insn)], set->bitmap_index))
272790075Sobrien	    break;
272890075Sobrien	  set = next_set (regno, set);
272990075Sobrien	}
273090075Sobrien
273190075Sobrien      /* If no available set was found we've reached the end of the
273290075Sobrien	 (possibly empty) copy chain.  */
273390075Sobrien      if (set == 0)
2734117395Skan	break;
273590075Sobrien
2736169689Skan      gcc_assert (GET_CODE (set->expr) == SET);
273790075Sobrien
273890075Sobrien      src = SET_SRC (set->expr);
273990075Sobrien
274090075Sobrien      /* We know the set is available.
274190075Sobrien	 Now check that SRC is ANTLOC (i.e. none of the source operands
2742117395Skan	 have changed since the start of the block).
274390075Sobrien
274490075Sobrien         If the source operand changed, we may still use it for the next
274590075Sobrien         iteration of this loop, but we may not use it for substitutions.  */
274690075Sobrien
2747132718Skan      if (gcse_constant_p (src) || oprs_not_set_p (src, insn))
274890075Sobrien	set1 = set;
274990075Sobrien
275090075Sobrien      /* If the source of the set is anything except a register, then
275190075Sobrien	 we have reached the end of the copy chain.  */
2752169689Skan      if (! REG_P (src))
275350397Sobrien	break;
275490075Sobrien
2755169689Skan      /* Follow the copy chain, i.e. start another iteration of the loop
275690075Sobrien	 and see if we have an available copy into SRC.  */
275790075Sobrien      regno = REGNO (src);
275850397Sobrien    }
275950397Sobrien
276090075Sobrien  /* SET1 holds the last set that was available and anticipatable at
276190075Sobrien     INSN.  */
276290075Sobrien  return set1;
276350397Sobrien}
276450397Sobrien
276590075Sobrien/* Subroutine of cprop_insn that tries to propagate constants into
2766117395Skan   JUMP_INSNS.  JUMP must be a conditional jump.  If SETCC is non-NULL
2767132718Skan   it is the instruction that immediately precedes JUMP, and must be a
2768117395Skan   single SET of a register.  FROM is what we will try to replace,
2769117395Skan   SRC is the constant we will try to substitute for it.  Returns nonzero
2770117395Skan   if a change was made.  */
277190075Sobrien
277290075Sobrienstatic int
2773132718Skancprop_jump (basic_block bb, rtx setcc, rtx jump, rtx from, rtx src)
277490075Sobrien{
2775132718Skan  rtx new, set_src, note_src;
2776117395Skan  rtx set = pc_set (jump);
2777132718Skan  rtx note = find_reg_equal_equiv_note (jump);
277890075Sobrien
2779132718Skan  if (note)
2780132718Skan    {
2781132718Skan      note_src = XEXP (note, 0);
2782132718Skan      if (GET_CODE (note_src) == EXPR_LIST)
2783132718Skan	note_src = NULL_RTX;
2784132718Skan    }
2785132718Skan  else note_src = NULL_RTX;
2786132718Skan
2787132718Skan  /* Prefer REG_EQUAL notes except those containing EXPR_LISTs.  */
2788132718Skan  set_src = note_src ? note_src : SET_SRC (set);
2789132718Skan
2790132718Skan  /* First substitute the SETCC condition into the JUMP instruction,
2791132718Skan     then substitute that given values into this expanded JUMP.  */
2792132718Skan  if (setcc != NULL_RTX
2793117395Skan      && !modified_between_p (from, setcc, jump)
2794117395Skan      && !modified_between_p (src, setcc, jump))
2795117395Skan    {
2796132718Skan      rtx setcc_src;
2797117395Skan      rtx setcc_set = single_set (setcc);
2798132718Skan      rtx setcc_note = find_reg_equal_equiv_note (setcc);
2799132718Skan      setcc_src = (setcc_note && GET_CODE (XEXP (setcc_note, 0)) != EXPR_LIST)
2800132718Skan		? XEXP (setcc_note, 0) : SET_SRC (setcc_set);
2801132718Skan      set_src = simplify_replace_rtx (set_src, SET_DEST (setcc_set),
2802132718Skan				      setcc_src);
2803117395Skan    }
2804117395Skan  else
2805132718Skan    setcc = NULL_RTX;
2806117395Skan
2807132718Skan  new = simplify_replace_rtx (set_src, from, src);
2808117395Skan
2809132718Skan  /* If no simplification can be made, then try the next register.  */
2810132718Skan  if (rtx_equal_p (new, SET_SRC (set)))
281190075Sobrien    return 0;
2812117395Skan
281390075Sobrien  /* If this is now a no-op delete it, otherwise this must be a valid insn.  */
281490075Sobrien  if (new == pc_rtx)
2815117395Skan    delete_insn (jump);
281690075Sobrien  else
281790075Sobrien    {
2818117395Skan      /* Ensure the value computed inside the jump insn to be equivalent
2819117395Skan         to one computed by setcc.  */
2820132718Skan      if (setcc && modified_in_p (new, setcc))
282190075Sobrien	return 0;
2822117395Skan      if (! validate_change (jump, &SET_SRC (set), new, 0))
2823132718Skan	{
2824132718Skan	  /* When (some) constants are not valid in a comparison, and there
2825132718Skan	     are two registers to be replaced by constants before the entire
2826132718Skan	     comparison can be folded into a constant, we need to keep
2827132718Skan	     intermediate information in REG_EQUAL notes.  For targets with
2828132718Skan	     separate compare insns, such notes are added by try_replace_reg.
2829132718Skan	     When we have a combined compare-and-branch instruction, however,
2830132718Skan	     we need to attach a note to the branch itself to make this
2831132718Skan	     optimization work.  */
283290075Sobrien
2833132718Skan	  if (!rtx_equal_p (new, note_src))
2834132718Skan	    set_unique_reg_note (jump, REG_EQUAL, copy_rtx (new));
2835132718Skan	  return 0;
2836132718Skan	}
2837132718Skan
2838132718Skan      /* Remove REG_EQUAL note after simplification.  */
2839132718Skan      if (note_src)
2840132718Skan	remove_note (jump, note);
2841132718Skan
284290075Sobrien      /* If this has turned into an unconditional jump,
284390075Sobrien	 then put a barrier after it so that the unreachable
284490075Sobrien	 code will be deleted.  */
284590075Sobrien      if (GET_CODE (SET_SRC (set)) == LABEL_REF)
2846117395Skan	emit_barrier_after (jump);
284790075Sobrien     }
284890075Sobrien
2849117395Skan#ifdef HAVE_cc0
2850117395Skan  /* Delete the cc0 setter.  */
2851117395Skan  if (setcc != NULL && CC0_P (SET_DEST (single_set (setcc))))
2852117395Skan    delete_insn (setcc);
2853117395Skan#endif
2854117395Skan
285590075Sobrien  run_jump_opt_after_gcse = 1;
285690075Sobrien
2857169689Skan  global_const_prop_count++;
2858169689Skan  if (dump_file != NULL)
285990075Sobrien    {
2860169689Skan      fprintf (dump_file,
2861169689Skan	       "GLOBAL CONST-PROP: Replacing reg %d in jump_insn %d with constant ",
2862117395Skan	       REGNO (from), INSN_UID (jump));
2863169689Skan      print_rtl (dump_file, src);
2864169689Skan      fprintf (dump_file, "\n");
286590075Sobrien    }
286690075Sobrien  purge_dead_edges (bb);
286790075Sobrien
286890075Sobrien  return 1;
286990075Sobrien}
287090075Sobrien
2871117395Skanstatic bool
2872169689Skanconstprop_register (rtx insn, rtx from, rtx to, bool alter_jumps)
287390075Sobrien{
2874117395Skan  rtx sset;
287590075Sobrien
2876117395Skan  /* Check for reg or cc0 setting instructions followed by
2877117395Skan     conditional branch instructions first.  */
2878117395Skan  if (alter_jumps
2879117395Skan      && (sset = single_set (insn)) != NULL
2880117395Skan      && NEXT_INSN (insn)
2881117395Skan      && any_condjump_p (NEXT_INSN (insn)) && onlyjump_p (NEXT_INSN (insn)))
2882117395Skan    {
2883117395Skan      rtx dest = SET_DEST (sset);
2884117395Skan      if ((REG_P (dest) || CC0_P (dest))
2885117395Skan	  && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn), from, to))
2886117395Skan	return 1;
2887117395Skan    }
288890075Sobrien
2889117395Skan  /* Handle normal insns next.  */
2890169689Skan  if (NONJUMP_INSN_P (insn)
2891117395Skan      && try_replace_reg (from, to, insn))
2892117395Skan    return 1;
289390075Sobrien
2894117395Skan  /* Try to propagate a CONST_INT into a conditional jump.
2895117395Skan     We're pretty specific about what we will handle in this
2896117395Skan     code, we can extend this as necessary over time.
2897117395Skan
2898117395Skan     Right now the insn in question must look like
2899117395Skan     (set (pc) (if_then_else ...))  */
2900117395Skan  else if (alter_jumps && any_condjump_p (insn) && onlyjump_p (insn))
2901117395Skan    return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, to);
2902117395Skan  return 0;
290390075Sobrien}
2904117395Skan
290550397Sobrien/* Perform constant and copy propagation on INSN.
2906117395Skan   The result is nonzero if a change was made.  */
290750397Sobrien
290850397Sobrienstatic int
2909132718Skancprop_insn (rtx insn, int alter_jumps)
291050397Sobrien{
291150397Sobrien  struct reg_use *reg_used;
291250397Sobrien  int changed = 0;
291390075Sobrien  rtx note;
291450397Sobrien
291590075Sobrien  if (!INSN_P (insn))
291650397Sobrien    return 0;
291750397Sobrien
291850397Sobrien  reg_use_count = 0;
291990075Sobrien  note_uses (&PATTERN (insn), find_used_regs, NULL);
2920117395Skan
292190075Sobrien  note = find_reg_equal_equiv_note (insn);
292250397Sobrien
292390075Sobrien  /* We may win even when propagating constants into notes.  */
292490075Sobrien  if (note)
292590075Sobrien    find_used_regs (&XEXP (note, 0), NULL);
292690075Sobrien
292790075Sobrien  for (reg_used = &reg_use_table[0]; reg_use_count > 0;
292890075Sobrien       reg_used++, reg_use_count--)
292950397Sobrien    {
293090075Sobrien      unsigned int regno = REGNO (reg_used->reg_rtx);
293150397Sobrien      rtx pat, src;
293250397Sobrien      struct expr *set;
293350397Sobrien
293450397Sobrien      /* Ignore registers created by GCSE.
293590075Sobrien	 We do this because ...  */
293650397Sobrien      if (regno >= max_gcse_regno)
293750397Sobrien	continue;
293850397Sobrien
293950397Sobrien      /* If the register has already been set in this block, there's
294050397Sobrien	 nothing we can do.  */
294150397Sobrien      if (! oprs_not_set_p (reg_used->reg_rtx, insn))
294250397Sobrien	continue;
294350397Sobrien
294450397Sobrien      /* Find an assignment that sets reg_used and is available
294550397Sobrien	 at the start of the block.  */
294650397Sobrien      set = find_avail_set (regno, insn);
294750397Sobrien      if (! set)
294850397Sobrien	continue;
2949117395Skan
295050397Sobrien      pat = set->expr;
295150397Sobrien      /* ??? We might be able to handle PARALLELs.  Later.  */
2952169689Skan      gcc_assert (GET_CODE (pat) == SET);
295390075Sobrien
295450397Sobrien      src = SET_SRC (pat);
295550397Sobrien
295652284Sobrien      /* Constant propagation.  */
2957132718Skan      if (gcse_constant_p (src))
295850397Sobrien	{
2959117395Skan          if (constprop_register (insn, reg_used->reg_rtx, src, alter_jumps))
296050397Sobrien	    {
296150397Sobrien	      changed = 1;
2962169689Skan	      global_const_prop_count++;
2963169689Skan	      if (dump_file != NULL)
296450397Sobrien		{
2965169689Skan		  fprintf (dump_file, "GLOBAL CONST-PROP: Replacing reg %d in ", regno);
2966169689Skan		  fprintf (dump_file, "insn %d with constant ", INSN_UID (insn));
2967169689Skan		  print_rtl (dump_file, src);
2968169689Skan		  fprintf (dump_file, "\n");
296950397Sobrien		}
2970132718Skan	      if (INSN_DELETED_P (insn))
2971132718Skan		return 1;
297250397Sobrien	    }
297350397Sobrien	}
2974169689Skan      else if (REG_P (src)
297550397Sobrien	       && REGNO (src) >= FIRST_PSEUDO_REGISTER
297650397Sobrien	       && REGNO (src) != regno)
297750397Sobrien	{
297890075Sobrien	  if (try_replace_reg (reg_used->reg_rtx, src, insn))
297950397Sobrien	    {
298090075Sobrien	      changed = 1;
2981169689Skan	      global_copy_prop_count++;
2982169689Skan	      if (dump_file != NULL)
298350397Sobrien		{
2984169689Skan		  fprintf (dump_file, "GLOBAL COPY-PROP: Replacing reg %d in insn %d",
298590075Sobrien			   regno, INSN_UID (insn));
2986169689Skan		  fprintf (dump_file, " with reg %d\n", REGNO (src));
298790075Sobrien		}
298850397Sobrien
298990075Sobrien	      /* The original insn setting reg_used may or may not now be
299090075Sobrien		 deletable.  We leave the deletion to flow.  */
299190075Sobrien	      /* FIXME: If it turns out that the insn isn't deletable,
299290075Sobrien		 then we may have unnecessarily extended register lifetimes
299390075Sobrien		 and made things worse.  */
299450397Sobrien	    }
299550397Sobrien	}
299650397Sobrien    }
299750397Sobrien
299850397Sobrien  return changed;
299950397Sobrien}
300050397Sobrien
3001117395Skan/* Like find_used_regs, but avoid recording uses that appear in
3002117395Skan   input-output contexts such as zero_extract or pre_dec.  This
3003117395Skan   restricts the cases we consider to those for which local cprop
3004117395Skan   can legitimately make replacements.  */
3005117395Skan
3006117395Skanstatic void
3007132718Skanlocal_cprop_find_used_regs (rtx *xptr, void *data)
3008117395Skan{
3009117395Skan  rtx x = *xptr;
3010117395Skan
3011117395Skan  if (x == 0)
3012117395Skan    return;
3013117395Skan
3014117395Skan  switch (GET_CODE (x))
3015117395Skan    {
3016117395Skan    case ZERO_EXTRACT:
3017117395Skan    case SIGN_EXTRACT:
3018117395Skan    case STRICT_LOW_PART:
3019117395Skan      return;
3020117395Skan
3021117395Skan    case PRE_DEC:
3022117395Skan    case PRE_INC:
3023117395Skan    case POST_DEC:
3024117395Skan    case POST_INC:
3025117395Skan    case PRE_MODIFY:
3026117395Skan    case POST_MODIFY:
3027117395Skan      /* Can only legitimately appear this early in the context of
3028117395Skan	 stack pushes for function arguments, but handle all of the
3029117395Skan	 codes nonetheless.  */
3030117395Skan      return;
3031117395Skan
3032117395Skan    case SUBREG:
3033117395Skan      /* Setting a subreg of a register larger than word_mode leaves
3034117395Skan	 the non-written words unchanged.  */
3035117395Skan      if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) > BITS_PER_WORD)
3036117395Skan	return;
3037117395Skan      break;
3038117395Skan
3039117395Skan    default:
3040117395Skan      break;
3041117395Skan    }
3042117395Skan
3043117395Skan  find_used_regs (xptr, data);
3044117395Skan}
3045132718Skan
3046117395Skan/* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall;
3047117395Skan   their REG_EQUAL notes need updating.  */
3048117395Skan
3049117395Skanstatic bool
3050169689Skando_local_cprop (rtx x, rtx insn, bool alter_jumps, rtx *libcall_sp)
3051117395Skan{
3052117395Skan  rtx newreg = NULL, newcnst = NULL;
3053117395Skan
3054117395Skan  /* Rule out USE instructions and ASM statements as we don't want to
3055117395Skan     change the hard registers mentioned.  */
3056169689Skan  if (REG_P (x)
3057117395Skan      && (REGNO (x) >= FIRST_PSEUDO_REGISTER
3058117395Skan          || (GET_CODE (PATTERN (insn)) != USE
3059117395Skan	      && asm_noperands (PATTERN (insn)) < 0)))
3060117395Skan    {
3061117395Skan      cselib_val *val = cselib_lookup (x, GET_MODE (x), 0);
3062117395Skan      struct elt_loc_list *l;
3063117395Skan
3064117395Skan      if (!val)
3065117395Skan	return false;
3066117395Skan      for (l = val->locs; l; l = l->next)
3067117395Skan	{
3068117395Skan	  rtx this_rtx = l->loc;
3069117395Skan	  rtx note;
3070117395Skan
3071146895Skan	  /* Don't CSE non-constant values out of libcall blocks.  */
3072146895Skan	  if (l->in_libcall && ! CONSTANT_P (this_rtx))
3073117395Skan	    continue;
3074117395Skan
3075132718Skan	  if (gcse_constant_p (this_rtx))
3076117395Skan	    newcnst = this_rtx;
3077117395Skan	  if (REG_P (this_rtx) && REGNO (this_rtx) >= FIRST_PSEUDO_REGISTER
3078117395Skan	      /* Don't copy propagate if it has attached REG_EQUIV note.
3079117395Skan		 At this point this only function parameters should have
3080117395Skan		 REG_EQUIV notes and if the argument slot is used somewhere
3081117395Skan		 explicitly, it means address of parameter has been taken,
3082117395Skan		 so we should not extend the lifetime of the pseudo.  */
3083117395Skan	      && (!(note = find_reg_note (l->setting_insn, REG_EQUIV, NULL_RTX))
3084169689Skan		  || ! MEM_P (XEXP (note, 0))))
3085117395Skan	    newreg = this_rtx;
3086117395Skan	}
3087117395Skan      if (newcnst && constprop_register (insn, x, newcnst, alter_jumps))
3088117395Skan	{
3089117395Skan	  /* If we find a case where we can't fix the retval REG_EQUAL notes
3090132718Skan	     match the new register, we either have to abandon this replacement
3091117395Skan	     or fix delete_trivially_dead_insns to preserve the setting insn,
3092117395Skan	     or make it delete the REG_EUAQL note, and fix up all passes that
3093117395Skan	     require the REG_EQUAL note there.  */
3094169689Skan	  bool adjusted;
3095169689Skan
3096169689Skan	  adjusted = adjust_libcall_notes (x, newcnst, insn, libcall_sp);
3097169689Skan	  gcc_assert (adjusted);
3098169689Skan
3099169689Skan	  if (dump_file != NULL)
3100117395Skan	    {
3101169689Skan	      fprintf (dump_file, "LOCAL CONST-PROP: Replacing reg %d in ",
3102117395Skan		       REGNO (x));
3103169689Skan	      fprintf (dump_file, "insn %d with constant ",
3104117395Skan		       INSN_UID (insn));
3105169689Skan	      print_rtl (dump_file, newcnst);
3106169689Skan	      fprintf (dump_file, "\n");
3107117395Skan	    }
3108169689Skan	  local_const_prop_count++;
3109117395Skan	  return true;
3110117395Skan	}
3111117395Skan      else if (newreg && newreg != x && try_replace_reg (x, newreg, insn))
3112117395Skan	{
3113117395Skan	  adjust_libcall_notes (x, newreg, insn, libcall_sp);
3114169689Skan	  if (dump_file != NULL)
3115117395Skan	    {
3116169689Skan	      fprintf (dump_file,
3117117395Skan		       "LOCAL COPY-PROP: Replacing reg %d in insn %d",
3118117395Skan		       REGNO (x), INSN_UID (insn));
3119169689Skan	      fprintf (dump_file, " with reg %d\n", REGNO (newreg));
3120117395Skan	    }
3121169689Skan	  local_copy_prop_count++;
3122117395Skan	  return true;
3123117395Skan	}
3124117395Skan    }
3125117395Skan  return false;
3126117395Skan}
3127117395Skan
3128117395Skan/* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall;
3129117395Skan   their REG_EQUAL notes need updating to reflect that OLDREG has been
3130117395Skan   replaced with NEWVAL in INSN.  Return true if all substitutions could
3131117395Skan   be made.  */
3132117395Skanstatic bool
3133132718Skanadjust_libcall_notes (rtx oldreg, rtx newval, rtx insn, rtx *libcall_sp)
3134117395Skan{
3135117395Skan  rtx end;
3136117395Skan
3137117395Skan  while ((end = *libcall_sp++))
3138117395Skan    {
3139117395Skan      rtx note = find_reg_equal_equiv_note (end);
3140117395Skan
3141117395Skan      if (! note)
3142117395Skan	continue;
3143117395Skan
3144117395Skan      if (REG_P (newval))
3145117395Skan	{
3146117395Skan	  if (reg_set_between_p (newval, PREV_INSN (insn), end))
3147117395Skan	    {
3148117395Skan	      do
3149117395Skan		{
3150117395Skan		  note = find_reg_equal_equiv_note (end);
3151117395Skan		  if (! note)
3152117395Skan		    continue;
3153117395Skan		  if (reg_mentioned_p (newval, XEXP (note, 0)))
3154117395Skan		    return false;
3155117395Skan		}
3156117395Skan	      while ((end = *libcall_sp++));
3157117395Skan	      return true;
3158117395Skan	    }
3159117395Skan	}
3160146895Skan      XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), oldreg, newval);
3161117395Skan      insn = end;
3162117395Skan    }
3163117395Skan  return true;
3164117395Skan}
3165117395Skan
3166117395Skan#define MAX_NESTED_LIBCALLS 9
3167117395Skan
3168169689Skan/* Do local const/copy propagation (i.e. within each basic block).
3169169689Skan   If ALTER_JUMPS is true, allow propagating into jump insns, which
3170169689Skan   could modify the CFG.  */
3171169689Skan
3172117395Skanstatic void
3173169689Skanlocal_cprop_pass (bool alter_jumps)
3174117395Skan{
3175169689Skan  basic_block bb;
3176117395Skan  rtx insn;
3177117395Skan  struct reg_use *reg_used;
3178117395Skan  rtx libcall_stack[MAX_NESTED_LIBCALLS + 1], *libcall_sp;
3179117395Skan  bool changed = false;
3180117395Skan
3181169689Skan  cselib_init (false);
3182117395Skan  libcall_sp = &libcall_stack[MAX_NESTED_LIBCALLS];
3183117395Skan  *libcall_sp = 0;
3184169689Skan  FOR_EACH_BB (bb)
3185117395Skan    {
3186169689Skan      FOR_BB_INSNS (bb, insn)
3187117395Skan	{
3188169689Skan	  if (INSN_P (insn))
3189169689Skan	    {
3190169689Skan	      rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
3191117395Skan
3192117395Skan	      if (note)
3193169689Skan		{
3194169689Skan		  gcc_assert (libcall_sp != libcall_stack);
3195169689Skan		  *--libcall_sp = XEXP (note, 0);
3196169689Skan		}
3197169689Skan	      note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
3198169689Skan	      if (note)
3199169689Skan		libcall_sp++;
3200169689Skan	      note = find_reg_equal_equiv_note (insn);
3201169689Skan	      do
3202169689Skan		{
3203169689Skan		  reg_use_count = 0;
3204169689Skan		  note_uses (&PATTERN (insn), local_cprop_find_used_regs,
3205169689Skan			     NULL);
3206169689Skan		  if (note)
3207169689Skan		    local_cprop_find_used_regs (&XEXP (note, 0), NULL);
3208117395Skan
3209169689Skan		  for (reg_used = &reg_use_table[0]; reg_use_count > 0;
3210169689Skan		       reg_used++, reg_use_count--)
3211169689Skan		    if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
3212169689Skan			libcall_sp))
3213169689Skan		      {
3214169689Skan			changed = true;
3215169689Skan			break;
3216169689Skan		      }
3217169689Skan		  if (INSN_DELETED_P (insn))
3218117395Skan		    break;
3219169689Skan		}
3220169689Skan	      while (reg_use_count);
3221117395Skan	    }
3222169689Skan	  cselib_process_insn (insn);
3223117395Skan	}
3224169689Skan
3225169689Skan      /* Forget everything at the end of a basic block.  Make sure we are
3226169689Skan	 not inside a libcall, they should never cross basic blocks.  */
3227169689Skan      cselib_clear_table ();
3228169689Skan      gcc_assert (libcall_sp == &libcall_stack[MAX_NESTED_LIBCALLS]);
3229117395Skan    }
3230169689Skan
3231117395Skan  cselib_finish ();
3232169689Skan
3233117395Skan  /* Global analysis may get into infinite loops for unreachable blocks.  */
3234117395Skan  if (changed && alter_jumps)
3235117395Skan    {
3236117395Skan      delete_unreachable_blocks ();
3237117395Skan      free_reg_set_mem ();
3238117395Skan      alloc_reg_set_mem (max_reg_num ());
3239169689Skan      compute_sets ();
3240117395Skan    }
3241117395Skan}
3242117395Skan
324390075Sobrien/* Forward propagate copies.  This includes copies and constants.  Return
3244117395Skan   nonzero if a change was made.  */
324550397Sobrien
324650397Sobrienstatic int
3247132718Skancprop (int alter_jumps)
324850397Sobrien{
3249117395Skan  int changed;
3250117395Skan  basic_block bb;
325150397Sobrien  rtx insn;
325250397Sobrien
325350397Sobrien  /* Note we start at block 1.  */
3254117395Skan  if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
3255117395Skan    {
3256169689Skan      if (dump_file != NULL)
3257169689Skan	fprintf (dump_file, "\n");
3258117395Skan      return 0;
3259117395Skan    }
326050397Sobrien
326150397Sobrien  changed = 0;
3262117395Skan  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR, next_bb)
326350397Sobrien    {
326450397Sobrien      /* Reset tables used to keep track of what's still valid [since the
326550397Sobrien	 start of the block].  */
326650397Sobrien      reset_opr_set_tables ();
326750397Sobrien
3268169689Skan      FOR_BB_INSNS (bb, insn)
326990075Sobrien	if (INSN_P (insn))
327090075Sobrien	  {
3271117395Skan	    changed |= cprop_insn (insn, alter_jumps);
327250397Sobrien
327390075Sobrien	    /* Keep track of everything modified by this insn.  */
327490075Sobrien	    /* ??? Need to be careful w.r.t. mods done to INSN.  Don't
327590075Sobrien	       call mark_oprs_set if we turned the insn into a NOTE.  */
3276169689Skan	    if (! NOTE_P (insn))
327750397Sobrien	      mark_oprs_set (insn);
327890075Sobrien	  }
327950397Sobrien    }
328050397Sobrien
3281169689Skan  if (dump_file != NULL)
3282169689Skan    fprintf (dump_file, "\n");
328350397Sobrien
328450397Sobrien  return changed;
328550397Sobrien}
328650397Sobrien
3287132718Skan/* Similar to get_condition, only the resulting condition must be
3288132718Skan   valid at JUMP, instead of at EARLIEST.
3289132718Skan
3290132718Skan   This differs from noce_get_condition in ifcvt.c in that we prefer not to
3291132718Skan   settle for the condition variable in the jump instruction being integral.
3292132718Skan   We prefer to be able to record the value of a user variable, rather than
3293132718Skan   the value of a temporary used in a condition.  This could be solved by
3294169689Skan   recording the value of *every* register scanned by canonicalize_condition,
3295132718Skan   but this would require some code reorganization.  */
3296132718Skan
3297132718Skanrtx
3298132718Skanfis_get_condition (rtx jump)
3299132718Skan{
3300169689Skan  return get_condition (jump, NULL, false, true);
3301132718Skan}
3302132718Skan
3303132718Skan/* Check the comparison COND to see if we can safely form an implicit set from
3304132718Skan   it.  COND is either an EQ or NE comparison.  */
3305132718Skan
3306132718Skanstatic bool
3307132718Skanimplicit_set_cond_p (rtx cond)
3308132718Skan{
3309132718Skan  enum machine_mode mode = GET_MODE (XEXP (cond, 0));
3310132718Skan  rtx cst = XEXP (cond, 1);
3311132718Skan
3312132718Skan  /* We can't perform this optimization if either operand might be or might
3313132718Skan     contain a signed zero.  */
3314132718Skan  if (HONOR_SIGNED_ZEROS (mode))
3315132718Skan    {
3316132718Skan      /* It is sufficient to check if CST is or contains a zero.  We must
3317132718Skan	 handle float, complex, and vector.  If any subpart is a zero, then
3318132718Skan	 the optimization can't be performed.  */
3319132718Skan      /* ??? The complex and vector checks are not implemented yet.  We just
3320132718Skan	 always return zero for them.  */
3321132718Skan      if (GET_CODE (cst) == CONST_DOUBLE)
3322132718Skan	{
3323132718Skan	  REAL_VALUE_TYPE d;
3324132718Skan	  REAL_VALUE_FROM_CONST_DOUBLE (d, cst);
3325132718Skan	  if (REAL_VALUES_EQUAL (d, dconst0))
3326132718Skan	    return 0;
3327132718Skan	}
3328132718Skan      else
3329132718Skan	return 0;
3330132718Skan    }
3331132718Skan
3332132718Skan  return gcse_constant_p (cst);
3333132718Skan}
3334132718Skan
3335132718Skan/* Find the implicit sets of a function.  An "implicit set" is a constraint
3336132718Skan   on the value of a variable, implied by a conditional jump.  For example,
3337132718Skan   following "if (x == 2)", the then branch may be optimized as though the
3338132718Skan   conditional performed an "explicit set", in this example, "x = 2".  This
3339132718Skan   function records the set patterns that are implicit at the start of each
3340132718Skan   basic block.  */
3341132718Skan
3342132718Skanstatic void
3343132718Skanfind_implicit_sets (void)
3344132718Skan{
3345132718Skan  basic_block bb, dest;
3346132718Skan  unsigned int count;
3347132718Skan  rtx cond, new;
3348132718Skan
3349132718Skan  count = 0;
3350132718Skan  FOR_EACH_BB (bb)
3351132718Skan    /* Check for more than one successor.  */
3352169689Skan    if (EDGE_COUNT (bb->succs) > 1)
3353132718Skan      {
3354132718Skan	cond = fis_get_condition (BB_END (bb));
3355132718Skan
3356132718Skan	if (cond
3357132718Skan	    && (GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
3358169689Skan	    && REG_P (XEXP (cond, 0))
3359132718Skan	    && REGNO (XEXP (cond, 0)) >= FIRST_PSEUDO_REGISTER
3360132718Skan	    && implicit_set_cond_p (cond))
3361132718Skan	  {
3362132718Skan	    dest = GET_CODE (cond) == EQ ? BRANCH_EDGE (bb)->dest
3363132718Skan					 : FALLTHRU_EDGE (bb)->dest;
3364132718Skan
3365169689Skan	    if (dest && single_pred_p (dest)
3366132718Skan		&& dest != EXIT_BLOCK_PTR)
3367132718Skan	      {
3368132718Skan		new = gen_rtx_SET (VOIDmode, XEXP (cond, 0),
3369132718Skan					     XEXP (cond, 1));
3370132718Skan		implicit_sets[dest->index] = new;
3371169689Skan		if (dump_file)
3372132718Skan		  {
3373169689Skan		    fprintf(dump_file, "Implicit set of reg %d in ",
3374132718Skan			    REGNO (XEXP (cond, 0)));
3375169689Skan		    fprintf(dump_file, "basic block %d\n", dest->index);
3376132718Skan		  }
3377132718Skan		count++;
3378132718Skan	      }
3379132718Skan	  }
3380132718Skan      }
3381132718Skan
3382169689Skan  if (dump_file)
3383169689Skan    fprintf (dump_file, "Found %d implicit sets\n", count);
3384132718Skan}
3385132718Skan
338650397Sobrien/* Perform one copy/constant propagation pass.
3387132718Skan   PASS is the pass count.  If CPROP_JUMPS is true, perform constant
3388132718Skan   propagation into conditional jumps.  If BYPASS_JUMPS is true,
3389132718Skan   perform conditional jump bypassing optimizations.  */
339050397Sobrien
339150397Sobrienstatic int
3392169689Skanone_cprop_pass (int pass, bool cprop_jumps, bool bypass_jumps)
339350397Sobrien{
339450397Sobrien  int changed = 0;
339550397Sobrien
3396169689Skan  global_const_prop_count = local_const_prop_count = 0;
3397169689Skan  global_copy_prop_count = local_copy_prop_count = 0;
339850397Sobrien
3399132718Skan  local_cprop_pass (cprop_jumps);
3400117395Skan
3401132718Skan  /* Determine implicit sets.  */
3402169689Skan  implicit_sets = XCNEWVEC (rtx, last_basic_block);
3403132718Skan  find_implicit_sets ();
3404132718Skan
3405117395Skan  alloc_hash_table (max_cuid, &set_hash_table, 1);
3406117395Skan  compute_hash_table (&set_hash_table);
3407132718Skan
3408132718Skan  /* Free implicit_sets before peak usage.  */
3409132718Skan  free (implicit_sets);
3410132718Skan  implicit_sets = NULL;
3411132718Skan
3412169689Skan  if (dump_file)
3413169689Skan    dump_hash_table (dump_file, "SET", &set_hash_table);
3414117395Skan  if (set_hash_table.n_elems > 0)
341550397Sobrien    {
3416117395Skan      alloc_cprop_mem (last_basic_block, set_hash_table.n_elems);
341750397Sobrien      compute_cprop_data ();
3418132718Skan      changed = cprop (cprop_jumps);
3419132718Skan      if (bypass_jumps)
3420117395Skan	changed |= bypass_conditional_jumps ();
342150397Sobrien      free_cprop_mem ();
342250397Sobrien    }
342390075Sobrien
3424117395Skan  free_hash_table (&set_hash_table);
342550397Sobrien
3426169689Skan  if (dump_file)
342750397Sobrien    {
3428169689Skan      fprintf (dump_file, "CPROP of %s, pass %d: %d bytes needed, ",
3429132718Skan	       current_function_name (), pass, bytes_used);
3430169689Skan      fprintf (dump_file, "%d local const props, %d local copy props, ",
3431169689Skan	       local_const_prop_count, local_copy_prop_count);
3432169689Skan      fprintf (dump_file, "%d global const props, %d global copy props\n\n",
3433169689Skan	       global_const_prop_count, global_copy_prop_count);
343450397Sobrien    }
3435117395Skan  /* Global analysis may get into infinite loops for unreachable blocks.  */
3436132718Skan  if (changed && cprop_jumps)
3437117395Skan    delete_unreachable_blocks ();
343850397Sobrien
343950397Sobrien  return changed;
344050397Sobrien}
344150397Sobrien
3442117395Skan/* Bypass conditional jumps.  */
3443117395Skan
3444132718Skan/* The value of last_basic_block at the beginning of the jump_bypass
3445132718Skan   pass.  The use of redirect_edge_and_branch_force may introduce new
3446132718Skan   basic blocks, but the data flow analysis is only valid for basic
3447132718Skan   block indices less than bypass_last_basic_block.  */
3448132718Skan
3449132718Skanstatic int bypass_last_basic_block;
3450132718Skan
3451117395Skan/* Find a set of REGNO to a constant that is available at the end of basic
3452117395Skan   block BB.  Returns NULL if no such set is found.  Based heavily upon
3453117395Skan   find_avail_set.  */
3454117395Skan
3455117395Skanstatic struct expr *
3456132718Skanfind_bypass_set (int regno, int bb)
3457117395Skan{
3458117395Skan  struct expr *result = 0;
3459117395Skan
3460117395Skan  for (;;)
3461117395Skan    {
3462117395Skan      rtx src;
3463132718Skan      struct expr *set = lookup_set (regno, &set_hash_table);
3464117395Skan
3465117395Skan      while (set)
3466117395Skan	{
3467117395Skan	  if (TEST_BIT (cprop_avout[bb], set->bitmap_index))
3468117395Skan	    break;
3469117395Skan	  set = next_set (regno, set);
3470117395Skan	}
3471117395Skan
3472117395Skan      if (set == 0)
3473117395Skan	break;
3474117395Skan
3475169689Skan      gcc_assert (GET_CODE (set->expr) == SET);
3476117395Skan
3477117395Skan      src = SET_SRC (set->expr);
3478132718Skan      if (gcse_constant_p (src))
3479117395Skan	result = set;
3480117395Skan
3481169689Skan      if (! REG_P (src))
3482117395Skan	break;
3483117395Skan
3484117395Skan      regno = REGNO (src);
3485117395Skan    }
3486117395Skan  return result;
3487117395Skan}
3488117395Skan
3489117395Skan
3490117395Skan/* Subroutine of bypass_block that checks whether a pseudo is killed by
3491117395Skan   any of the instructions inserted on an edge.  Jump bypassing places
3492117395Skan   condition code setters on CFG edges using insert_insn_on_edge.  This
3493117395Skan   function is required to check that our data flow analysis is still
3494117395Skan   valid prior to commit_edge_insertions.  */
3495117395Skan
3496117395Skanstatic bool
3497132718Skanreg_killed_on_edge (rtx reg, edge e)
3498117395Skan{
3499117395Skan  rtx insn;
3500117395Skan
3501169689Skan  for (insn = e->insns.r; insn; insn = NEXT_INSN (insn))
3502117395Skan    if (INSN_P (insn) && reg_set_p (reg, insn))
3503117395Skan      return true;
3504117395Skan
3505117395Skan  return false;
3506117395Skan}
3507117395Skan
3508117395Skan/* Subroutine of bypass_conditional_jumps that attempts to bypass the given
3509117395Skan   basic block BB which has more than one predecessor.  If not NULL, SETCC
3510117395Skan   is the first instruction of BB, which is immediately followed by JUMP_INSN
3511117395Skan   JUMP.  Otherwise, SETCC is NULL, and JUMP is the first insn of BB.
3512117395Skan   Returns nonzero if a change was made.
3513117395Skan
3514132718Skan   During the jump bypassing pass, we may place copies of SETCC instructions
3515117395Skan   on CFG edges.  The following routine must be careful to pay attention to
3516117395Skan   these inserted insns when performing its transformations.  */
3517117395Skan
3518117395Skanstatic int
3519132718Skanbypass_block (basic_block bb, rtx setcc, rtx jump)
3520117395Skan{
3521117395Skan  rtx insn, note;
3522169689Skan  edge e, edest;
3523117395Skan  int i, change;
3524132718Skan  int may_be_loop_header;
3525169689Skan  unsigned removed_p;
3526169689Skan  edge_iterator ei;
3527117395Skan
3528117395Skan  insn = (setcc != NULL) ? setcc : jump;
3529117395Skan
3530117395Skan  /* Determine set of register uses in INSN.  */
3531117395Skan  reg_use_count = 0;
3532117395Skan  note_uses (&PATTERN (insn), find_used_regs, NULL);
3533117395Skan  note = find_reg_equal_equiv_note (insn);
3534117395Skan  if (note)
3535117395Skan    find_used_regs (&XEXP (note, 0), NULL);
3536117395Skan
3537132718Skan  may_be_loop_header = false;
3538169689Skan  FOR_EACH_EDGE (e, ei, bb->preds)
3539132718Skan    if (e->flags & EDGE_DFS_BACK)
3540132718Skan      {
3541132718Skan	may_be_loop_header = true;
3542132718Skan	break;
3543132718Skan      }
3544132718Skan
3545117395Skan  change = 0;
3546169689Skan  for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
3547117395Skan    {
3548169689Skan      removed_p = 0;
3549169689Skan
3550132718Skan      if (e->flags & EDGE_COMPLEX)
3551169689Skan	{
3552169689Skan	  ei_next (&ei);
3553169689Skan	  continue;
3554169689Skan	}
3555132718Skan
3556132718Skan      /* We can't redirect edges from new basic blocks.  */
3557132718Skan      if (e->src->index >= bypass_last_basic_block)
3558169689Skan	{
3559169689Skan	  ei_next (&ei);
3560169689Skan	  continue;
3561169689Skan	}
3562132718Skan
3563132718Skan      /* The irreducible loops created by redirecting of edges entering the
3564132718Skan	 loop from outside would decrease effectiveness of some of the following
3565132718Skan	 optimizations, so prevent this.  */
3566132718Skan      if (may_be_loop_header
3567132718Skan	  && !(e->flags & EDGE_DFS_BACK))
3568169689Skan	{
3569169689Skan	  ei_next (&ei);
3570169689Skan	  continue;
3571169689Skan	}
3572132718Skan
3573117395Skan      for (i = 0; i < reg_use_count; i++)
3574117395Skan	{
3575117395Skan	  struct reg_use *reg_used = &reg_use_table[i];
3576117395Skan	  unsigned int regno = REGNO (reg_used->reg_rtx);
3577117395Skan	  basic_block dest, old_dest;
3578117395Skan	  struct expr *set;
3579117395Skan	  rtx src, new;
3580117395Skan
3581117395Skan	  if (regno >= max_gcse_regno)
3582117395Skan	    continue;
3583117395Skan
3584117395Skan	  set = find_bypass_set (regno, e->src->index);
3585117395Skan
3586117395Skan	  if (! set)
3587117395Skan	    continue;
3588117395Skan
3589117395Skan	  /* Check the data flow is valid after edge insertions.  */
3590169689Skan	  if (e->insns.r && reg_killed_on_edge (reg_used->reg_rtx, e))
3591117395Skan	    continue;
3592117395Skan
3593117395Skan	  src = SET_SRC (pc_set (jump));
3594117395Skan
3595117395Skan	  if (setcc != NULL)
3596117395Skan	      src = simplify_replace_rtx (src,
3597117395Skan					  SET_DEST (PATTERN (setcc)),
3598117395Skan					  SET_SRC (PATTERN (setcc)));
3599117395Skan
3600117395Skan	  new = simplify_replace_rtx (src, reg_used->reg_rtx,
3601117395Skan				      SET_SRC (set->expr));
3602117395Skan
3603132718Skan	  /* Jump bypassing may have already placed instructions on
3604117395Skan	     edges of the CFG.  We can't bypass an outgoing edge that
3605117395Skan	     has instructions associated with it, as these insns won't
3606117395Skan	     get executed if the incoming edge is redirected.  */
3607117395Skan
3608117395Skan	  if (new == pc_rtx)
3609117395Skan	    {
3610117395Skan	      edest = FALLTHRU_EDGE (bb);
3611169689Skan	      dest = edest->insns.r ? NULL : edest->dest;
3612117395Skan	    }
3613117395Skan	  else if (GET_CODE (new) == LABEL_REF)
3614117395Skan	    {
3615117395Skan	      dest = BLOCK_FOR_INSN (XEXP (new, 0));
3616117395Skan	      /* Don't bypass edges containing instructions.  */
3617169689Skan	      edest = find_edge (bb, dest);
3618169689Skan	      if (edest && edest->insns.r)
3619169689Skan		dest = NULL;
3620117395Skan	    }
3621117395Skan	  else
3622117395Skan	    dest = NULL;
3623117395Skan
3624132718Skan	  /* Avoid unification of the edge with other edges from original
3625132718Skan	     branch.  We would end up emitting the instruction on "both"
3626132718Skan	     edges.  */
3627132718Skan
3628169689Skan	  if (dest && setcc && !CC0_P (SET_DEST (PATTERN (setcc)))
3629169689Skan	      && find_edge (e->src, dest))
3630169689Skan	    dest = NULL;
3631169689Skan
3632117395Skan	  old_dest = e->dest;
3633132718Skan	  if (dest != NULL
3634132718Skan	      && dest != old_dest
3635132718Skan	      && dest != EXIT_BLOCK_PTR)
3636132718Skan            {
3637132718Skan	      redirect_edge_and_branch_force (e, dest);
3638132718Skan
3639117395Skan	      /* Copy the register setter to the redirected edge.
3640117395Skan		 Don't copy CC0 setters, as CC0 is dead after jump.  */
3641117395Skan	      if (setcc)
3642117395Skan		{
3643117395Skan		  rtx pat = PATTERN (setcc);
3644117395Skan		  if (!CC0_P (SET_DEST (pat)))
3645117395Skan		    insert_insn_on_edge (copy_insn (pat), e);
3646117395Skan		}
3647117395Skan
3648169689Skan	      if (dump_file != NULL)
3649117395Skan		{
3650169689Skan		  fprintf (dump_file, "JUMP-BYPASS: Proved reg %d "
3651169689Skan				      "in jump_insn %d equals constant ",
3652117395Skan			   regno, INSN_UID (jump));
3653169689Skan		  print_rtl (dump_file, SET_SRC (set->expr));
3654169689Skan		  fprintf (dump_file, "\nBypass edge from %d->%d to %d\n",
3655117395Skan			   e->src->index, old_dest->index, dest->index);
3656117395Skan		}
3657117395Skan	      change = 1;
3658169689Skan	      removed_p = 1;
3659117395Skan	      break;
3660117395Skan	    }
3661117395Skan	}
3662169689Skan      if (!removed_p)
3663169689Skan	ei_next (&ei);
3664117395Skan    }
3665117395Skan  return change;
3666117395Skan}
3667117395Skan
3668117395Skan/* Find basic blocks with more than one predecessor that only contain a
3669117395Skan   single conditional jump.  If the result of the comparison is known at
3670117395Skan   compile-time from any incoming edge, redirect that edge to the
3671132718Skan   appropriate target.  Returns nonzero if a change was made.
3672117395Skan
3673132718Skan   This function is now mis-named, because we also handle indirect jumps.  */
3674132718Skan
3675117395Skanstatic int
3676132718Skanbypass_conditional_jumps (void)
3677117395Skan{
3678117395Skan  basic_block bb;
3679117395Skan  int changed;
3680117395Skan  rtx setcc;
3681117395Skan  rtx insn;
3682117395Skan  rtx dest;
3683117395Skan
3684117395Skan  /* Note we start at block 1.  */
3685117395Skan  if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
3686117395Skan    return 0;
3687117395Skan
3688132718Skan  bypass_last_basic_block = last_basic_block;
3689132718Skan  mark_dfs_back_edges ();
3690132718Skan
3691117395Skan  changed = 0;
3692117395Skan  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb,
3693117395Skan		  EXIT_BLOCK_PTR, next_bb)
3694117395Skan    {
3695117395Skan      /* Check for more than one predecessor.  */
3696169689Skan      if (!single_pred_p (bb))
3697117395Skan	{
3698117395Skan	  setcc = NULL_RTX;
3699169689Skan	  FOR_BB_INSNS (bb, insn)
3700169689Skan	    if (NONJUMP_INSN_P (insn))
3701117395Skan	      {
3702117395Skan		if (setcc)
3703117395Skan		  break;
3704117395Skan		if (GET_CODE (PATTERN (insn)) != SET)
3705117395Skan		  break;
3706117395Skan
3707117395Skan		dest = SET_DEST (PATTERN (insn));
3708117395Skan		if (REG_P (dest) || CC0_P (dest))
3709117395Skan		  setcc = insn;
3710117395Skan		else
3711117395Skan		  break;
3712117395Skan	      }
3713169689Skan	    else if (JUMP_P (insn))
3714117395Skan	      {
3715132718Skan		if ((any_condjump_p (insn) || computed_jump_p (insn))
3716132718Skan		    && onlyjump_p (insn))
3717117395Skan		  changed |= bypass_block (bb, setcc, insn);
3718117395Skan		break;
3719117395Skan	      }
3720117395Skan	    else if (INSN_P (insn))
3721117395Skan	      break;
3722117395Skan	}
3723117395Skan    }
3724117395Skan
3725117395Skan  /* If we bypassed any register setting insns, we inserted a
3726132718Skan     copy on the redirected edge.  These need to be committed.  */
3727117395Skan  if (changed)
3728117395Skan    commit_edge_insertions();
3729117395Skan
3730117395Skan  return changed;
3731117395Skan}
3732117395Skan
373352284Sobrien/* Compute PRE+LCM working variables.  */
373450397Sobrien
373550397Sobrien/* Local properties of expressions.  */
373650397Sobrien/* Nonzero for expressions that are transparent in the block.  */
373752284Sobrienstatic sbitmap *transp;
373852284Sobrien
373952284Sobrien/* Nonzero for expressions that are transparent at the end of the block.
374052284Sobrien   This is only zero for expressions killed by abnormal critical edge
374152284Sobrien   created by a calls.  */
374252284Sobrienstatic sbitmap *transpout;
374352284Sobrien
374450397Sobrien/* Nonzero for expressions that are computed (available) in the block.  */
374552284Sobrienstatic sbitmap *comp;
374652284Sobrien
374750397Sobrien/* Nonzero for expressions that are locally anticipatable in the block.  */
374852284Sobrienstatic sbitmap *antloc;
374950397Sobrien
375052284Sobrien/* Nonzero for expressions where this block is an optimal computation
375152284Sobrien   point.  */
375252284Sobrienstatic sbitmap *pre_optimal;
375350397Sobrien
375452284Sobrien/* Nonzero for expressions which are redundant in a particular block.  */
375552284Sobrienstatic sbitmap *pre_redundant;
375650397Sobrien
375790075Sobrien/* Nonzero for expressions which should be inserted on a specific edge.  */
375890075Sobrienstatic sbitmap *pre_insert_map;
375952284Sobrien
376090075Sobrien/* Nonzero for expressions which should be deleted in a specific block.  */
376190075Sobrienstatic sbitmap *pre_delete_map;
376290075Sobrien
376390075Sobrien/* Contains the edge_list returned by pre_edge_lcm.  */
376490075Sobrienstatic struct edge_list *edge_list;
376590075Sobrien
376652284Sobrien/* Redundant insns.  */
376752284Sobrienstatic sbitmap pre_redundant_insns;
376852284Sobrien
376950397Sobrien/* Allocate vars used for PRE analysis.  */
377050397Sobrien
377150397Sobrienstatic void
3772132718Skanalloc_pre_mem (int n_blocks, int n_exprs)
377350397Sobrien{
377452284Sobrien  transp = sbitmap_vector_alloc (n_blocks, n_exprs);
377552284Sobrien  comp = sbitmap_vector_alloc (n_blocks, n_exprs);
377652284Sobrien  antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
377750397Sobrien
377890075Sobrien  pre_optimal = NULL;
377990075Sobrien  pre_redundant = NULL;
378090075Sobrien  pre_insert_map = NULL;
378190075Sobrien  pre_delete_map = NULL;
378290075Sobrien  ae_kill = sbitmap_vector_alloc (n_blocks, n_exprs);
378390075Sobrien
378490075Sobrien  /* pre_insert and pre_delete are allocated later.  */
378550397Sobrien}
378650397Sobrien
378750397Sobrien/* Free vars used for PRE analysis.  */
378850397Sobrien
378950397Sobrienstatic void
3790132718Skanfree_pre_mem (void)
379150397Sobrien{
379290075Sobrien  sbitmap_vector_free (transp);
379390075Sobrien  sbitmap_vector_free (comp);
379450397Sobrien
379590075Sobrien  /* ANTLOC and AE_KILL are freed just after pre_lcm finishes.  */
379690075Sobrien
379790075Sobrien  if (pre_optimal)
379890075Sobrien    sbitmap_vector_free (pre_optimal);
379990075Sobrien  if (pre_redundant)
380090075Sobrien    sbitmap_vector_free (pre_redundant);
380190075Sobrien  if (pre_insert_map)
380290075Sobrien    sbitmap_vector_free (pre_insert_map);
380390075Sobrien  if (pre_delete_map)
380490075Sobrien    sbitmap_vector_free (pre_delete_map);
380590075Sobrien
380690075Sobrien  transp = comp = NULL;
380790075Sobrien  pre_optimal = pre_redundant = pre_insert_map = pre_delete_map = NULL;
380850397Sobrien}
380950397Sobrien
381050397Sobrien/* Top level routine to do the dataflow analysis needed by PRE.  */
381150397Sobrien
381250397Sobrienstatic void
3813132718Skancompute_pre_data (void)
381450397Sobrien{
381590075Sobrien  sbitmap trapping_expr;
3816117395Skan  basic_block bb;
381790075Sobrien  unsigned int ui;
381890075Sobrien
3819117395Skan  compute_local_properties (transp, comp, antloc, &expr_hash_table);
3820117395Skan  sbitmap_vector_zero (ae_kill, last_basic_block);
382190075Sobrien
382290075Sobrien  /* Collect expressions which might trap.  */
3823117395Skan  trapping_expr = sbitmap_alloc (expr_hash_table.n_elems);
382490075Sobrien  sbitmap_zero (trapping_expr);
3825117395Skan  for (ui = 0; ui < expr_hash_table.size; ui++)
382690075Sobrien    {
382790075Sobrien      struct expr *e;
3828117395Skan      for (e = expr_hash_table.table[ui]; e != NULL; e = e->next_same_hash)
382990075Sobrien	if (may_trap_p (e->expr))
383090075Sobrien	  SET_BIT (trapping_expr, e->bitmap_index);
383190075Sobrien    }
383290075Sobrien
383390075Sobrien  /* Compute ae_kill for each basic block using:
383490075Sobrien
383590075Sobrien     ~(TRANSP | COMP)
3836169689Skan  */
383790075Sobrien
3838117395Skan  FOR_EACH_BB (bb)
383990075Sobrien    {
384090075Sobrien      edge e;
3841169689Skan      edge_iterator ei;
384290075Sobrien
384390075Sobrien      /* If the current block is the destination of an abnormal edge, we
384490075Sobrien	 kill all trapping expressions because we won't be able to properly
384590075Sobrien	 place the instruction on the edge.  So make them neither
384690075Sobrien	 anticipatable nor transparent.  This is fairly conservative.  */
3847169689Skan      FOR_EACH_EDGE (e, ei, bb->preds)
384890075Sobrien	if (e->flags & EDGE_ABNORMAL)
384990075Sobrien	  {
3850117395Skan	    sbitmap_difference (antloc[bb->index], antloc[bb->index], trapping_expr);
3851117395Skan	    sbitmap_difference (transp[bb->index], transp[bb->index], trapping_expr);
385290075Sobrien	    break;
385390075Sobrien	  }
385490075Sobrien
3855117395Skan      sbitmap_a_or_b (ae_kill[bb->index], transp[bb->index], comp[bb->index]);
3856117395Skan      sbitmap_not (ae_kill[bb->index], ae_kill[bb->index]);
385790075Sobrien    }
385890075Sobrien
3859169689Skan  edge_list = pre_edge_lcm (expr_hash_table.n_elems, transp, comp, antloc,
386090075Sobrien			    ae_kill, &pre_insert_map, &pre_delete_map);
386190075Sobrien  sbitmap_vector_free (antloc);
386290075Sobrien  antloc = NULL;
386390075Sobrien  sbitmap_vector_free (ae_kill);
3864117395Skan  ae_kill = NULL;
386590075Sobrien  sbitmap_free (trapping_expr);
386650397Sobrien}
386750397Sobrien
386850397Sobrien/* PRE utilities */
386950397Sobrien
3870117395Skan/* Return nonzero if an occurrence of expression EXPR in OCCR_BB would reach
387152284Sobrien   block BB.
387250397Sobrien
387350397Sobrien   VISITED is a pointer to a working buffer for tracking which BB's have
387450397Sobrien   been visited.  It is NULL for the top-level call.
387550397Sobrien
387650397Sobrien   We treat reaching expressions that go through blocks containing the same
387750397Sobrien   reaching expression as "not reaching".  E.g. if EXPR is generated in blocks
387850397Sobrien   2 and 3, INSN is in block 4, and 2->3->4, we treat the expression in block
387950397Sobrien   2 as not reaching.  The intent is to improve the probability of finding
388050397Sobrien   only one reaching expression and to reduce register lifetimes by picking
388150397Sobrien   the closest such expression.  */
388250397Sobrien
388350397Sobrienstatic int
3884132718Skanpre_expr_reaches_here_p_work (basic_block occr_bb, struct expr *expr, basic_block bb, char *visited)
388550397Sobrien{
388690075Sobrien  edge pred;
3887169689Skan  edge_iterator ei;
3888169689Skan
3889169689Skan  FOR_EACH_EDGE (pred, ei, bb->preds)
389050397Sobrien    {
389190075Sobrien      basic_block pred_bb = pred->src;
389250397Sobrien
389390075Sobrien      if (pred->src == ENTRY_BLOCK_PTR
389490075Sobrien	  /* Has predecessor has already been visited?  */
389590075Sobrien	  || visited[pred_bb->index])
389690075Sobrien	;/* Nothing to do.  */
389750397Sobrien
389850397Sobrien      /* Does this predecessor generate this expression?  */
389990075Sobrien      else if (TEST_BIT (comp[pred_bb->index], expr->bitmap_index))
390050397Sobrien	{
390150397Sobrien	  /* Is this the occurrence we're looking for?
390250397Sobrien	     Note that there's only one generating occurrence per block
390350397Sobrien	     so we just need to check the block number.  */
390452284Sobrien	  if (occr_bb == pred_bb)
390550397Sobrien	    return 1;
390690075Sobrien
390790075Sobrien	  visited[pred_bb->index] = 1;
390850397Sobrien	}
390950397Sobrien      /* Ignore this predecessor if it kills the expression.  */
391090075Sobrien      else if (! TEST_BIT (transp[pred_bb->index], expr->bitmap_index))
391190075Sobrien	visited[pred_bb->index] = 1;
391290075Sobrien
391350397Sobrien      /* Neither gen nor kill.  */
391450397Sobrien      else
391552284Sobrien	{
391690075Sobrien	  visited[pred_bb->index] = 1;
391790075Sobrien	  if (pre_expr_reaches_here_p_work (occr_bb, expr, pred_bb, visited))
391850397Sobrien	    return 1;
391952284Sobrien	}
392050397Sobrien    }
392150397Sobrien
392250397Sobrien  /* All paths have been checked.  */
392350397Sobrien  return 0;
392450397Sobrien}
392590075Sobrien
392690075Sobrien/* The wrapper for pre_expr_reaches_here_work that ensures that any
392790075Sobrien   memory allocated for that function is returned.  */
392890075Sobrien
392990075Sobrienstatic int
3930132718Skanpre_expr_reaches_here_p (basic_block occr_bb, struct expr *expr, basic_block bb)
393190075Sobrien{
393290075Sobrien  int rval;
3933169689Skan  char *visited = XCNEWVEC (char, last_basic_block);
393490075Sobrien
393590075Sobrien  rval = pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited);
393690075Sobrien
393790075Sobrien  free (visited);
393890075Sobrien  return rval;
393990075Sobrien}
394050397Sobrien
394190075Sobrien
394290075Sobrien/* Given an expr, generate RTL which we can insert at the end of a BB,
3943117395Skan   or on an edge.  Set the block number of any insns generated to
394490075Sobrien   the value of BB.  */
394590075Sobrien
394690075Sobrienstatic rtx
3947132718Skanprocess_insert_insn (struct expr *expr)
394890075Sobrien{
394990075Sobrien  rtx reg = expr->reaching_reg;
395090075Sobrien  rtx exp = copy_rtx (expr->expr);
395190075Sobrien  rtx pat;
395290075Sobrien
395390075Sobrien  start_sequence ();
395490075Sobrien
395590075Sobrien  /* If the expression is something that's an operand, like a constant,
395690075Sobrien     just copy it to a register.  */
395790075Sobrien  if (general_operand (exp, GET_MODE (reg)))
395890075Sobrien    emit_move_insn (reg, exp);
395990075Sobrien
396090075Sobrien  /* Otherwise, make a new insn to compute this expression and make sure the
396190075Sobrien     insn will be recognized (this also adds any needed CLOBBERs).  Copy the
396290075Sobrien     expression to make sure we don't have any sharing issues.  */
3963169689Skan  else
3964169689Skan    {
3965169689Skan      rtx insn = emit_insn (gen_rtx_SET (VOIDmode, reg, exp));
3966117395Skan
3967169689Skan      if (insn_invalid_p (insn))
3968169689Skan	gcc_unreachable ();
3969169689Skan    }
3970169689Skan
3971169689Skan
3972117395Skan  pat = get_insns ();
397390075Sobrien  end_sequence ();
397490075Sobrien
397590075Sobrien  return pat;
397690075Sobrien}
3977117395Skan
397852284Sobrien/* Add EXPR to the end of basic block BB.
397950397Sobrien
398052284Sobrien   This is used by both the PRE and code hoisting.
398152284Sobrien
398252284Sobrien   For PRE, we want to verify that the expr is either transparent
398352284Sobrien   or locally anticipatable in the target block.  This check makes
398452284Sobrien   no sense for code hoisting.  */
398552284Sobrien
398650397Sobrienstatic void
3987132718Skaninsert_insn_end_bb (struct expr *expr, basic_block bb, int pre)
398850397Sobrien{
3989132718Skan  rtx insn = BB_END (bb);
399050397Sobrien  rtx new_insn;
399150397Sobrien  rtx reg = expr->reaching_reg;
399250397Sobrien  int regno = REGNO (reg);
3993117395Skan  rtx pat, pat_end;
399450397Sobrien
399590075Sobrien  pat = process_insert_insn (expr);
3996169689Skan  gcc_assert (pat && INSN_P (pat));
399750397Sobrien
3998117395Skan  pat_end = pat;
3999117395Skan  while (NEXT_INSN (pat_end) != NULL_RTX)
4000117395Skan    pat_end = NEXT_INSN (pat_end);
4001117395Skan
400250397Sobrien  /* If the last insn is a jump, insert EXPR in front [taking care to
4003132718Skan     handle cc0, etc. properly].  Similarly we need to care trapping
400496263Sobrien     instructions in presence of non-call exceptions.  */
400550397Sobrien
4006169689Skan  if (JUMP_P (insn)
4007169689Skan      || (NONJUMP_INSN_P (insn)
4008169689Skan	  && (!single_succ_p (bb)
4009169689Skan	      || single_succ_edge (bb)->flags & EDGE_ABNORMAL)))
401050397Sobrien    {
401150397Sobrien#ifdef HAVE_cc0
401250397Sobrien      rtx note;
401350397Sobrien#endif
401496263Sobrien      /* It should always be the case that we can put these instructions
401596263Sobrien	 anywhere in the basic block with performing PRE optimizations.
401696263Sobrien	 Check this.  */
4017169689Skan      gcc_assert (!NONJUMP_INSN_P (insn) || !pre
4018169689Skan		  || TEST_BIT (antloc[bb->index], expr->bitmap_index)
4019169689Skan		  || TEST_BIT (transp[bb->index], expr->bitmap_index));
402050397Sobrien
402150397Sobrien      /* If this is a jump table, then we can't insert stuff here.  Since
402250397Sobrien	 we know the previous real insn must be the tablejump, we insert
402350397Sobrien	 the new instruction just before the tablejump.  */
402450397Sobrien      if (GET_CODE (PATTERN (insn)) == ADDR_VEC
402550397Sobrien	  || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
402650397Sobrien	insn = prev_real_insn (insn);
402750397Sobrien
402850397Sobrien#ifdef HAVE_cc0
402950397Sobrien      /* FIXME: 'twould be nice to call prev_cc0_setter here but it aborts
403050397Sobrien	 if cc0 isn't set.  */
403150397Sobrien      note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
403250397Sobrien      if (note)
403350397Sobrien	insn = XEXP (note, 0);
403450397Sobrien      else
403550397Sobrien	{
403650397Sobrien	  rtx maybe_cc0_setter = prev_nonnote_insn (insn);
403750397Sobrien	  if (maybe_cc0_setter
403890075Sobrien	      && INSN_P (maybe_cc0_setter)
403950397Sobrien	      && sets_cc0_p (PATTERN (maybe_cc0_setter)))
404050397Sobrien	    insn = maybe_cc0_setter;
404150397Sobrien	}
404250397Sobrien#endif
404350397Sobrien      /* FIXME: What if something in cc0/jump uses value set in new insn?  */
4044132718Skan      new_insn = emit_insn_before_noloc (pat, insn);
404550397Sobrien    }
404690075Sobrien
404752284Sobrien  /* Likewise if the last insn is a call, as will happen in the presence
404852284Sobrien     of exception handling.  */
4049169689Skan  else if (CALL_P (insn)
4050169689Skan	   && (!single_succ_p (bb)
4051169689Skan	       || single_succ_edge (bb)->flags & EDGE_ABNORMAL))
405252284Sobrien    {
405352284Sobrien      /* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers,
405452284Sobrien	 we search backward and place the instructions before the first
405552284Sobrien	 parameter is loaded.  Do this for everyone for consistency and a
4056132718Skan	 presumption that we'll get better code elsewhere as well.
405752284Sobrien
405890075Sobrien	 It should always be the case that we can put these instructions
405952284Sobrien	 anywhere in the basic block with performing PRE optimizations.
406052284Sobrien	 Check this.  */
406190075Sobrien
4062169689Skan      gcc_assert (!pre
4063169689Skan		  || TEST_BIT (antloc[bb->index], expr->bitmap_index)
4064169689Skan		  || TEST_BIT (transp[bb->index], expr->bitmap_index));
406552284Sobrien
406652284Sobrien      /* Since different machines initialize their parameter registers
406752284Sobrien	 in different orders, assume nothing.  Collect the set of all
406852284Sobrien	 parameter registers.  */
4069132718Skan      insn = find_first_parameter_load (insn, BB_HEAD (bb));
407052284Sobrien
407152284Sobrien      /* If we found all the parameter loads, then we want to insert
407252284Sobrien	 before the first parameter load.
407352284Sobrien
407452284Sobrien	 If we did not find all the parameter loads, then we might have
407552284Sobrien	 stopped on the head of the block, which could be a CODE_LABEL.
407652284Sobrien	 If we inserted before the CODE_LABEL, then we would be putting
407752284Sobrien	 the insn in the wrong basic block.  In that case, put the insn
407890075Sobrien	 after the CODE_LABEL.  Also, respect NOTE_INSN_BASIC_BLOCK.  */
4079169689Skan      while (LABEL_P (insn)
408090075Sobrien	     || NOTE_INSN_BASIC_BLOCK_P (insn))
408190075Sobrien	insn = NEXT_INSN (insn);
408252284Sobrien
4083132718Skan      new_insn = emit_insn_before_noloc (pat, insn);
408452284Sobrien    }
408550397Sobrien  else
4086132718Skan    new_insn = emit_insn_after_noloc (pat, insn);
408752284Sobrien
4088117395Skan  while (1)
408952284Sobrien    {
4090117395Skan      if (INSN_P (pat))
409152284Sobrien	{
4092117395Skan	  add_label_notes (PATTERN (pat), new_insn);
4093117395Skan	  note_stores (PATTERN (pat), record_set_info, pat);
409452284Sobrien	}
4095117395Skan      if (pat == pat_end)
4096117395Skan	break;
4097117395Skan      pat = NEXT_INSN (pat);
409852284Sobrien    }
409990075Sobrien
410050397Sobrien  gcse_create_count++;
410150397Sobrien
4102169689Skan  if (dump_file)
410350397Sobrien    {
4104169689Skan      fprintf (dump_file, "PRE/HOIST: end of bb %d, insn %d, ",
410590075Sobrien	       bb->index, INSN_UID (new_insn));
4106169689Skan      fprintf (dump_file, "copying expression %d to reg %d\n",
410790075Sobrien	       expr->bitmap_index, regno);
410850397Sobrien    }
410950397Sobrien}
411050397Sobrien
411190075Sobrien/* Insert partially redundant expressions on edges in the CFG to make
411290075Sobrien   the expressions fully redundant.  */
411350397Sobrien
411490075Sobrienstatic int
4115132718Skanpre_edge_insert (struct edge_list *edge_list, struct expr **index_map)
411650397Sobrien{
411790075Sobrien  int e, i, j, num_edges, set_size, did_insert = 0;
411852284Sobrien  sbitmap *inserted;
411950397Sobrien
412090075Sobrien  /* Where PRE_INSERT_MAP is nonzero, we add the expression on that edge
412190075Sobrien     if it reaches any of the deleted expressions.  */
412250397Sobrien
412390075Sobrien  set_size = pre_insert_map[0]->size;
412490075Sobrien  num_edges = NUM_EDGES (edge_list);
4125117395Skan  inserted = sbitmap_vector_alloc (num_edges, expr_hash_table.n_elems);
412690075Sobrien  sbitmap_vector_zero (inserted, num_edges);
412752284Sobrien
412890075Sobrien  for (e = 0; e < num_edges; e++)
412950397Sobrien    {
413050397Sobrien      int indx;
413190075Sobrien      basic_block bb = INDEX_EDGE_PRED_BB (edge_list, e);
413250397Sobrien
413352284Sobrien      for (i = indx = 0; i < set_size; i++, indx += SBITMAP_ELT_BITS)
413450397Sobrien	{
413590075Sobrien	  SBITMAP_ELT_TYPE insert = pre_insert_map[e]->elms[i];
413650397Sobrien
4137117395Skan	  for (j = indx; insert && j < (int) expr_hash_table.n_elems; j++, insert >>= 1)
413890075Sobrien	    if ((insert & 1) != 0 && index_map[j]->reaching_reg != NULL_RTX)
413990075Sobrien	      {
414090075Sobrien		struct expr *expr = index_map[j];
414190075Sobrien		struct occr *occr;
414252284Sobrien
414390075Sobrien		/* Now look at each deleted occurrence of this expression.  */
414490075Sobrien		for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
414590075Sobrien		  {
414690075Sobrien		    if (! occr->deleted_p)
414790075Sobrien		      continue;
414852284Sobrien
4149169689Skan		    /* Insert this expression on this edge if it would
415090075Sobrien		       reach the deleted occurrence in BB.  */
415190075Sobrien		    if (!TEST_BIT (inserted[e], j))
415290075Sobrien		      {
415390075Sobrien			rtx insn;
415490075Sobrien			edge eg = INDEX_EDGE (edge_list, e);
415590075Sobrien
415690075Sobrien			/* We can't insert anything on an abnormal and
415790075Sobrien			   critical edge, so we insert the insn at the end of
415890075Sobrien			   the previous block. There are several alternatives
415990075Sobrien			   detailed in Morgans book P277 (sec 10.5) for
416090075Sobrien			   handling this situation.  This one is easiest for
416190075Sobrien			   now.  */
416290075Sobrien
4163169689Skan			if (eg->flags & EDGE_ABNORMAL)
416490075Sobrien			  insert_insn_end_bb (index_map[j], bb, 0);
416590075Sobrien			else
416690075Sobrien			  {
416790075Sobrien			    insn = process_insert_insn (index_map[j]);
416890075Sobrien			    insert_insn_on_edge (insn, eg);
416990075Sobrien			  }
417090075Sobrien
4171169689Skan			if (dump_file)
417290075Sobrien			  {
4173169689Skan			    fprintf (dump_file, "PRE/HOIST: edge (%d,%d), ",
417490075Sobrien				     bb->index,
417590075Sobrien				     INDEX_EDGE_SUCC_BB (edge_list, e)->index);
4176169689Skan			    fprintf (dump_file, "copy expression %d\n",
417790075Sobrien				     expr->bitmap_index);
417890075Sobrien			  }
417990075Sobrien
418090075Sobrien			update_ld_motion_stores (expr);
418190075Sobrien			SET_BIT (inserted[e], j);
418290075Sobrien			did_insert = 1;
418390075Sobrien			gcse_create_count++;
418490075Sobrien		      }
418590075Sobrien		  }
418690075Sobrien	      }
418750397Sobrien	}
418850397Sobrien    }
418990075Sobrien
419090075Sobrien  sbitmap_vector_free (inserted);
419190075Sobrien  return did_insert;
419250397Sobrien}
419350397Sobrien
4194132718Skan/* Copy the result of EXPR->EXPR generated by INSN to EXPR->REACHING_REG.
4195132718Skan   Given "old_reg <- expr" (INSN), instead of adding after it
4196132718Skan     reaching_reg <- old_reg
4197132718Skan   it's better to do the following:
4198132718Skan     reaching_reg <- expr
4199132718Skan     old_reg      <- reaching_reg
4200132718Skan   because this way copy propagation can discover additional PRE
4201132718Skan   opportunities.  But if this fails, we try the old way.
4202132718Skan   When "expr" is a store, i.e.
4203132718Skan   given "MEM <- old_reg", instead of adding after it
4204132718Skan     reaching_reg <- old_reg
4205132718Skan   it's better to add it before as follows:
4206132718Skan     reaching_reg <- old_reg
4207132718Skan     MEM          <- reaching_reg.  */
420850397Sobrien
420950397Sobrienstatic void
4210132718Skanpre_insert_copy_insn (struct expr *expr, rtx insn)
421150397Sobrien{
421250397Sobrien  rtx reg = expr->reaching_reg;
421350397Sobrien  int regno = REGNO (reg);
421450397Sobrien  int indx = expr->bitmap_index;
4215132718Skan  rtx pat = PATTERN (insn);
4216169689Skan  rtx set, first_set, new_insn;
4217132718Skan  rtx old_reg;
4218132718Skan  int i;
421950397Sobrien
4220132718Skan  /* This block matches the logic in hash_scan_insn.  */
4221169689Skan  switch (GET_CODE (pat))
4222132718Skan    {
4223169689Skan    case SET:
4224169689Skan      set = pat;
4225169689Skan      break;
4226169689Skan
4227169689Skan    case PARALLEL:
4228132718Skan      /* Search through the parallel looking for the set whose
4229132718Skan	 source was the expression that we're interested in.  */
4230169689Skan      first_set = NULL_RTX;
4231132718Skan      set = NULL_RTX;
4232132718Skan      for (i = 0; i < XVECLEN (pat, 0); i++)
4233132718Skan	{
4234132718Skan	  rtx x = XVECEXP (pat, 0, i);
4235169689Skan	  if (GET_CODE (x) == SET)
4236132718Skan	    {
4237169689Skan	      /* If the source was a REG_EQUAL or REG_EQUIV note, we
4238169689Skan		 may not find an equivalent expression, but in this
4239169689Skan		 case the PARALLEL will have a single set.  */
4240169689Skan	      if (first_set == NULL_RTX)
4241169689Skan		first_set = x;
4242169689Skan	      if (expr_equiv_p (SET_SRC (x), expr->expr))
4243169689Skan	        {
4244169689Skan	          set = x;
4245169689Skan	          break;
4246169689Skan	        }
4247132718Skan	    }
4248132718Skan	}
4249169689Skan
4250169689Skan      gcc_assert (first_set);
4251169689Skan      if (set == NULL_RTX)
4252169689Skan        set = first_set;
4253169689Skan      break;
4254169689Skan
4255169689Skan    default:
4256169689Skan      gcc_unreachable ();
4257132718Skan    }
425890075Sobrien
4259169689Skan  if (REG_P (SET_DEST (set)))
4260132718Skan    {
4261132718Skan      old_reg = SET_DEST (set);
4262132718Skan      /* Check if we can modify the set destination in the original insn.  */
4263132718Skan      if (validate_change (insn, &SET_DEST (set), reg, 0))
4264132718Skan        {
4265132718Skan          new_insn = gen_move_insn (old_reg, reg);
4266132718Skan          new_insn = emit_insn_after (new_insn, insn);
426790075Sobrien
4268132718Skan          /* Keep register set table up to date.  */
4269132718Skan          record_one_set (regno, insn);
4270132718Skan        }
4271132718Skan      else
4272132718Skan        {
4273132718Skan          new_insn = gen_move_insn (reg, old_reg);
4274132718Skan          new_insn = emit_insn_after (new_insn, insn);
427550397Sobrien
4276132718Skan          /* Keep register set table up to date.  */
4277132718Skan          record_one_set (regno, new_insn);
4278132718Skan        }
4279132718Skan    }
4280132718Skan  else /* This is possible only in case of a store to memory.  */
4281132718Skan    {
4282132718Skan      old_reg = SET_SRC (set);
4283132718Skan      new_insn = gen_move_insn (reg, old_reg);
4284132718Skan
4285132718Skan      /* Check if we can modify the set source in the original insn.  */
4286132718Skan      if (validate_change (insn, &SET_SRC (set), reg, 0))
4287132718Skan        new_insn = emit_insn_before (new_insn, insn);
4288132718Skan      else
4289132718Skan        new_insn = emit_insn_after (new_insn, insn);
4290132718Skan
4291132718Skan      /* Keep register set table up to date.  */
4292132718Skan      record_one_set (regno, new_insn);
4293132718Skan    }
4294132718Skan
429550397Sobrien  gcse_create_count++;
429650397Sobrien
4297169689Skan  if (dump_file)
4298169689Skan    fprintf (dump_file,
429990075Sobrien	     "PRE: bb %d, insn %d, copy expression %d in insn %d to reg %d\n",
430090075Sobrien	      BLOCK_NUM (insn), INSN_UID (new_insn), indx,
430190075Sobrien	      INSN_UID (insn), regno);
430250397Sobrien}
430350397Sobrien
430450397Sobrien/* Copy available expressions that reach the redundant expression
430550397Sobrien   to `reaching_reg'.  */
430650397Sobrien
430750397Sobrienstatic void
4308132718Skanpre_insert_copies (void)
430950397Sobrien{
4310132718Skan  unsigned int i, added_copy;
431190075Sobrien  struct expr *expr;
431290075Sobrien  struct occr *occr;
431390075Sobrien  struct occr *avail;
431450397Sobrien
431550397Sobrien  /* For each available expression in the table, copy the result to
431650397Sobrien     `reaching_reg' if the expression reaches a deleted one.
431750397Sobrien
431850397Sobrien     ??? The current algorithm is rather brute force.
431950397Sobrien     Need to do some profiling.  */
432050397Sobrien
4321117395Skan  for (i = 0; i < expr_hash_table.size; i++)
4322117395Skan    for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
432390075Sobrien      {
432490075Sobrien	/* If the basic block isn't reachable, PPOUT will be TRUE.  However,
432590075Sobrien	   we don't want to insert a copy here because the expression may not
432690075Sobrien	   really be redundant.  So only insert an insn if the expression was
432790075Sobrien	   deleted.  This test also avoids further processing if the
432890075Sobrien	   expression wasn't deleted anywhere.  */
432990075Sobrien	if (expr->reaching_reg == NULL)
433090075Sobrien	  continue;
4331169689Skan
4332132718Skan	/* Set when we add a copy for that expression.  */
4333169689Skan	added_copy = 0;
433450397Sobrien
433590075Sobrien	for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
433690075Sobrien	  {
433790075Sobrien	    if (! occr->deleted_p)
433890075Sobrien	      continue;
433950397Sobrien
434090075Sobrien	    for (avail = expr->avail_occr; avail != NULL; avail = avail->next)
434190075Sobrien	      {
434290075Sobrien		rtx insn = avail->insn;
434350397Sobrien
434490075Sobrien		/* No need to handle this one if handled already.  */
434590075Sobrien		if (avail->copied_p)
434690075Sobrien		  continue;
434750397Sobrien
434890075Sobrien		/* Don't handle this one if it's a redundant one.  */
434990075Sobrien		if (TEST_BIT (pre_redundant_insns, INSN_CUID (insn)))
435090075Sobrien		  continue;
435150397Sobrien
435290075Sobrien		/* Or if the expression doesn't reach the deleted one.  */
4353117395Skan		if (! pre_expr_reaches_here_p (BLOCK_FOR_INSN (avail->insn),
435490075Sobrien					       expr,
435590075Sobrien					       BLOCK_FOR_INSN (occr->insn)))
435690075Sobrien		  continue;
435750397Sobrien
4358132718Skan                added_copy = 1;
4359132718Skan
436090075Sobrien		/* Copy the result of avail to reaching_reg.  */
436190075Sobrien		pre_insert_copy_insn (expr, insn);
436290075Sobrien		avail->copied_p = 1;
436390075Sobrien	      }
436490075Sobrien	  }
4365132718Skan
4366169689Skan	  if (added_copy)
4367132718Skan            update_ld_motion_stores (expr);
436890075Sobrien      }
436950397Sobrien}
437050397Sobrien
4371117395Skan/* Emit move from SRC to DEST noting the equivalence with expression computed
4372117395Skan   in INSN.  */
4373117395Skanstatic rtx
4374132718Skangcse_emit_move_after (rtx src, rtx dest, rtx insn)
4375117395Skan{
4376117395Skan  rtx new;
4377117395Skan  rtx set = single_set (insn), set2;
4378117395Skan  rtx note;
4379117395Skan  rtx eqv;
4380117395Skan
4381117395Skan  /* This should never fail since we're creating a reg->reg copy
4382117395Skan     we've verified to be valid.  */
4383117395Skan
4384117395Skan  new = emit_insn_after (gen_move_insn (dest, src), insn);
4385117395Skan
4386117395Skan  /* Note the equivalence for local CSE pass.  */
4387117395Skan  set2 = single_set (new);
4388117395Skan  if (!set2 || !rtx_equal_p (SET_DEST (set2), dest))
4389117395Skan    return new;
4390117395Skan  if ((note = find_reg_equal_equiv_note (insn)))
4391117395Skan    eqv = XEXP (note, 0);
4392117395Skan  else
4393117395Skan    eqv = SET_SRC (set);
4394117395Skan
4395117395Skan  set_unique_reg_note (new, REG_EQUAL, copy_insn_1 (eqv));
4396117395Skan
4397117395Skan  return new;
4398117395Skan}
4399117395Skan
440050397Sobrien/* Delete redundant computations.
440150397Sobrien   Deletion is done by changing the insn to copy the `reaching_reg' of
440250397Sobrien   the expression into the result of the SET.  It is left to later passes
440350397Sobrien   (cprop, cse2, flow, combine, regmove) to propagate the copy or eliminate it.
440450397Sobrien
4405117395Skan   Returns nonzero if a change is made.  */
440650397Sobrien
440750397Sobrienstatic int
4408132718Skanpre_delete (void)
440950397Sobrien{
441090075Sobrien  unsigned int i;
441190075Sobrien  int changed;
441290075Sobrien  struct expr *expr;
441390075Sobrien  struct occr *occr;
441450397Sobrien
441550397Sobrien  changed = 0;
4416117395Skan  for (i = 0; i < expr_hash_table.size; i++)
4417132718Skan    for (expr = expr_hash_table.table[i];
4418132718Skan	 expr != NULL;
4419132718Skan	 expr = expr->next_same_hash)
442090075Sobrien      {
442190075Sobrien	int indx = expr->bitmap_index;
442250397Sobrien
442390075Sobrien	/* We only need to search antic_occr since we require
442490075Sobrien	   ANTLOC != 0.  */
442550397Sobrien
442690075Sobrien	for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
442790075Sobrien	  {
442890075Sobrien	    rtx insn = occr->insn;
442990075Sobrien	    rtx set;
443090075Sobrien	    basic_block bb = BLOCK_FOR_INSN (insn);
443150397Sobrien
4432132718Skan	    /* We only delete insns that have a single_set.  */
4433132718Skan	    if (TEST_BIT (pre_delete_map[bb->index], indx)
4434132718Skan		&& (set = single_set (insn)) != 0)
443590075Sobrien	      {
443690075Sobrien		/* Create a pseudo-reg to store the result of reaching
443790075Sobrien		   expressions into.  Get the mode for the new pseudo from
443890075Sobrien		   the mode of the original destination pseudo.  */
443990075Sobrien		if (expr->reaching_reg == NULL)
444090075Sobrien		  expr->reaching_reg
444190075Sobrien		    = gen_reg_rtx (GET_MODE (SET_DEST (set)));
444250397Sobrien
4443117395Skan		gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
4444117395Skan		delete_insn (insn);
4445117395Skan		occr->deleted_p = 1;
4446117395Skan		SET_BIT (pre_redundant_insns, INSN_CUID (insn));
4447117395Skan		changed = 1;
4448117395Skan		gcse_subst_count++;
444950397Sobrien
4450169689Skan		if (dump_file)
445190075Sobrien		  {
4452169689Skan		    fprintf (dump_file,
445390075Sobrien			     "PRE: redundant insn %d (expression %d) in ",
445490075Sobrien			       INSN_UID (insn), indx);
4455169689Skan		    fprintf (dump_file, "bb %d, reaching reg is %d\n",
445690075Sobrien			     bb->index, REGNO (expr->reaching_reg));
445790075Sobrien		  }
445890075Sobrien	      }
445990075Sobrien	  }
446090075Sobrien      }
446150397Sobrien
446250397Sobrien  return changed;
446350397Sobrien}
446450397Sobrien
446550397Sobrien/* Perform GCSE optimizations using PRE.
446650397Sobrien   This is called by one_pre_gcse_pass after all the dataflow analysis
446750397Sobrien   has been done.
446850397Sobrien
446990075Sobrien   This is based on the original Morel-Renvoise paper Fred Chow's thesis, and
447090075Sobrien   lazy code motion from Knoop, Ruthing and Steffen as described in Advanced
447190075Sobrien   Compiler Design and Implementation.
447250397Sobrien
447390075Sobrien   ??? A new pseudo reg is created to hold the reaching expression.  The nice
447490075Sobrien   thing about the classical approach is that it would try to use an existing
447590075Sobrien   reg.  If the register can't be adequately optimized [i.e. we introduce
447690075Sobrien   reload problems], one could add a pass here to propagate the new register
447790075Sobrien   through the block.
447850397Sobrien
447990075Sobrien   ??? We don't handle single sets in PARALLELs because we're [currently] not
448090075Sobrien   able to copy the rest of the parallel when we insert copies to create full
448190075Sobrien   redundancies from partial redundancies.  However, there's no reason why we
448290075Sobrien   can't handle PARALLELs in the cases where there are no partial
448350397Sobrien   redundancies.  */
448450397Sobrien
448550397Sobrienstatic int
4486132718Skanpre_gcse (void)
448750397Sobrien{
448890075Sobrien  unsigned int i;
448990075Sobrien  int did_insert, changed;
449050397Sobrien  struct expr **index_map;
449190075Sobrien  struct expr *expr;
449250397Sobrien
449350397Sobrien  /* Compute a mapping from expression number (`bitmap_index') to
449450397Sobrien     hash table entry.  */
449550397Sobrien
4496169689Skan  index_map = XCNEWVEC (struct expr *, expr_hash_table.n_elems);
4497117395Skan  for (i = 0; i < expr_hash_table.size; i++)
4498117395Skan    for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
449990075Sobrien      index_map[expr->bitmap_index] = expr;
450050397Sobrien
450150397Sobrien  /* Reset bitmap used to track which insns are redundant.  */
450252284Sobrien  pre_redundant_insns = sbitmap_alloc (max_cuid);
450352284Sobrien  sbitmap_zero (pre_redundant_insns);
450450397Sobrien
450550397Sobrien  /* Delete the redundant insns first so that
450650397Sobrien     - we know what register to use for the new insns and for the other
450750397Sobrien       ones with reaching expressions
450850397Sobrien     - we know which insns are redundant when we go to create copies  */
450990075Sobrien
451050397Sobrien  changed = pre_delete ();
451150397Sobrien
451290075Sobrien  did_insert = pre_edge_insert (edge_list, index_map);
451350397Sobrien
451450397Sobrien  /* In other places with reaching expressions, copy the expression to the
451590075Sobrien     specially allocated pseudo-reg that reaches the redundant expr.  */
451650397Sobrien  pre_insert_copies ();
451790075Sobrien  if (did_insert)
451890075Sobrien    {
451990075Sobrien      commit_edge_insertions ();
452090075Sobrien      changed = 1;
452190075Sobrien    }
452250397Sobrien
452390075Sobrien  free (index_map);
452490075Sobrien  sbitmap_free (pre_redundant_insns);
452550397Sobrien  return changed;
452650397Sobrien}
452750397Sobrien
452850397Sobrien/* Top level routine to perform one PRE GCSE pass.
452950397Sobrien
4530117395Skan   Return nonzero if a change was made.  */
453150397Sobrien
453250397Sobrienstatic int
4533132718Skanone_pre_gcse_pass (int pass)
453450397Sobrien{
453550397Sobrien  int changed = 0;
453650397Sobrien
453750397Sobrien  gcse_subst_count = 0;
453850397Sobrien  gcse_create_count = 0;
453950397Sobrien
4540117395Skan  alloc_hash_table (max_cuid, &expr_hash_table, 0);
454190075Sobrien  add_noreturn_fake_exit_edges ();
454290075Sobrien  if (flag_gcse_lm)
454390075Sobrien    compute_ld_motion_mems ();
454490075Sobrien
4545117395Skan  compute_hash_table (&expr_hash_table);
454690075Sobrien  trim_ld_motion_mems ();
4547169689Skan  if (dump_file)
4548169689Skan    dump_hash_table (dump_file, "Expression", &expr_hash_table);
454990075Sobrien
4550117395Skan  if (expr_hash_table.n_elems > 0)
455150397Sobrien    {
4552117395Skan      alloc_pre_mem (last_basic_block, expr_hash_table.n_elems);
455350397Sobrien      compute_pre_data ();
455450397Sobrien      changed |= pre_gcse ();
455590075Sobrien      free_edge_list (edge_list);
455650397Sobrien      free_pre_mem ();
455750397Sobrien    }
455890075Sobrien
455990075Sobrien  free_ldst_mems ();
4560169689Skan  remove_fake_exit_edges ();
4561117395Skan  free_hash_table (&expr_hash_table);
456250397Sobrien
4563169689Skan  if (dump_file)
456450397Sobrien    {
4565169689Skan      fprintf (dump_file, "\nPRE GCSE of %s, pass %d: %d bytes needed, ",
4566132718Skan	       current_function_name (), pass, bytes_used);
4567169689Skan      fprintf (dump_file, "%d substs, %d insns created\n",
456890075Sobrien	       gcse_subst_count, gcse_create_count);
456950397Sobrien    }
457050397Sobrien
457150397Sobrien  return changed;
457250397Sobrien}
457350397Sobrien
457450397Sobrien/* If X contains any LABEL_REF's, add REG_LABEL notes for them to INSN.
457590075Sobrien   If notes are added to an insn which references a CODE_LABEL, the
457690075Sobrien   LABEL_NUSES count is incremented.  We have to add REG_LABEL notes,
457790075Sobrien   because the following loop optimization pass requires them.  */
457850397Sobrien
457950397Sobrien/* ??? If there was a jump optimization pass after gcse and before loop,
458050397Sobrien   then we would not need to do this here, because jump would add the
458150397Sobrien   necessary REG_LABEL notes.  */
458250397Sobrien
458350397Sobrienstatic void
4584132718Skanadd_label_notes (rtx x, rtx insn)
458550397Sobrien{
458650397Sobrien  enum rtx_code code = GET_CODE (x);
458750397Sobrien  int i, j;
458890075Sobrien  const char *fmt;
458950397Sobrien
459050397Sobrien  if (code == LABEL_REF && !LABEL_REF_NONLOCAL_P (x))
459150397Sobrien    {
459250397Sobrien      /* This code used to ignore labels that referred to dispatch tables to
4593132718Skan	 avoid flow generating (slightly) worse code.
459450397Sobrien
459552284Sobrien	 We no longer ignore such label references (see LABEL_REF handling in
459652284Sobrien	 mark_jump_label for additional information).  */
459790075Sobrien
459890075Sobrien      REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, XEXP (x, 0),
459950397Sobrien					    REG_NOTES (insn));
460090075Sobrien      if (LABEL_P (XEXP (x, 0)))
4601117395Skan	LABEL_NUSES (XEXP (x, 0))++;
460250397Sobrien      return;
460350397Sobrien    }
460450397Sobrien
460590075Sobrien  for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
460650397Sobrien    {
460750397Sobrien      if (fmt[i] == 'e')
460850397Sobrien	add_label_notes (XEXP (x, i), insn);
460950397Sobrien      else if (fmt[i] == 'E')
461050397Sobrien	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
461150397Sobrien	  add_label_notes (XVECEXP (x, i, j), insn);
461250397Sobrien    }
461350397Sobrien}
461452284Sobrien
461552284Sobrien/* Compute transparent outgoing information for each block.
461652284Sobrien
461752284Sobrien   An expression is transparent to an edge unless it is killed by
461852284Sobrien   the edge itself.  This can only happen with abnormal control flow,
461952284Sobrien   when the edge is traversed through a call.  This happens with
462052284Sobrien   non-local labels and exceptions.
462152284Sobrien
462252284Sobrien   This would not be necessary if we split the edge.  While this is
462352284Sobrien   normally impossible for abnormal critical edges, with some effort
462452284Sobrien   it should be possible with exception handling, since we still have
462552284Sobrien   control over which handler should be invoked.  But due to increased
462652284Sobrien   EH table sizes, this may not be worthwhile.  */
462752284Sobrien
462852284Sobrienstatic void
4629132718Skancompute_transpout (void)
463052284Sobrien{
4631117395Skan  basic_block bb;
463290075Sobrien  unsigned int i;
463390075Sobrien  struct expr *expr;
463452284Sobrien
4635117395Skan  sbitmap_vector_ones (transpout, last_basic_block);
463652284Sobrien
4637117395Skan  FOR_EACH_BB (bb)
463852284Sobrien    {
463952284Sobrien      /* Note that flow inserted a nop a the end of basic blocks that
464052284Sobrien	 end in call instructions for reasons other than abnormal
464152284Sobrien	 control flow.  */
4642169689Skan      if (! CALL_P (BB_END (bb)))
464352284Sobrien	continue;
464452284Sobrien
4645117395Skan      for (i = 0; i < expr_hash_table.size; i++)
4646117395Skan	for (expr = expr_hash_table.table[i]; expr ; expr = expr->next_same_hash)
4647169689Skan	  if (MEM_P (expr->expr))
464890075Sobrien	    {
464990075Sobrien	      if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF
465090075Sobrien		  && CONSTANT_POOL_ADDRESS_P (XEXP (expr->expr, 0)))
465190075Sobrien		continue;
4652117395Skan
465390075Sobrien	      /* ??? Optimally, we would use interprocedural alias
465490075Sobrien		 analysis to determine if this mem is actually killed
465590075Sobrien		 by this call.  */
4656117395Skan	      RESET_BIT (transpout[bb->index], expr->bitmap_index);
465790075Sobrien	    }
465890075Sobrien    }
465990075Sobrien}
466090075Sobrien
466190075Sobrien/* Code Hoisting variables and subroutines.  */
466290075Sobrien
466390075Sobrien/* Very busy expressions.  */
466490075Sobrienstatic sbitmap *hoist_vbein;
466590075Sobrienstatic sbitmap *hoist_vbeout;
466690075Sobrien
466790075Sobrien/* Hoistable expressions.  */
466890075Sobrienstatic sbitmap *hoist_exprs;
466990075Sobrien
467090075Sobrien/* ??? We could compute post dominators and run this algorithm in
4671117395Skan   reverse to perform tail merging, doing so would probably be
467290075Sobrien   more effective than the tail merging code in jump.c.
467390075Sobrien
467490075Sobrien   It's unclear if tail merging could be run in parallel with
467590075Sobrien   code hoisting.  It would be nice.  */
467690075Sobrien
467790075Sobrien/* Allocate vars used for code hoisting analysis.  */
467890075Sobrien
467990075Sobrienstatic void
4680132718Skanalloc_code_hoist_mem (int n_blocks, int n_exprs)
468190075Sobrien{
468290075Sobrien  antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
468390075Sobrien  transp = sbitmap_vector_alloc (n_blocks, n_exprs);
468490075Sobrien  comp = sbitmap_vector_alloc (n_blocks, n_exprs);
468590075Sobrien
468690075Sobrien  hoist_vbein = sbitmap_vector_alloc (n_blocks, n_exprs);
468790075Sobrien  hoist_vbeout = sbitmap_vector_alloc (n_blocks, n_exprs);
468890075Sobrien  hoist_exprs = sbitmap_vector_alloc (n_blocks, n_exprs);
468990075Sobrien  transpout = sbitmap_vector_alloc (n_blocks, n_exprs);
469090075Sobrien}
469190075Sobrien
469290075Sobrien/* Free vars used for code hoisting analysis.  */
469390075Sobrien
469490075Sobrienstatic void
4695132718Skanfree_code_hoist_mem (void)
469690075Sobrien{
469790075Sobrien  sbitmap_vector_free (antloc);
469890075Sobrien  sbitmap_vector_free (transp);
469990075Sobrien  sbitmap_vector_free (comp);
470090075Sobrien
470190075Sobrien  sbitmap_vector_free (hoist_vbein);
470290075Sobrien  sbitmap_vector_free (hoist_vbeout);
470390075Sobrien  sbitmap_vector_free (hoist_exprs);
470490075Sobrien  sbitmap_vector_free (transpout);
470590075Sobrien
4706132718Skan  free_dominance_info (CDI_DOMINATORS);
470790075Sobrien}
470890075Sobrien
470990075Sobrien/* Compute the very busy expressions at entry/exit from each block.
471090075Sobrien
471190075Sobrien   An expression is very busy if all paths from a given point
471290075Sobrien   compute the expression.  */
471390075Sobrien
471490075Sobrienstatic void
4715132718Skancompute_code_hoist_vbeinout (void)
471690075Sobrien{
4717117395Skan  int changed, passes;
4718117395Skan  basic_block bb;
471990075Sobrien
4720117395Skan  sbitmap_vector_zero (hoist_vbeout, last_basic_block);
4721117395Skan  sbitmap_vector_zero (hoist_vbein, last_basic_block);
472290075Sobrien
472390075Sobrien  passes = 0;
472490075Sobrien  changed = 1;
472590075Sobrien
472690075Sobrien  while (changed)
472790075Sobrien    {
472890075Sobrien      changed = 0;
472990075Sobrien
473090075Sobrien      /* We scan the blocks in the reverse order to speed up
473190075Sobrien	 the convergence.  */
4732117395Skan      FOR_EACH_BB_REVERSE (bb)
473390075Sobrien	{
4734117395Skan	  changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index], antloc[bb->index],
4735117395Skan					      hoist_vbeout[bb->index], transp[bb->index]);
4736117395Skan	  if (bb->next_bb != EXIT_BLOCK_PTR)
4737117395Skan	    sbitmap_intersection_of_succs (hoist_vbeout[bb->index], hoist_vbein, bb->index);
473890075Sobrien	}
473990075Sobrien
474090075Sobrien      passes++;
474190075Sobrien    }
474290075Sobrien
4743169689Skan  if (dump_file)
4744169689Skan    fprintf (dump_file, "hoisting vbeinout computation: %d passes\n", passes);
474590075Sobrien}
474690075Sobrien
474790075Sobrien/* Top level routine to do the dataflow analysis needed by code hoisting.  */
474890075Sobrien
474990075Sobrienstatic void
4750132718Skancompute_code_hoist_data (void)
475190075Sobrien{
4752117395Skan  compute_local_properties (transp, comp, antloc, &expr_hash_table);
475390075Sobrien  compute_transpout ();
475490075Sobrien  compute_code_hoist_vbeinout ();
4755132718Skan  calculate_dominance_info (CDI_DOMINATORS);
4756169689Skan  if (dump_file)
4757169689Skan    fprintf (dump_file, "\n");
475890075Sobrien}
475990075Sobrien
476090075Sobrien/* Determine if the expression identified by EXPR_INDEX would
476190075Sobrien   reach BB unimpared if it was placed at the end of EXPR_BB.
476290075Sobrien
476390075Sobrien   It's unclear exactly what Muchnick meant by "unimpared".  It seems
476490075Sobrien   to me that the expression must either be computed or transparent in
476590075Sobrien   *every* block in the path(s) from EXPR_BB to BB.  Any other definition
476690075Sobrien   would allow the expression to be hoisted out of loops, even if
476790075Sobrien   the expression wasn't a loop invariant.
476890075Sobrien
476990075Sobrien   Contrast this to reachability for PRE where an expression is
477090075Sobrien   considered reachable if *any* path reaches instead of *all*
477190075Sobrien   paths.  */
477290075Sobrien
477390075Sobrienstatic int
4774132718Skanhoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb, char *visited)
477590075Sobrien{
477690075Sobrien  edge pred;
4777169689Skan  edge_iterator ei;
477890075Sobrien  int visited_allocated_locally = 0;
477990075Sobrien
4780117395Skan
478190075Sobrien  if (visited == NULL)
478290075Sobrien    {
478390075Sobrien      visited_allocated_locally = 1;
4784169689Skan      visited = XCNEWVEC (char, last_basic_block);
478590075Sobrien    }
478690075Sobrien
4787169689Skan  FOR_EACH_EDGE (pred, ei, bb->preds)
478890075Sobrien    {
478990075Sobrien      basic_block pred_bb = pred->src;
479090075Sobrien
479190075Sobrien      if (pred->src == ENTRY_BLOCK_PTR)
479290075Sobrien	break;
4793117395Skan      else if (pred_bb == expr_bb)
4794117395Skan	continue;
479590075Sobrien      else if (visited[pred_bb->index])
479690075Sobrien	continue;
479790075Sobrien
479890075Sobrien      /* Does this predecessor generate this expression?  */
479990075Sobrien      else if (TEST_BIT (comp[pred_bb->index], expr_index))
480090075Sobrien	break;
480190075Sobrien      else if (! TEST_BIT (transp[pred_bb->index], expr_index))
480290075Sobrien	break;
480390075Sobrien
480490075Sobrien      /* Not killed.  */
480590075Sobrien      else
480690075Sobrien	{
480790075Sobrien	  visited[pred_bb->index] = 1;
480890075Sobrien	  if (! hoist_expr_reaches_here_p (expr_bb, expr_index,
480990075Sobrien					   pred_bb, visited))
481090075Sobrien	    break;
481190075Sobrien	}
481290075Sobrien    }
4813117395Skan  if (visited_allocated_locally)
481490075Sobrien    free (visited);
481590075Sobrien
481690075Sobrien  return (pred == NULL);
481790075Sobrien}
481890075Sobrien
481990075Sobrien/* Actually perform code hoisting.  */
482090075Sobrien
482190075Sobrienstatic void
4822132718Skanhoist_code (void)
482390075Sobrien{
4824117395Skan  basic_block bb, dominated;
4825117395Skan  basic_block *domby;
4826117395Skan  unsigned int domby_len;
4827117395Skan  unsigned int i,j;
482890075Sobrien  struct expr **index_map;
482990075Sobrien  struct expr *expr;
483090075Sobrien
4831117395Skan  sbitmap_vector_zero (hoist_exprs, last_basic_block);
483290075Sobrien
483390075Sobrien  /* Compute a mapping from expression number (`bitmap_index') to
483490075Sobrien     hash table entry.  */
483590075Sobrien
4836169689Skan  index_map = XCNEWVEC (struct expr *, expr_hash_table.n_elems);
4837117395Skan  for (i = 0; i < expr_hash_table.size; i++)
4838117395Skan    for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
483990075Sobrien      index_map[expr->bitmap_index] = expr;
484090075Sobrien
484190075Sobrien  /* Walk over each basic block looking for potentially hoistable
484290075Sobrien     expressions, nothing gets hoisted from the entry block.  */
4843117395Skan  FOR_EACH_BB (bb)
484490075Sobrien    {
484590075Sobrien      int found = 0;
484690075Sobrien      int insn_inserted_p;
484790075Sobrien
4848132718Skan      domby_len = get_dominated_by (CDI_DOMINATORS, bb, &domby);
484990075Sobrien      /* Examine each expression that is very busy at the exit of this
485090075Sobrien	 block.  These are the potentially hoistable expressions.  */
4851117395Skan      for (i = 0; i < hoist_vbeout[bb->index]->n_bits; i++)
485290075Sobrien	{
485390075Sobrien	  int hoistable = 0;
485490075Sobrien
4855117395Skan	  if (TEST_BIT (hoist_vbeout[bb->index], i)
4856117395Skan	      && TEST_BIT (transpout[bb->index], i))
485790075Sobrien	    {
485890075Sobrien	      /* We've found a potentially hoistable expression, now
485990075Sobrien		 we look at every block BB dominates to see if it
486090075Sobrien		 computes the expression.  */
4861117395Skan	      for (j = 0; j < domby_len; j++)
486290075Sobrien		{
4863117395Skan		  dominated = domby[j];
486490075Sobrien		  /* Ignore self dominance.  */
4865117395Skan		  if (bb == dominated)
486690075Sobrien		    continue;
486790075Sobrien		  /* We've found a dominated block, now see if it computes
486890075Sobrien		     the busy expression and whether or not moving that
486990075Sobrien		     expression to the "beginning" of that block is safe.  */
4870117395Skan		  if (!TEST_BIT (antloc[dominated->index], i))
487190075Sobrien		    continue;
487290075Sobrien
487390075Sobrien		  /* Note if the expression would reach the dominated block
4874117395Skan		     unimpared if it was placed at the end of BB.
487590075Sobrien
487690075Sobrien		     Keep track of how many times this expression is hoistable
487790075Sobrien		     from a dominated block into BB.  */
4878117395Skan		  if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
487990075Sobrien		    hoistable++;
488090075Sobrien		}
488190075Sobrien
488290075Sobrien	      /* If we found more than one hoistable occurrence of this
488390075Sobrien		 expression, then note it in the bitmap of expressions to
488490075Sobrien		 hoist.  It makes no sense to hoist things which are computed
488590075Sobrien		 in only one BB, and doing so tends to pessimize register
488690075Sobrien		 allocation.  One could increase this value to try harder
488790075Sobrien		 to avoid any possible code expansion due to register
488890075Sobrien		 allocation issues; however experiments have shown that
488990075Sobrien		 the vast majority of hoistable expressions are only movable
4890132718Skan		 from two successors, so raising this threshold is likely
489190075Sobrien		 to nullify any benefit we get from code hoisting.  */
489290075Sobrien	      if (hoistable > 1)
489390075Sobrien		{
4894117395Skan		  SET_BIT (hoist_exprs[bb->index], i);
489590075Sobrien		  found = 1;
489690075Sobrien		}
489790075Sobrien	    }
489890075Sobrien	}
489990075Sobrien      /* If we found nothing to hoist, then quit now.  */
490090075Sobrien      if (! found)
4901117395Skan        {
4902132718Skan	  free (domby);
490390075Sobrien	continue;
4904117395Skan	}
490590075Sobrien
490690075Sobrien      /* Loop over all the hoistable expressions.  */
4907117395Skan      for (i = 0; i < hoist_exprs[bb->index]->n_bits; i++)
490890075Sobrien	{
490990075Sobrien	  /* We want to insert the expression into BB only once, so
491090075Sobrien	     note when we've inserted it.  */
491190075Sobrien	  insn_inserted_p = 0;
491290075Sobrien
491390075Sobrien	  /* These tests should be the same as the tests above.  */
4914161651Skan	  if (TEST_BIT (hoist_exprs[bb->index], i))
491590075Sobrien	    {
491690075Sobrien	      /* We've found a potentially hoistable expression, now
491790075Sobrien		 we look at every block BB dominates to see if it
491890075Sobrien		 computes the expression.  */
4919117395Skan	      for (j = 0; j < domby_len; j++)
492090075Sobrien		{
4921117395Skan		  dominated = domby[j];
492290075Sobrien		  /* Ignore self dominance.  */
4923117395Skan		  if (bb == dominated)
492490075Sobrien		    continue;
492590075Sobrien
492690075Sobrien		  /* We've found a dominated block, now see if it computes
492790075Sobrien		     the busy expression and whether or not moving that
492890075Sobrien		     expression to the "beginning" of that block is safe.  */
4929117395Skan		  if (!TEST_BIT (antloc[dominated->index], i))
493090075Sobrien		    continue;
493190075Sobrien
493290075Sobrien		  /* The expression is computed in the dominated block and
493390075Sobrien		     it would be safe to compute it at the start of the
493490075Sobrien		     dominated block.  Now we have to determine if the
493590075Sobrien		     expression would reach the dominated block if it was
493690075Sobrien		     placed at the end of BB.  */
4937117395Skan		  if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
493890075Sobrien		    {
493990075Sobrien		      struct expr *expr = index_map[i];
494090075Sobrien		      struct occr *occr = expr->antic_occr;
494190075Sobrien		      rtx insn;
494290075Sobrien		      rtx set;
494390075Sobrien
494490075Sobrien		      /* Find the right occurrence of this expression.  */
4945117395Skan		      while (BLOCK_FOR_INSN (occr->insn) != dominated && occr)
494690075Sobrien			occr = occr->next;
494790075Sobrien
4948169689Skan		      gcc_assert (occr);
494990075Sobrien		      insn = occr->insn;
495090075Sobrien		      set = single_set (insn);
4951169689Skan		      gcc_assert (set);
495290075Sobrien
495390075Sobrien		      /* Create a pseudo-reg to store the result of reaching
495490075Sobrien			 expressions into.  Get the mode for the new pseudo
495590075Sobrien			 from the mode of the original destination pseudo.  */
495690075Sobrien		      if (expr->reaching_reg == NULL)
495790075Sobrien			expr->reaching_reg
495890075Sobrien			  = gen_reg_rtx (GET_MODE (SET_DEST (set)));
495990075Sobrien
4960117395Skan		      gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
4961117395Skan		      delete_insn (insn);
4962117395Skan		      occr->deleted_p = 1;
4963117395Skan		      if (!insn_inserted_p)
496490075Sobrien			{
4965117395Skan			  insert_insn_end_bb (index_map[i], bb, 0);
4966117395Skan			  insn_inserted_p = 1;
496790075Sobrien			}
496890075Sobrien		    }
496990075Sobrien		}
497090075Sobrien	    }
497152284Sobrien	}
4972117395Skan      free (domby);
497352284Sobrien    }
497490075Sobrien
497590075Sobrien  free (index_map);
497652284Sobrien}
497790075Sobrien
497890075Sobrien/* Top level routine to perform one code hoisting (aka unification) pass
497990075Sobrien
4980117395Skan   Return nonzero if a change was made.  */
498190075Sobrien
498290075Sobrienstatic int
4983132718Skanone_code_hoisting_pass (void)
498490075Sobrien{
498590075Sobrien  int changed = 0;
498690075Sobrien
4987117395Skan  alloc_hash_table (max_cuid, &expr_hash_table, 0);
4988117395Skan  compute_hash_table (&expr_hash_table);
4989169689Skan  if (dump_file)
4990169689Skan    dump_hash_table (dump_file, "Code Hosting Expressions", &expr_hash_table);
499190075Sobrien
4992117395Skan  if (expr_hash_table.n_elems > 0)
499390075Sobrien    {
4994117395Skan      alloc_code_hoist_mem (last_basic_block, expr_hash_table.n_elems);
499590075Sobrien      compute_code_hoist_data ();
499690075Sobrien      hoist_code ();
499790075Sobrien      free_code_hoist_mem ();
499890075Sobrien    }
499990075Sobrien
5000117395Skan  free_hash_table (&expr_hash_table);
500190075Sobrien
500290075Sobrien  return changed;
500390075Sobrien}
500490075Sobrien
500590075Sobrien/*  Here we provide the things required to do store motion towards
500690075Sobrien    the exit. In order for this to be effective, gcse also needed to
500790075Sobrien    be taught how to move a load when it is kill only by a store to itself.
500890075Sobrien
500990075Sobrien	    int i;
501090075Sobrien	    float a[10];
501190075Sobrien
501290075Sobrien	    void foo(float scale)
501390075Sobrien	    {
501490075Sobrien	      for (i=0; i<10; i++)
501590075Sobrien		a[i] *= scale;
501690075Sobrien	    }
501790075Sobrien
501890075Sobrien    'i' is both loaded and stored to in the loop. Normally, gcse cannot move
5019117395Skan    the load out since its live around the loop, and stored at the bottom
5020117395Skan    of the loop.
502190075Sobrien
5022117395Skan      The 'Load Motion' referred to and implemented in this file is
502390075Sobrien    an enhancement to gcse which when using edge based lcm, recognizes
502490075Sobrien    this situation and allows gcse to move the load out of the loop.
502590075Sobrien
502690075Sobrien      Once gcse has hoisted the load, store motion can then push this
502790075Sobrien    load towards the exit, and we end up with no loads or stores of 'i'
502890075Sobrien    in the loop.  */
502990075Sobrien
5030169689Skanstatic hashval_t
5031169689Skanpre_ldst_expr_hash (const void *p)
5032169689Skan{
5033169689Skan  int do_not_record_p = 0;
5034169689Skan  const struct ls_expr *x = p;
5035169689Skan  return hash_rtx (x->pattern, GET_MODE (x->pattern), &do_not_record_p, NULL, false);
5036169689Skan}
5037169689Skan
5038169689Skanstatic int
5039169689Skanpre_ldst_expr_eq (const void *p1, const void *p2)
5040169689Skan{
5041169689Skan  const struct ls_expr *ptr1 = p1, *ptr2 = p2;
5042169689Skan  return expr_equiv_p (ptr1->pattern, ptr2->pattern);
5043169689Skan}
5044169689Skan
504590075Sobrien/* This will search the ldst list for a matching expression. If it
504690075Sobrien   doesn't find one, we create one and initialize it.  */
504790075Sobrien
504890075Sobrienstatic struct ls_expr *
5049132718Skanldst_entry (rtx x)
505090075Sobrien{
5051132718Skan  int do_not_record_p = 0;
505290075Sobrien  struct ls_expr * ptr;
5053132718Skan  unsigned int hash;
5054169689Skan  void **slot;
5055169689Skan  struct ls_expr e;
505690075Sobrien
5057169689Skan  hash = hash_rtx (x, GET_MODE (x), &do_not_record_p,
5058169689Skan		   NULL,  /*have_reg_qty=*/false);
505990075Sobrien
5060169689Skan  e.pattern = x;
5061169689Skan  slot = htab_find_slot_with_hash (pre_ldst_table, &e, hash, INSERT);
5062169689Skan  if (*slot)
5063169689Skan    return (struct ls_expr *)*slot;
506490075Sobrien
5065169689Skan  ptr = XNEW (struct ls_expr);
5066117395Skan
5067132718Skan  ptr->next         = pre_ldst_mems;
5068132718Skan  ptr->expr         = NULL;
5069132718Skan  ptr->pattern      = x;
5070132718Skan  ptr->pattern_regs = NULL_RTX;
5071132718Skan  ptr->loads        = NULL_RTX;
5072132718Skan  ptr->stores       = NULL_RTX;
5073132718Skan  ptr->reaching_reg = NULL_RTX;
5074132718Skan  ptr->invalid      = 0;
5075132718Skan  ptr->index        = 0;
5076132718Skan  ptr->hash_index   = hash;
5077132718Skan  pre_ldst_mems     = ptr;
5078169689Skan  *slot = ptr;
5079132718Skan
508090075Sobrien  return ptr;
508190075Sobrien}
508290075Sobrien
508390075Sobrien/* Free up an individual ldst entry.  */
508490075Sobrien
5085117395Skanstatic void
5086132718Skanfree_ldst_entry (struct ls_expr * ptr)
508790075Sobrien{
508890075Sobrien  free_INSN_LIST_list (& ptr->loads);
508990075Sobrien  free_INSN_LIST_list (& ptr->stores);
509090075Sobrien
509190075Sobrien  free (ptr);
509290075Sobrien}
509390075Sobrien
509490075Sobrien/* Free up all memory associated with the ldst list.  */
509590075Sobrien
509690075Sobrienstatic void
5097132718Skanfree_ldst_mems (void)
509890075Sobrien{
5099169689Skan  if (pre_ldst_table)
5100169689Skan    htab_delete (pre_ldst_table);
5101169689Skan  pre_ldst_table = NULL;
5102169689Skan
5103117395Skan  while (pre_ldst_mems)
510490075Sobrien    {
510590075Sobrien      struct ls_expr * tmp = pre_ldst_mems;
510690075Sobrien
510790075Sobrien      pre_ldst_mems = pre_ldst_mems->next;
510890075Sobrien
510990075Sobrien      free_ldst_entry (tmp);
511090075Sobrien    }
511190075Sobrien
511290075Sobrien  pre_ldst_mems = NULL;
511390075Sobrien}
511490075Sobrien
511590075Sobrien/* Dump debugging info about the ldst list.  */
511690075Sobrien
511790075Sobrienstatic void
5118132718Skanprint_ldst_list (FILE * file)
511990075Sobrien{
512090075Sobrien  struct ls_expr * ptr;
512190075Sobrien
512290075Sobrien  fprintf (file, "LDST list: \n");
512390075Sobrien
512490075Sobrien  for (ptr = first_ls_expr(); ptr != NULL; ptr = next_ls_expr (ptr))
512590075Sobrien    {
512690075Sobrien      fprintf (file, "  Pattern (%3d): ", ptr->index);
512790075Sobrien
512890075Sobrien      print_rtl (file, ptr->pattern);
512990075Sobrien
513090075Sobrien      fprintf (file, "\n	 Loads : ");
513190075Sobrien
513290075Sobrien      if (ptr->loads)
513390075Sobrien	print_rtl (file, ptr->loads);
513490075Sobrien      else
513590075Sobrien	fprintf (file, "(nil)");
513690075Sobrien
513790075Sobrien      fprintf (file, "\n	Stores : ");
513890075Sobrien
513990075Sobrien      if (ptr->stores)
514090075Sobrien	print_rtl (file, ptr->stores);
514190075Sobrien      else
514290075Sobrien	fprintf (file, "(nil)");
514390075Sobrien
514490075Sobrien      fprintf (file, "\n\n");
514590075Sobrien    }
514690075Sobrien
514790075Sobrien  fprintf (file, "\n");
514890075Sobrien}
514990075Sobrien
515090075Sobrien/* Returns 1 if X is in the list of ldst only expressions.  */
515190075Sobrien
515290075Sobrienstatic struct ls_expr *
5153132718Skanfind_rtx_in_ldst (rtx x)
515490075Sobrien{
5155169689Skan  struct ls_expr e;
5156169689Skan  void **slot;
5157169689Skan  if (!pre_ldst_table)
5158169689Skan    return NULL;
5159169689Skan  e.pattern = x;
5160169689Skan  slot = htab_find_slot (pre_ldst_table, &e, NO_INSERT);
5161169689Skan  if (!slot || ((struct ls_expr *)*slot)->invalid)
5162169689Skan    return NULL;
5163169689Skan  return *slot;
516490075Sobrien}
516590075Sobrien
516690075Sobrien/* Assign each element of the list of mems a monotonically increasing value.  */
516790075Sobrien
516890075Sobrienstatic int
5169132718Skanenumerate_ldsts (void)
517090075Sobrien{
517190075Sobrien  struct ls_expr * ptr;
517290075Sobrien  int n = 0;
517390075Sobrien
517490075Sobrien  for (ptr = pre_ldst_mems; ptr != NULL; ptr = ptr->next)
517590075Sobrien    ptr->index = n++;
517690075Sobrien
517790075Sobrien  return n;
517890075Sobrien}
517990075Sobrien
518090075Sobrien/* Return first item in the list.  */
518190075Sobrien
518290075Sobrienstatic inline struct ls_expr *
5183132718Skanfirst_ls_expr (void)
518490075Sobrien{
518590075Sobrien  return pre_ldst_mems;
518690075Sobrien}
518790075Sobrien
5188132718Skan/* Return the next item in the list after the specified one.  */
518990075Sobrien
519090075Sobrienstatic inline struct ls_expr *
5191132718Skannext_ls_expr (struct ls_expr * ptr)
519290075Sobrien{
519390075Sobrien  return ptr->next;
519490075Sobrien}
519590075Sobrien
519690075Sobrien/* Load Motion for loads which only kill themselves.  */
519790075Sobrien
519890075Sobrien/* Return true if x is a simple MEM operation, with no registers or
519990075Sobrien   side effects. These are the types of loads we consider for the
520090075Sobrien   ld_motion list, otherwise we let the usual aliasing take care of it.  */
520190075Sobrien
5202117395Skanstatic int
5203132718Skansimple_mem (rtx x)
520490075Sobrien{
5205169689Skan  if (! MEM_P (x))
520690075Sobrien    return 0;
5207117395Skan
520890075Sobrien  if (MEM_VOLATILE_P (x))
520990075Sobrien    return 0;
5210117395Skan
521190075Sobrien  if (GET_MODE (x) == BLKmode)
521290075Sobrien    return 0;
521390075Sobrien
5214132718Skan  /* If we are handling exceptions, we must be careful with memory references
5215132718Skan     that may trap. If we are not, the behavior is undefined, so we may just
5216132718Skan     continue.  */
5217132718Skan  if (flag_non_call_exceptions && may_trap_p (x))
5218132718Skan    return 0;
5219117395Skan
5220132718Skan  if (side_effects_p (x))
5221132718Skan    return 0;
5222132718Skan
5223132718Skan  /* Do not consider function arguments passed on stack.  */
5224132718Skan  if (reg_mentioned_p (stack_pointer_rtx, x))
5225132718Skan    return 0;
5226132718Skan
5227132718Skan  if (flag_float_store && FLOAT_MODE_P (GET_MODE (x)))
5228132718Skan    return 0;
5229132718Skan
5230132718Skan  return 1;
523190075Sobrien}
523290075Sobrien
5233117395Skan/* Make sure there isn't a buried reference in this pattern anywhere.
5234117395Skan   If there is, invalidate the entry for it since we're not capable
5235117395Skan   of fixing it up just yet.. We have to be sure we know about ALL
523690075Sobrien   loads since the aliasing code will allow all entries in the
523790075Sobrien   ld_motion list to not-alias itself.  If we miss a load, we will get
5238117395Skan   the wrong value since gcse might common it and we won't know to
523990075Sobrien   fix it up.  */
524090075Sobrien
524190075Sobrienstatic void
5242132718Skaninvalidate_any_buried_refs (rtx x)
524390075Sobrien{
524490075Sobrien  const char * fmt;
524590075Sobrien  int i, j;
524690075Sobrien  struct ls_expr * ptr;
524790075Sobrien
524890075Sobrien  /* Invalidate it in the list.  */
5249169689Skan  if (MEM_P (x) && simple_mem (x))
525090075Sobrien    {
525190075Sobrien      ptr = ldst_entry (x);
525290075Sobrien      ptr->invalid = 1;
525390075Sobrien    }
525490075Sobrien
525590075Sobrien  /* Recursively process the insn.  */
525690075Sobrien  fmt = GET_RTX_FORMAT (GET_CODE (x));
5257117395Skan
525890075Sobrien  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
525990075Sobrien    {
526090075Sobrien      if (fmt[i] == 'e')
526190075Sobrien	invalidate_any_buried_refs (XEXP (x, i));
526290075Sobrien      else if (fmt[i] == 'E')
526390075Sobrien	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
526490075Sobrien	  invalidate_any_buried_refs (XVECEXP (x, i, j));
526590075Sobrien    }
526690075Sobrien}
526790075Sobrien
5268132718Skan/* Find all the 'simple' MEMs which are used in LOADs and STORES.  Simple
5269132718Skan   being defined as MEM loads and stores to symbols, with no side effects
5270132718Skan   and no registers in the expression.  For a MEM destination, we also
5271132718Skan   check that the insn is still valid if we replace the destination with a
5272132718Skan   REG, as is done in update_ld_motion_stores.  If there are any uses/defs
5273132718Skan   which don't match this criteria, they are invalidated and trimmed out
5274132718Skan   later.  */
527590075Sobrien
5276117395Skanstatic void
5277132718Skancompute_ld_motion_mems (void)
527890075Sobrien{
527990075Sobrien  struct ls_expr * ptr;
5280117395Skan  basic_block bb;
528190075Sobrien  rtx insn;
5282117395Skan
528390075Sobrien  pre_ldst_mems = NULL;
5284169689Skan  pre_ldst_table = htab_create (13, pre_ldst_expr_hash,
5285169689Skan				pre_ldst_expr_eq, NULL);
528690075Sobrien
5287117395Skan  FOR_EACH_BB (bb)
528890075Sobrien    {
5289169689Skan      FOR_BB_INSNS (bb, insn)
529090075Sobrien	{
5291132718Skan	  if (INSN_P (insn))
529290075Sobrien	    {
529390075Sobrien	      if (GET_CODE (PATTERN (insn)) == SET)
529490075Sobrien		{
529590075Sobrien		  rtx src = SET_SRC (PATTERN (insn));
529690075Sobrien		  rtx dest = SET_DEST (PATTERN (insn));
529790075Sobrien
529890075Sobrien		  /* Check for a simple LOAD...  */
5299169689Skan		  if (MEM_P (src) && simple_mem (src))
530090075Sobrien		    {
530190075Sobrien		      ptr = ldst_entry (src);
5302169689Skan		      if (REG_P (dest))
530390075Sobrien			ptr->loads = alloc_INSN_LIST (insn, ptr->loads);
530490075Sobrien		      else
530590075Sobrien			ptr->invalid = 1;
530690075Sobrien		    }
530790075Sobrien		  else
530890075Sobrien		    {
530990075Sobrien		      /* Make sure there isn't a buried load somewhere.  */
531090075Sobrien		      invalidate_any_buried_refs (src);
531190075Sobrien		    }
5312117395Skan
531390075Sobrien		  /* Check for stores. Don't worry about aliased ones, they
531490075Sobrien		     will block any movement we might do later. We only care
531590075Sobrien		     about this exact pattern since those are the only
531690075Sobrien		     circumstance that we will ignore the aliasing info.  */
5317169689Skan		  if (MEM_P (dest) && simple_mem (dest))
531890075Sobrien		    {
531990075Sobrien		      ptr = ldst_entry (dest);
5320117395Skan
5321169689Skan		      if (! MEM_P (src)
5322132718Skan			  && GET_CODE (src) != ASM_OPERANDS
5323132718Skan			  /* Check for REG manually since want_to_gcse_p
5324132718Skan			     returns 0 for all REGs.  */
5325169689Skan			  && can_assign_to_reg_p (src))
532690075Sobrien			ptr->stores = alloc_INSN_LIST (insn, ptr->stores);
532790075Sobrien		      else
532890075Sobrien			ptr->invalid = 1;
532990075Sobrien		    }
533090075Sobrien		}
533190075Sobrien	      else
533290075Sobrien		invalidate_any_buried_refs (PATTERN (insn));
533390075Sobrien	    }
533490075Sobrien	}
533590075Sobrien    }
533690075Sobrien}
533790075Sobrien
5338117395Skan/* Remove any references that have been either invalidated or are not in the
533990075Sobrien   expression list for pre gcse.  */
534090075Sobrien
534190075Sobrienstatic void
5342132718Skantrim_ld_motion_mems (void)
534390075Sobrien{
5344132718Skan  struct ls_expr * * last = & pre_ldst_mems;
5345132718Skan  struct ls_expr * ptr = pre_ldst_mems;
534690075Sobrien
534790075Sobrien  while (ptr != NULL)
534890075Sobrien    {
5349132718Skan      struct expr * expr;
5350117395Skan
535190075Sobrien      /* Delete if entry has been made invalid.  */
5352132718Skan      if (! ptr->invalid)
535390075Sobrien	{
535490075Sobrien	  /* Delete if we cannot find this mem in the expression list.  */
5355132718Skan	  unsigned int hash = ptr->hash_index % expr_hash_table.size;
5356117395Skan
5357132718Skan	  for (expr = expr_hash_table.table[hash];
5358132718Skan	       expr != NULL;
5359132718Skan	       expr = expr->next_same_hash)
5360132718Skan	    if (expr_equiv_p (expr->expr, ptr->pattern))
5361132718Skan	      break;
536290075Sobrien	}
536390075Sobrien      else
5364132718Skan	expr = (struct expr *) 0;
5365132718Skan
5366132718Skan      if (expr)
536790075Sobrien	{
536890075Sobrien	  /* Set the expression field if we are keeping it.  */
536990075Sobrien	  ptr->expr = expr;
5370132718Skan	  last = & ptr->next;
537190075Sobrien	  ptr = ptr->next;
537290075Sobrien	}
5373132718Skan      else
5374132718Skan	{
5375132718Skan	  *last = ptr->next;
5376169689Skan	  htab_remove_elt_with_hash (pre_ldst_table, ptr, ptr->hash_index);
5377132718Skan	  free_ldst_entry (ptr);
5378132718Skan	  ptr = * last;
5379132718Skan	}
538090075Sobrien    }
538190075Sobrien
538290075Sobrien  /* Show the world what we've found.  */
5383169689Skan  if (dump_file && pre_ldst_mems != NULL)
5384169689Skan    print_ldst_list (dump_file);
538590075Sobrien}
538690075Sobrien
538790075Sobrien/* This routine will take an expression which we are replacing with
538890075Sobrien   a reaching register, and update any stores that are needed if
538990075Sobrien   that expression is in the ld_motion list.  Stores are updated by
5390132718Skan   copying their SRC to the reaching register, and then storing
539190075Sobrien   the reaching register into the store location. These keeps the
539290075Sobrien   correct value in the reaching register for the loads.  */
539390075Sobrien
539490075Sobrienstatic void
5395132718Skanupdate_ld_motion_stores (struct expr * expr)
539690075Sobrien{
539790075Sobrien  struct ls_expr * mem_ptr;
539890075Sobrien
539990075Sobrien  if ((mem_ptr = find_rtx_in_ldst (expr->expr)))
540090075Sobrien    {
5401117395Skan      /* We can try to find just the REACHED stores, but is shouldn't
5402117395Skan	 matter to set the reaching reg everywhere...  some might be
540390075Sobrien	 dead and should be eliminated later.  */
540490075Sobrien
5405132718Skan      /* We replace (set mem expr) with (set reg expr) (set mem reg)
5406132718Skan	 where reg is the reaching reg used in the load.  We checked in
5407132718Skan	 compute_ld_motion_mems that we can replace (set mem expr) with
5408132718Skan	 (set reg expr) in that insn.  */
540990075Sobrien      rtx list = mem_ptr->stores;
5410117395Skan
541190075Sobrien      for ( ; list != NULL_RTX; list = XEXP (list, 1))
541290075Sobrien	{
541390075Sobrien	  rtx insn = XEXP (list, 0);
541490075Sobrien	  rtx pat = PATTERN (insn);
541590075Sobrien	  rtx src = SET_SRC (pat);
541690075Sobrien	  rtx reg = expr->reaching_reg;
541790075Sobrien	  rtx copy, new;
541890075Sobrien
541990075Sobrien	  /* If we've already copied it, continue.  */
542090075Sobrien	  if (expr->reaching_reg == src)
542190075Sobrien	    continue;
5422117395Skan
5423169689Skan	  if (dump_file)
542490075Sobrien	    {
5425169689Skan	      fprintf (dump_file, "PRE:  store updated with reaching reg ");
5426169689Skan	      print_rtl (dump_file, expr->reaching_reg);
5427169689Skan	      fprintf (dump_file, ":\n	");
5428169689Skan	      print_inline_rtx (dump_file, insn, 8);
5429169689Skan	      fprintf (dump_file, "\n");
543090075Sobrien	    }
5431117395Skan
5432132718Skan	  copy = gen_move_insn ( reg, copy_rtx (SET_SRC (pat)));
543390075Sobrien	  new = emit_insn_before (copy, insn);
543490075Sobrien	  record_one_set (REGNO (reg), new);
543590075Sobrien	  SET_SRC (pat) = reg;
543690075Sobrien
543790075Sobrien	  /* un-recognize this pattern since it's probably different now.  */
543890075Sobrien	  INSN_CODE (insn) = -1;
543990075Sobrien	  gcse_create_count++;
544090075Sobrien	}
544190075Sobrien    }
544290075Sobrien}
544390075Sobrien
544490075Sobrien/* Store motion code.  */
544590075Sobrien
5446132718Skan#define ANTIC_STORE_LIST(x)		((x)->loads)
5447132718Skan#define AVAIL_STORE_LIST(x)		((x)->stores)
5448132718Skan#define LAST_AVAIL_CHECK_FAILURE(x)	((x)->reaching_reg)
5449132718Skan
5450117395Skan/* This is used to communicate the target bitvector we want to use in the
545190075Sobrien   reg_set_info routine when called via the note_stores mechanism.  */
5452132718Skanstatic int * regvec;
545390075Sobrien
5454132718Skan/* And current insn, for the same routine.  */
5455132718Skanstatic rtx compute_store_table_current_insn;
5456132718Skan
545790075Sobrien/* Used in computing the reverse edge graph bit vectors.  */
545890075Sobrienstatic sbitmap * st_antloc;
545990075Sobrien
546090075Sobrien/* Global holding the number of store expressions we are dealing with.  */
546190075Sobrienstatic int num_stores;
546290075Sobrien
5463132718Skan/* Checks to set if we need to mark a register set.  Called from
5464132718Skan   note_stores.  */
546590075Sobrien
546690075Sobrienstatic void
5467132718Skanreg_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED,
5468132718Skan	      void *data)
546990075Sobrien{
5470132718Skan  sbitmap bb_reg = data;
5471132718Skan
547290075Sobrien  if (GET_CODE (dest) == SUBREG)
547390075Sobrien    dest = SUBREG_REG (dest);
547490075Sobrien
5475169689Skan  if (REG_P (dest))
5476132718Skan    {
5477132718Skan      regvec[REGNO (dest)] = INSN_UID (compute_store_table_current_insn);
5478132718Skan      if (bb_reg)
5479132718Skan	SET_BIT (bb_reg, REGNO (dest));
5480132718Skan    }
548190075Sobrien}
548290075Sobrien
5483132718Skan/* Clear any mark that says that this insn sets dest.  Called from
5484132718Skan   note_stores.  */
548590075Sobrien
5486132718Skanstatic void
5487132718Skanreg_clear_last_set (rtx dest, rtx setter ATTRIBUTE_UNUSED,
5488132718Skan	      void *data)
548990075Sobrien{
5490132718Skan  int *dead_vec = data;
5491132718Skan
5492132718Skan  if (GET_CODE (dest) == SUBREG)
5493132718Skan    dest = SUBREG_REG (dest);
5494132718Skan
5495169689Skan  if (REG_P (dest) &&
5496132718Skan      dead_vec[REGNO (dest)] == INSN_UID (compute_store_table_current_insn))
5497132718Skan    dead_vec[REGNO (dest)] = 0;
5498132718Skan}
5499132718Skan
5500132718Skan/* Return zero if some of the registers in list X are killed
5501132718Skan   due to set of registers in bitmap REGS_SET.  */
5502132718Skan
5503132718Skanstatic bool
5504132718Skanstore_ops_ok (rtx x, int *regs_set)
5505132718Skan{
5506132718Skan  rtx reg;
5507132718Skan
5508132718Skan  for (; x; x = XEXP (x, 1))
5509132718Skan    {
5510132718Skan      reg = XEXP (x, 0);
5511132718Skan      if (regs_set[REGNO(reg)])
5512132718Skan	return false;
5513132718Skan    }
5514132718Skan
5515132718Skan  return true;
5516132718Skan}
5517132718Skan
5518132718Skan/* Returns a list of registers mentioned in X.  */
5519132718Skanstatic rtx
5520132718Skanextract_mentioned_regs (rtx x)
5521132718Skan{
5522132718Skan  return extract_mentioned_regs_helper (x, NULL_RTX);
5523132718Skan}
5524132718Skan
5525132718Skan/* Helper for extract_mentioned_regs; ACCUM is used to accumulate used
5526132718Skan   registers.  */
5527132718Skanstatic rtx
5528132718Skanextract_mentioned_regs_helper (rtx x, rtx accum)
5529132718Skan{
553090075Sobrien  int i;
553190075Sobrien  enum rtx_code code;
553290075Sobrien  const char * fmt;
553390075Sobrien
553490075Sobrien  /* Repeat is used to turn tail-recursion into iteration.  */
553590075Sobrien repeat:
553690075Sobrien
553790075Sobrien  if (x == 0)
5538132718Skan    return accum;
553990075Sobrien
554090075Sobrien  code = GET_CODE (x);
554190075Sobrien  switch (code)
554290075Sobrien    {
554390075Sobrien    case REG:
5544132718Skan      return alloc_EXPR_LIST (0, x, accum);
554590075Sobrien
554690075Sobrien    case MEM:
554790075Sobrien      x = XEXP (x, 0);
554890075Sobrien      goto repeat;
554990075Sobrien
555090075Sobrien    case PRE_DEC:
555190075Sobrien    case PRE_INC:
555290075Sobrien    case POST_DEC:
555390075Sobrien    case POST_INC:
5554132718Skan      /* We do not run this function with arguments having side effects.  */
5555169689Skan      gcc_unreachable ();
555690075Sobrien
555790075Sobrien    case PC:
555890075Sobrien    case CC0: /*FIXME*/
555990075Sobrien    case CONST:
556090075Sobrien    case CONST_INT:
556190075Sobrien    case CONST_DOUBLE:
556296263Sobrien    case CONST_VECTOR:
556390075Sobrien    case SYMBOL_REF:
556490075Sobrien    case LABEL_REF:
556590075Sobrien    case ADDR_VEC:
556690075Sobrien    case ADDR_DIFF_VEC:
5567132718Skan      return accum;
556890075Sobrien
556990075Sobrien    default:
557090075Sobrien      break;
557190075Sobrien    }
557290075Sobrien
557390075Sobrien  i = GET_RTX_LENGTH (code) - 1;
557490075Sobrien  fmt = GET_RTX_FORMAT (code);
5575117395Skan
557690075Sobrien  for (; i >= 0; i--)
557790075Sobrien    {
557890075Sobrien      if (fmt[i] == 'e')
557990075Sobrien	{
558090075Sobrien	  rtx tem = XEXP (x, i);
558190075Sobrien
558290075Sobrien	  /* If we are about to do the last recursive call
5583132718Skan	     needed at this level, change it into iteration.  */
558490075Sobrien	  if (i == 0)
558590075Sobrien	    {
558690075Sobrien	      x = tem;
558790075Sobrien	      goto repeat;
558890075Sobrien	    }
5589117395Skan
5590132718Skan	  accum = extract_mentioned_regs_helper (tem, accum);
559190075Sobrien	}
559290075Sobrien      else if (fmt[i] == 'E')
559390075Sobrien	{
559490075Sobrien	  int j;
5595117395Skan
559690075Sobrien	  for (j = 0; j < XVECLEN (x, i); j++)
5597132718Skan	    accum = extract_mentioned_regs_helper (XVECEXP (x, i, j), accum);
559890075Sobrien	}
559990075Sobrien    }
560090075Sobrien
5601132718Skan  return accum;
560290075Sobrien}
560390075Sobrien
5604132718Skan/* Determine whether INSN is MEM store pattern that we will consider moving.
5605132718Skan   REGS_SET_BEFORE is bitmap of registers set before (and including) the
5606132718Skan   current insn, REGS_SET_AFTER is bitmap of registers set after (and
5607132718Skan   including) the insn in this basic block.  We must be passing through BB from
5608132718Skan   head to end, as we are using this fact to speed things up.
560990075Sobrien
5610132718Skan   The results are stored this way:
5611132718Skan
5612132718Skan   -- the first anticipatable expression is added into ANTIC_STORE_LIST
5613132718Skan   -- if the processed expression is not anticipatable, NULL_RTX is added
5614132718Skan      there instead, so that we can use it as indicator that no further
5615132718Skan      expression of this type may be anticipatable
5616132718Skan   -- if the expression is available, it is added as head of AVAIL_STORE_LIST;
5617132718Skan      consequently, all of them but this head are dead and may be deleted.
5618132718Skan   -- if the expression is not available, the insn due to that it fails to be
5619132718Skan      available is stored in reaching_reg.
5620132718Skan
5621132718Skan   The things are complicated a bit by fact that there already may be stores
5622132718Skan   to the same MEM from other blocks; also caller must take care of the
5623132718Skan   necessary cleanup of the temporary markers after end of the basic block.
5624132718Skan   */
5625132718Skan
562690075Sobrienstatic void
5627132718Skanfind_moveable_store (rtx insn, int *regs_set_before, int *regs_set_after)
562890075Sobrien{
562990075Sobrien  struct ls_expr * ptr;
5630132718Skan  rtx dest, set, tmp;
5631132718Skan  int check_anticipatable, check_available;
5632132718Skan  basic_block bb = BLOCK_FOR_INSN (insn);
563390075Sobrien
5634132718Skan  set = single_set (insn);
5635132718Skan  if (!set)
563690075Sobrien    return;
563790075Sobrien
5638132718Skan  dest = SET_DEST (set);
5639117395Skan
5640169689Skan  if (! MEM_P (dest) || MEM_VOLATILE_P (dest)
564190075Sobrien      || GET_MODE (dest) == BLKmode)
564290075Sobrien    return;
564390075Sobrien
5644132718Skan  if (side_effects_p (dest))
5645132718Skan    return;
564690075Sobrien
5647132718Skan  /* If we are handling exceptions, we must be careful with memory references
5648132718Skan     that may trap. If we are not, the behavior is undefined, so we may just
5649132718Skan     continue.  */
5650132718Skan  if (flag_non_call_exceptions && may_trap_p (dest))
565190075Sobrien    return;
565290075Sobrien
5653169689Skan  /* Even if the destination cannot trap, the source may.  In this case we'd
5654169689Skan     need to handle updating the REG_EH_REGION note.  */
5655169689Skan  if (find_reg_note (insn, REG_EH_REGION, NULL_RTX))
5656169689Skan    return;
5657169689Skan
5658169689Skan  /* Make sure that the SET_SRC of this store insns can be assigned to
5659169689Skan     a register, or we will fail later on in replace_store_insn, which
5660169689Skan     assumes that we can do this.  But sometimes the target machine has
5661169689Skan     oddities like MEM read-modify-write instruction.  See for example
5662169689Skan     PR24257.  */
5663169689Skan  if (!can_assign_to_reg_p (SET_SRC (set)))
5664169689Skan    return;
5665169689Skan
566690075Sobrien  ptr = ldst_entry (dest);
5667132718Skan  if (!ptr->pattern_regs)
5668132718Skan    ptr->pattern_regs = extract_mentioned_regs (dest);
5669132718Skan
5670132718Skan  /* Do not check for anticipatability if we either found one anticipatable
5671132718Skan     store already, or tested for one and found out that it was killed.  */
5672132718Skan  check_anticipatable = 0;
5673132718Skan  if (!ANTIC_STORE_LIST (ptr))
5674132718Skan    check_anticipatable = 1;
5675132718Skan  else
5676132718Skan    {
5677132718Skan      tmp = XEXP (ANTIC_STORE_LIST (ptr), 0);
5678132718Skan      if (tmp != NULL_RTX
5679132718Skan	  && BLOCK_FOR_INSN (tmp) != bb)
5680132718Skan	check_anticipatable = 1;
5681132718Skan    }
5682132718Skan  if (check_anticipatable)
5683132718Skan    {
5684132718Skan      if (store_killed_before (dest, ptr->pattern_regs, insn, bb, regs_set_before))
5685132718Skan	tmp = NULL_RTX;
5686132718Skan      else
5687132718Skan	tmp = insn;
5688132718Skan      ANTIC_STORE_LIST (ptr) = alloc_INSN_LIST (tmp,
5689132718Skan						ANTIC_STORE_LIST (ptr));
5690132718Skan    }
5691132718Skan
5692132718Skan  /* It is not necessary to check whether store is available if we did
5693132718Skan     it successfully before; if we failed before, do not bother to check
5694132718Skan     until we reach the insn that caused us to fail.  */
5695132718Skan  check_available = 0;
5696132718Skan  if (!AVAIL_STORE_LIST (ptr))
5697132718Skan    check_available = 1;
5698132718Skan  else
5699132718Skan    {
5700132718Skan      tmp = XEXP (AVAIL_STORE_LIST (ptr), 0);
5701132718Skan      if (BLOCK_FOR_INSN (tmp) != bb)
5702132718Skan	check_available = 1;
5703132718Skan    }
5704132718Skan  if (check_available)
5705132718Skan    {
5706132718Skan      /* Check that we have already reached the insn at that the check
5707132718Skan	 failed last time.  */
5708132718Skan      if (LAST_AVAIL_CHECK_FAILURE (ptr))
5709132718Skan	{
5710132718Skan	  for (tmp = BB_END (bb);
5711132718Skan	       tmp != insn && tmp != LAST_AVAIL_CHECK_FAILURE (ptr);
5712132718Skan	       tmp = PREV_INSN (tmp))
5713132718Skan	    continue;
5714132718Skan	  if (tmp == insn)
5715132718Skan	    check_available = 0;
5716132718Skan	}
5717132718Skan      else
5718132718Skan	check_available = store_killed_after (dest, ptr->pattern_regs, insn,
5719132718Skan					      bb, regs_set_after,
5720132718Skan					      &LAST_AVAIL_CHECK_FAILURE (ptr));
5721132718Skan    }
5722132718Skan  if (!check_available)
5723132718Skan    AVAIL_STORE_LIST (ptr) = alloc_INSN_LIST (insn, AVAIL_STORE_LIST (ptr));
572490075Sobrien}
572590075Sobrien
5726132718Skan/* Find available and anticipatable stores.  */
572790075Sobrien
572890075Sobrienstatic int
5729132718Skancompute_store_table (void)
573090075Sobrien{
5731117395Skan  int ret;
5732117395Skan  basic_block bb;
573390075Sobrien  unsigned regno;
5734132718Skan  rtx insn, pat, tmp;
5735132718Skan  int *last_set_in, *already_set;
5736132718Skan  struct ls_expr * ptr, **prev_next_ptr_ptr;
573790075Sobrien
573890075Sobrien  max_gcse_regno = max_reg_num ();
573990075Sobrien
5740132718Skan  reg_set_in_block = sbitmap_vector_alloc (last_basic_block,
574190075Sobrien						       max_gcse_regno);
5742117395Skan  sbitmap_vector_zero (reg_set_in_block, last_basic_block);
574390075Sobrien  pre_ldst_mems = 0;
5744169689Skan  pre_ldst_table = htab_create (13, pre_ldst_expr_hash,
5745169689Skan				pre_ldst_expr_eq, NULL);
5746169689Skan  last_set_in = XCNEWVEC (int, max_gcse_regno);
5747169689Skan  already_set = XNEWVEC (int, max_gcse_regno);
574890075Sobrien
574990075Sobrien  /* Find all the stores we care about.  */
5750117395Skan  FOR_EACH_BB (bb)
575190075Sobrien    {
5752132718Skan      /* First compute the registers set in this block.  */
5753132718Skan      regvec = last_set_in;
5754132718Skan
5755169689Skan      FOR_BB_INSNS (bb, insn)
575690075Sobrien	{
575790075Sobrien	  if (! INSN_P (insn))
575890075Sobrien	    continue;
575990075Sobrien
5760169689Skan	  if (CALL_P (insn))
576190075Sobrien	    {
576290075Sobrien	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
5763169689Skan		if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
5764132718Skan		  {
5765132718Skan		    last_set_in[regno] = INSN_UID (insn);
5766132718Skan		    SET_BIT (reg_set_in_block[bb->index], regno);
5767132718Skan		  }
576890075Sobrien	    }
5769117395Skan
577090075Sobrien	  pat = PATTERN (insn);
5771132718Skan	  compute_store_table_current_insn = insn;
5772132718Skan	  note_stores (pat, reg_set_info, reg_set_in_block[bb->index]);
5773132718Skan	}
5774132718Skan
5775132718Skan      /* Now find the stores.  */
5776132718Skan      memset (already_set, 0, sizeof (int) * max_gcse_regno);
5777132718Skan      regvec = already_set;
5778169689Skan      FOR_BB_INSNS (bb, insn)
5779132718Skan	{
5780132718Skan	  if (! INSN_P (insn))
5781132718Skan	    continue;
5782132718Skan
5783169689Skan	  if (CALL_P (insn))
5784132718Skan	    {
5785132718Skan	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
5786169689Skan		if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
5787132718Skan		  already_set[regno] = 1;
5788132718Skan	    }
5789132718Skan
5790132718Skan	  pat = PATTERN (insn);
579190075Sobrien	  note_stores (pat, reg_set_info, NULL);
5792117395Skan
579390075Sobrien	  /* Now that we've marked regs, look for stores.  */
5794132718Skan	  find_moveable_store (insn, already_set, last_set_in);
5795132718Skan
5796132718Skan	  /* Unmark regs that are no longer set.  */
5797132718Skan	  compute_store_table_current_insn = insn;
5798132718Skan	  note_stores (pat, reg_clear_last_set, last_set_in);
5799169689Skan	  if (CALL_P (insn))
5800132718Skan	    {
5801132718Skan	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
5802169689Skan		if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)
5803132718Skan		    && last_set_in[regno] == INSN_UID (insn))
5804132718Skan		  last_set_in[regno] = 0;
5805132718Skan	    }
580690075Sobrien	}
5807132718Skan
5808132718Skan#ifdef ENABLE_CHECKING
5809132718Skan      /* last_set_in should now be all-zero.  */
5810132718Skan      for (regno = 0; regno < max_gcse_regno; regno++)
5811169689Skan	gcc_assert (!last_set_in[regno]);
5812132718Skan#endif
5813132718Skan
5814132718Skan      /* Clear temporary marks.  */
5815132718Skan      for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
5816132718Skan	{
5817132718Skan	  LAST_AVAIL_CHECK_FAILURE(ptr) = NULL_RTX;
5818132718Skan	  if (ANTIC_STORE_LIST (ptr)
5819132718Skan	      && (tmp = XEXP (ANTIC_STORE_LIST (ptr), 0)) == NULL_RTX)
5820132718Skan	    ANTIC_STORE_LIST (ptr) = XEXP (ANTIC_STORE_LIST (ptr), 1);
5821132718Skan	}
582290075Sobrien    }
582390075Sobrien
5824132718Skan  /* Remove the stores that are not available anywhere, as there will
5825132718Skan     be no opportunity to optimize them.  */
5826132718Skan  for (ptr = pre_ldst_mems, prev_next_ptr_ptr = &pre_ldst_mems;
5827132718Skan       ptr != NULL;
5828132718Skan       ptr = *prev_next_ptr_ptr)
5829132718Skan    {
5830132718Skan      if (!AVAIL_STORE_LIST (ptr))
5831132718Skan	{
5832132718Skan	  *prev_next_ptr_ptr = ptr->next;
5833169689Skan	  htab_remove_elt_with_hash (pre_ldst_table, ptr, ptr->hash_index);
5834132718Skan	  free_ldst_entry (ptr);
5835132718Skan	}
5836132718Skan      else
5837132718Skan	prev_next_ptr_ptr = &ptr->next;
5838132718Skan    }
5839132718Skan
584090075Sobrien  ret = enumerate_ldsts ();
5841117395Skan
5842169689Skan  if (dump_file)
584390075Sobrien    {
5844169689Skan      fprintf (dump_file, "ST_avail and ST_antic (shown under loads..)\n");
5845169689Skan      print_ldst_list (dump_file);
584690075Sobrien    }
5847117395Skan
5848132718Skan  free (last_set_in);
5849132718Skan  free (already_set);
585090075Sobrien  return ret;
585190075Sobrien}
585290075Sobrien
5853132718Skan/* Check to see if the load X is aliased with STORE_PATTERN.
5854132718Skan   AFTER is true if we are checking the case when STORE_PATTERN occurs
5855132718Skan   after the X.  */
585690075Sobrien
5857132718Skanstatic bool
5858132718Skanload_kills_store (rtx x, rtx store_pattern, int after)
585990075Sobrien{
5860132718Skan  if (after)
5861132718Skan    return anti_dependence (x, store_pattern);
5862132718Skan  else
5863132718Skan    return true_dependence (store_pattern, GET_MODE (store_pattern), x,
5864132718Skan			    rtx_addr_varies_p);
586590075Sobrien}
586690075Sobrien
5867117395Skan/* Go through the entire insn X, looking for any loads which might alias
5868132718Skan   STORE_PATTERN.  Return true if found.
5869132718Skan   AFTER is true if we are checking the case when STORE_PATTERN occurs
5870132718Skan   after the insn X.  */
587190075Sobrien
5872132718Skanstatic bool
5873132718Skanfind_loads (rtx x, rtx store_pattern, int after)
587490075Sobrien{
587590075Sobrien  const char * fmt;
587690075Sobrien  int i, j;
5877132718Skan  int ret = false;
587890075Sobrien
587990075Sobrien  if (!x)
5880132718Skan    return false;
588190075Sobrien
5882117395Skan  if (GET_CODE (x) == SET)
588390075Sobrien    x = SET_SRC (x);
588490075Sobrien
5885169689Skan  if (MEM_P (x))
588690075Sobrien    {
5887132718Skan      if (load_kills_store (x, store_pattern, after))
5888132718Skan	return true;
588990075Sobrien    }
589090075Sobrien
589190075Sobrien  /* Recursively process the insn.  */
589290075Sobrien  fmt = GET_RTX_FORMAT (GET_CODE (x));
5893117395Skan
589490075Sobrien  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0 && !ret; i--)
589590075Sobrien    {
589690075Sobrien      if (fmt[i] == 'e')
5897132718Skan	ret |= find_loads (XEXP (x, i), store_pattern, after);
589890075Sobrien      else if (fmt[i] == 'E')
589990075Sobrien	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
5900132718Skan	  ret |= find_loads (XVECEXP (x, i, j), store_pattern, after);
590190075Sobrien    }
590290075Sobrien  return ret;
590390075Sobrien}
590490075Sobrien
5905117395Skan/* Check if INSN kills the store pattern X (is aliased with it).
5906132718Skan   AFTER is true if we are checking the case when store X occurs
5907169689Skan   after the insn.  Return true if it does.  */
590890075Sobrien
5909132718Skanstatic bool
5910132718Skanstore_killed_in_insn (rtx x, rtx x_regs, rtx insn, int after)
591190075Sobrien{
5912132718Skan  rtx reg, base, note;
5913117395Skan
5914132718Skan  if (!INSN_P (insn))
5915132718Skan    return false;
5916132718Skan
5917169689Skan  if (CALL_P (insn))
591890075Sobrien    {
591990075Sobrien      /* A normal or pure call might read from pattern,
592090075Sobrien	 but a const call will not.  */
5921132718Skan      if (! CONST_OR_PURE_CALL_P (insn) || pure_call_p (insn))
5922132718Skan	return true;
5923132718Skan
5924132718Skan      /* But even a const call reads its parameters.  Check whether the
5925132718Skan	 base of some of registers used in mem is stack pointer.  */
5926132718Skan      for (reg = x_regs; reg; reg = XEXP (reg, 1))
5927132718Skan	{
5928132718Skan	  base = find_base_term (XEXP (reg, 0));
5929132718Skan	  if (!base
5930132718Skan	      || (GET_CODE (base) == ADDRESS
5931132718Skan		  && GET_MODE (base) == Pmode
5932132718Skan		  && XEXP (base, 0) == stack_pointer_rtx))
5933132718Skan	    return true;
5934132718Skan	}
5935132718Skan
5936132718Skan      return false;
593790075Sobrien    }
5938117395Skan
593990075Sobrien  if (GET_CODE (PATTERN (insn)) == SET)
594090075Sobrien    {
594190075Sobrien      rtx pat = PATTERN (insn);
5942132718Skan      rtx dest = SET_DEST (pat);
5943132718Skan
5944169689Skan      if (GET_CODE (dest) == ZERO_EXTRACT)
5945132718Skan	dest = XEXP (dest, 0);
5946132718Skan
594790075Sobrien      /* Check for memory stores to aliased objects.  */
5948169689Skan      if (MEM_P (dest)
5949132718Skan	  && !expr_equiv_p (dest, x))
5950132718Skan	{
5951132718Skan	  if (after)
5952132718Skan	    {
5953132718Skan	      if (output_dependence (dest, x))
5954132718Skan		return true;
5955132718Skan	    }
5956132718Skan	  else
5957132718Skan	    {
5958132718Skan	      if (output_dependence (x, dest))
5959132718Skan		return true;
5960132718Skan	    }
5961132718Skan	}
5962132718Skan      if (find_loads (SET_SRC (pat), x, after))
5963132718Skan	return true;
596490075Sobrien    }
5965132718Skan  else if (find_loads (PATTERN (insn), x, after))
5966132718Skan    return true;
5967132718Skan
5968132718Skan  /* If this insn has a REG_EQUAL or REG_EQUIV note referencing a memory
5969132718Skan     location aliased with X, then this insn kills X.  */
5970132718Skan  note = find_reg_equal_equiv_note (insn);
5971132718Skan  if (! note)
5972132718Skan    return false;
5973132718Skan  note = XEXP (note, 0);
5974132718Skan
5975132718Skan  /* However, if the note represents a must alias rather than a may
5976132718Skan     alias relationship, then it does not kill X.  */
5977132718Skan  if (expr_equiv_p (note, x))
5978132718Skan    return false;
5979132718Skan
5980132718Skan  /* See if there are any aliased loads in the note.  */
5981132718Skan  return find_loads (note, x, after);
598290075Sobrien}
598390075Sobrien
5984132718Skan/* Returns true if the expression X is loaded or clobbered on or after INSN
5985132718Skan   within basic block BB.  REGS_SET_AFTER is bitmap of registers set in
5986132718Skan   or after the insn.  X_REGS is list of registers mentioned in X. If the store
5987132718Skan   is killed, return the last insn in that it occurs in FAIL_INSN.  */
598890075Sobrien
5989132718Skanstatic bool
5990132718Skanstore_killed_after (rtx x, rtx x_regs, rtx insn, basic_block bb,
5991132718Skan		    int *regs_set_after, rtx *fail_insn)
599290075Sobrien{
5993132718Skan  rtx last = BB_END (bb), act;
5994117395Skan
5995132718Skan  if (!store_ops_ok (x_regs, regs_set_after))
5996132718Skan    {
5997132718Skan      /* We do not know where it will happen.  */
5998132718Skan      if (fail_insn)
5999132718Skan	*fail_insn = NULL_RTX;
6000132718Skan      return true;
6001132718Skan    }
600290075Sobrien
6003132718Skan  /* Scan from the end, so that fail_insn is determined correctly.  */
6004132718Skan  for (act = last; act != PREV_INSN (insn); act = PREV_INSN (act))
6005132718Skan    if (store_killed_in_insn (x, x_regs, act, false))
6006132718Skan      {
6007132718Skan	if (fail_insn)
6008132718Skan	  *fail_insn = act;
6009132718Skan	return true;
6010132718Skan      }
601190075Sobrien
6012132718Skan  return false;
601390075Sobrien}
601490075Sobrien
6015132718Skan/* Returns true if the expression X is loaded or clobbered on or before INSN
6016132718Skan   within basic block BB. X_REGS is list of registers mentioned in X.
6017132718Skan   REGS_SET_BEFORE is bitmap of registers set before or in this insn.  */
6018132718Skanstatic bool
6019132718Skanstore_killed_before (rtx x, rtx x_regs, rtx insn, basic_block bb,
6020132718Skan		     int *regs_set_before)
602190075Sobrien{
6022132718Skan  rtx first = BB_HEAD (bb);
602390075Sobrien
6024132718Skan  if (!store_ops_ok (x_regs, regs_set_before))
6025132718Skan    return true;
6026117395Skan
6027132718Skan  for ( ; insn != PREV_INSN (first); insn = PREV_INSN (insn))
6028132718Skan    if (store_killed_in_insn (x, x_regs, insn, true))
6029132718Skan      return true;
603090075Sobrien
6031132718Skan  return false;
603290075Sobrien}
603390075Sobrien
6034132718Skan/* Fill in available, anticipatable, transparent and kill vectors in
6035132718Skan   STORE_DATA, based on lists of available and anticipatable stores.  */
603690075Sobrienstatic void
6037132718Skanbuild_store_vectors (void)
603890075Sobrien{
6039132718Skan  basic_block bb;
6040132718Skan  int *regs_set_in_block;
604190075Sobrien  rtx insn, st;
604290075Sobrien  struct ls_expr * ptr;
6043132718Skan  unsigned regno;
604490075Sobrien
604590075Sobrien  /* Build the gen_vector. This is any store in the table which is not killed
604690075Sobrien     by aliasing later in its block.  */
6047132718Skan  ae_gen = sbitmap_vector_alloc (last_basic_block, num_stores);
6048117395Skan  sbitmap_vector_zero (ae_gen, last_basic_block);
604990075Sobrien
6050132718Skan  st_antloc = sbitmap_vector_alloc (last_basic_block, num_stores);
6051117395Skan  sbitmap_vector_zero (st_antloc, last_basic_block);
605290075Sobrien
605390075Sobrien  for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
6054117395Skan    {
6055132718Skan      for (st = AVAIL_STORE_LIST (ptr); st != NULL; st = XEXP (st, 1))
605690075Sobrien	{
605790075Sobrien	  insn = XEXP (st, 0);
605890075Sobrien	  bb = BLOCK_FOR_INSN (insn);
6059117395Skan
6060132718Skan	  /* If we've already seen an available expression in this block,
6061132718Skan	     we can delete this one (It occurs earlier in the block). We'll
6062132718Skan	     copy the SRC expression to an unused register in case there
6063132718Skan	     are any side effects.  */
6064132718Skan	  if (TEST_BIT (ae_gen[bb->index], ptr->index))
606590075Sobrien	    {
6066132718Skan	      rtx r = gen_reg_rtx (GET_MODE (ptr->pattern));
6067169689Skan	      if (dump_file)
6068169689Skan		fprintf (dump_file, "Removing redundant store:\n");
6069132718Skan	      replace_store_insn (r, XEXP (st, 0), bb, ptr);
6070132718Skan	      continue;
607190075Sobrien	    }
6072132718Skan	  SET_BIT (ae_gen[bb->index], ptr->index);
6073132718Skan	}
6074117395Skan
6075132718Skan      for (st = ANTIC_STORE_LIST (ptr); st != NULL; st = XEXP (st, 1))
6076132718Skan	{
6077132718Skan	  insn = XEXP (st, 0);
6078132718Skan	  bb = BLOCK_FOR_INSN (insn);
6079132718Skan	  SET_BIT (st_antloc[bb->index], ptr->index);
608090075Sobrien	}
608190075Sobrien    }
608290075Sobrien
6083132718Skan  ae_kill = sbitmap_vector_alloc (last_basic_block, num_stores);
6084117395Skan  sbitmap_vector_zero (ae_kill, last_basic_block);
608590075Sobrien
6086132718Skan  transp = sbitmap_vector_alloc (last_basic_block, num_stores);
6087117395Skan  sbitmap_vector_zero (transp, last_basic_block);
6088169689Skan  regs_set_in_block = XNEWVEC (int, max_gcse_regno);
6089117395Skan
6090132718Skan  FOR_EACH_BB (bb)
6091132718Skan    {
6092132718Skan      for (regno = 0; regno < max_gcse_regno; regno++)
6093132718Skan	regs_set_in_block[regno] = TEST_BIT (reg_set_in_block[bb->index], regno);
609490075Sobrien
6095132718Skan      for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
6096132718Skan	{
6097132718Skan	  if (store_killed_after (ptr->pattern, ptr->pattern_regs, BB_HEAD (bb),
6098132718Skan				  bb, regs_set_in_block, NULL))
6099132718Skan	    {
6100132718Skan	      /* It should not be necessary to consider the expression
6101132718Skan		 killed if it is both anticipatable and available.  */
6102132718Skan	      if (!TEST_BIT (st_antloc[bb->index], ptr->index)
6103132718Skan		  || !TEST_BIT (ae_gen[bb->index], ptr->index))
6104132718Skan		SET_BIT (ae_kill[bb->index], ptr->index);
6105132718Skan	    }
6106132718Skan	  else
6107132718Skan	    SET_BIT (transp[bb->index], ptr->index);
6108132718Skan	}
6109132718Skan    }
6110132718Skan
6111132718Skan  free (regs_set_in_block);
6112132718Skan
6113169689Skan  if (dump_file)
611490075Sobrien    {
6115169689Skan      dump_sbitmap_vector (dump_file, "st_antloc", "", st_antloc, last_basic_block);
6116169689Skan      dump_sbitmap_vector (dump_file, "st_kill", "", ae_kill, last_basic_block);
6117169689Skan      dump_sbitmap_vector (dump_file, "Transpt", "", transp, last_basic_block);
6118169689Skan      dump_sbitmap_vector (dump_file, "st_avloc", "", ae_gen, last_basic_block);
611990075Sobrien    }
612090075Sobrien}
612190075Sobrien
6122132718Skan/* Insert an instruction at the beginning of a basic block, and update
6123132718Skan   the BB_HEAD if needed.  */
612490075Sobrien
6125117395Skanstatic void
6126132718Skaninsert_insn_start_bb (rtx insn, basic_block bb)
612790075Sobrien{
612890075Sobrien  /* Insert at start of successor block.  */
6129132718Skan  rtx prev = PREV_INSN (BB_HEAD (bb));
6130132718Skan  rtx before = BB_HEAD (bb);
613190075Sobrien  while (before != 0)
613290075Sobrien    {
6133169689Skan      if (! LABEL_P (before)
6134169689Skan	  && (! NOTE_P (before)
613590075Sobrien	      || NOTE_LINE_NUMBER (before) != NOTE_INSN_BASIC_BLOCK))
613690075Sobrien	break;
613790075Sobrien      prev = before;
6138132718Skan      if (prev == BB_END (bb))
613990075Sobrien	break;
614090075Sobrien      before = NEXT_INSN (before);
614190075Sobrien    }
614290075Sobrien
6143132718Skan  insn = emit_insn_after_noloc (insn, prev);
614490075Sobrien
6145169689Skan  if (dump_file)
614690075Sobrien    {
6147169689Skan      fprintf (dump_file, "STORE_MOTION  insert store at start of BB %d:\n",
614890075Sobrien	       bb->index);
6149169689Skan      print_inline_rtx (dump_file, insn, 6);
6150169689Skan      fprintf (dump_file, "\n");
615190075Sobrien    }
615290075Sobrien}
615390075Sobrien
615490075Sobrien/* This routine will insert a store on an edge. EXPR is the ldst entry for
6155117395Skan   the memory reference, and E is the edge to insert it on.  Returns nonzero
615690075Sobrien   if an edge insertion was performed.  */
615790075Sobrien
615890075Sobrienstatic int
6159132718Skaninsert_store (struct ls_expr * expr, edge e)
616090075Sobrien{
616190075Sobrien  rtx reg, insn;
616290075Sobrien  basic_block bb;
616390075Sobrien  edge tmp;
6164169689Skan  edge_iterator ei;
616590075Sobrien
616690075Sobrien  /* We did all the deleted before this insert, so if we didn't delete a
616790075Sobrien     store, then we haven't set the reaching reg yet either.  */
616890075Sobrien  if (expr->reaching_reg == NULL_RTX)
616990075Sobrien    return 0;
617090075Sobrien
6171132718Skan  if (e->flags & EDGE_FAKE)
6172132718Skan    return 0;
6173132718Skan
617490075Sobrien  reg = expr->reaching_reg;
6175132718Skan  insn = gen_move_insn (copy_rtx (expr->pattern), reg);
6176117395Skan
617790075Sobrien  /* If we are inserting this expression on ALL predecessor edges of a BB,
617890075Sobrien     insert it at the start of the BB, and reset the insert bits on the other
617990075Sobrien     edges so we don't try to insert it on the other edges.  */
618090075Sobrien  bb = e->dest;
6181169689Skan  FOR_EACH_EDGE (tmp, ei, e->dest->preds)
6182132718Skan    if (!(tmp->flags & EDGE_FAKE))
6183132718Skan      {
6184132718Skan	int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest);
6185169689Skan
6186169689Skan	gcc_assert (index != EDGE_INDEX_NO_EDGE);
6187132718Skan	if (! TEST_BIT (pre_insert_map[index], expr->index))
6188132718Skan	  break;
6189132718Skan      }
619090075Sobrien
619190075Sobrien  /* If tmp is NULL, we found an insertion on every edge, blank the
619290075Sobrien     insertion vector for these edges, and insert at the start of the BB.  */
619390075Sobrien  if (!tmp && bb != EXIT_BLOCK_PTR)
619490075Sobrien    {
6195169689Skan      FOR_EACH_EDGE (tmp, ei, e->dest->preds)
619690075Sobrien	{
619790075Sobrien	  int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest);
619890075Sobrien	  RESET_BIT (pre_insert_map[index], expr->index);
619990075Sobrien	}
620090075Sobrien      insert_insn_start_bb (insn, bb);
620190075Sobrien      return 0;
620290075Sobrien    }
6203117395Skan
6204169689Skan  /* We can't put stores in the front of blocks pointed to by abnormal
6205169689Skan     edges since that may put a store where one didn't used to be.  */
6206169689Skan  gcc_assert (!(e->flags & EDGE_ABNORMAL));
620790075Sobrien
620890075Sobrien  insert_insn_on_edge (insn, e);
6209117395Skan
6210169689Skan  if (dump_file)
621190075Sobrien    {
6212169689Skan      fprintf (dump_file, "STORE_MOTION  insert insn on edge (%d, %d):\n",
621390075Sobrien	       e->src->index, e->dest->index);
6214169689Skan      print_inline_rtx (dump_file, insn, 6);
6215169689Skan      fprintf (dump_file, "\n");
621690075Sobrien    }
6217117395Skan
621890075Sobrien  return 1;
621990075Sobrien}
622090075Sobrien
6221132718Skan/* Remove any REG_EQUAL or REG_EQUIV notes containing a reference to the
6222132718Skan   memory location in SMEXPR set in basic block BB.
6223132718Skan
6224132718Skan   This could be rather expensive.  */
6225132718Skan
6226132718Skanstatic void
6227132718Skanremove_reachable_equiv_notes (basic_block bb, struct ls_expr *smexpr)
6228132718Skan{
6229169689Skan  edge_iterator *stack, ei;
6230169689Skan  int sp;
6231169689Skan  edge act;
6232132718Skan  sbitmap visited = sbitmap_alloc (last_basic_block);
6233132718Skan  rtx last, insn, note;
6234132718Skan  rtx mem = smexpr->pattern;
6235132718Skan
6236169689Skan  stack = XNEWVEC (edge_iterator, n_basic_blocks);
6237169689Skan  sp = 0;
6238169689Skan  ei = ei_start (bb->succs);
6239169689Skan
6240132718Skan  sbitmap_zero (visited);
6241132718Skan
6242169689Skan  act = (EDGE_COUNT (ei_container (ei)) > 0 ? EDGE_I (ei_container (ei), 0) : NULL);
6243132718Skan  while (1)
6244132718Skan    {
6245132718Skan      if (!act)
6246132718Skan	{
6247169689Skan	  if (!sp)
6248132718Skan	    {
6249132718Skan	      free (stack);
6250132718Skan	      sbitmap_free (visited);
6251132718Skan	      return;
6252132718Skan	    }
6253169689Skan	  act = ei_edge (stack[--sp]);
6254132718Skan	}
6255132718Skan      bb = act->dest;
6256169689Skan
6257132718Skan      if (bb == EXIT_BLOCK_PTR
6258146895Skan	  || TEST_BIT (visited, bb->index))
6259132718Skan	{
6260169689Skan	  if (!ei_end_p (ei))
6261169689Skan	      ei_next (&ei);
6262169689Skan	  act = (! ei_end_p (ei)) ? ei_edge (ei) : NULL;
6263132718Skan	  continue;
6264132718Skan	}
6265132718Skan      SET_BIT (visited, bb->index);
6266132718Skan
6267132718Skan      if (TEST_BIT (st_antloc[bb->index], smexpr->index))
6268132718Skan	{
6269132718Skan	  for (last = ANTIC_STORE_LIST (smexpr);
6270132718Skan	       BLOCK_FOR_INSN (XEXP (last, 0)) != bb;
6271132718Skan	       last = XEXP (last, 1))
6272132718Skan	    continue;
6273132718Skan	  last = XEXP (last, 0);
6274132718Skan	}
6275132718Skan      else
6276132718Skan	last = NEXT_INSN (BB_END (bb));
6277169689Skan
6278132718Skan      for (insn = BB_HEAD (bb); insn != last; insn = NEXT_INSN (insn))
6279132718Skan	if (INSN_P (insn))
6280132718Skan	  {
6281132718Skan	    note = find_reg_equal_equiv_note (insn);
6282132718Skan	    if (!note || !expr_equiv_p (XEXP (note, 0), mem))
6283132718Skan	      continue;
6284132718Skan
6285169689Skan	    if (dump_file)
6286169689Skan	      fprintf (dump_file, "STORE_MOTION  drop REG_EQUAL note at insn %d:\n",
6287132718Skan		       INSN_UID (insn));
6288132718Skan	    remove_note (insn, note);
6289132718Skan	  }
6290169689Skan
6291169689Skan      if (!ei_end_p (ei))
6292169689Skan	ei_next (&ei);
6293169689Skan      act = (! ei_end_p (ei)) ? ei_edge (ei) : NULL;
6294169689Skan
6295169689Skan      if (EDGE_COUNT (bb->succs) > 0)
6296132718Skan	{
6297132718Skan	  if (act)
6298169689Skan	    stack[sp++] = ei;
6299169689Skan	  ei = ei_start (bb->succs);
6300169689Skan	  act = (EDGE_COUNT (ei_container (ei)) > 0 ? EDGE_I (ei_container (ei), 0) : NULL);
6301132718Skan	}
6302132718Skan    }
6303132718Skan}
6304132718Skan
630590075Sobrien/* This routine will replace a store with a SET to a specified register.  */
630690075Sobrien
630790075Sobrienstatic void
6308132718Skanreplace_store_insn (rtx reg, rtx del, basic_block bb, struct ls_expr *smexpr)
630990075Sobrien{
6310146895Skan  rtx insn, mem, note, set, ptr, pair;
6311117395Skan
6312132718Skan  mem = smexpr->pattern;
6313132718Skan  insn = gen_move_insn (reg, SET_SRC (single_set (del)));
631490075Sobrien  insn = emit_insn_after (insn, del);
6315117395Skan
6316169689Skan  if (dump_file)
631790075Sobrien    {
6318169689Skan      fprintf (dump_file,
631990075Sobrien	       "STORE_MOTION  delete insn in BB %d:\n      ", bb->index);
6320169689Skan      print_inline_rtx (dump_file, del, 6);
6321169689Skan      fprintf (dump_file, "\nSTORE MOTION  replaced with insn:\n      ");
6322169689Skan      print_inline_rtx (dump_file, insn, 6);
6323169689Skan      fprintf (dump_file, "\n");
632490075Sobrien    }
6325117395Skan
6326132718Skan  for (ptr = ANTIC_STORE_LIST (smexpr); ptr; ptr = XEXP (ptr, 1))
6327132718Skan    if (XEXP (ptr, 0) == del)
6328132718Skan      {
6329132718Skan	XEXP (ptr, 0) = insn;
6330132718Skan	break;
6331132718Skan      }
6332146895Skan
6333146895Skan  /* Move the notes from the deleted insn to its replacement, and patch
6334146895Skan     up the LIBCALL notes.  */
6335146895Skan  REG_NOTES (insn) = REG_NOTES (del);
6336146895Skan
6337146895Skan  note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
6338146895Skan  if (note)
6339146895Skan    {
6340146895Skan      pair = XEXP (note, 0);
6341146895Skan      note = find_reg_note (pair, REG_LIBCALL, NULL_RTX);
6342146895Skan      XEXP (note, 0) = insn;
6343146895Skan    }
6344146895Skan  note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
6345146895Skan  if (note)
6346146895Skan    {
6347146895Skan      pair = XEXP (note, 0);
6348146895Skan      note = find_reg_note (pair, REG_RETVAL, NULL_RTX);
6349146895Skan      XEXP (note, 0) = insn;
6350146895Skan    }
6351146895Skan
635290075Sobrien  delete_insn (del);
6353132718Skan
6354132718Skan  /* Now we must handle REG_EQUAL notes whose contents is equal to the mem;
6355132718Skan     they are no longer accurate provided that they are reached by this
6356132718Skan     definition, so drop them.  */
6357132718Skan  for (; insn != NEXT_INSN (BB_END (bb)); insn = NEXT_INSN (insn))
6358132718Skan    if (INSN_P (insn))
6359132718Skan      {
6360132718Skan	set = single_set (insn);
6361132718Skan	if (!set)
6362132718Skan	  continue;
6363132718Skan	if (expr_equiv_p (SET_DEST (set), mem))
6364132718Skan	  return;
6365132718Skan	note = find_reg_equal_equiv_note (insn);
6366132718Skan	if (!note || !expr_equiv_p (XEXP (note, 0), mem))
6367132718Skan	  continue;
6368132718Skan
6369169689Skan	if (dump_file)
6370169689Skan	  fprintf (dump_file, "STORE_MOTION  drop REG_EQUAL note at insn %d:\n",
6371132718Skan		   INSN_UID (insn));
6372132718Skan	remove_note (insn, note);
6373132718Skan      }
6374132718Skan  remove_reachable_equiv_notes (bb, smexpr);
637590075Sobrien}
637690075Sobrien
637790075Sobrien
637890075Sobrien/* Delete a store, but copy the value that would have been stored into
637990075Sobrien   the reaching_reg for later storing.  */
638090075Sobrien
638190075Sobrienstatic void
6382132718Skandelete_store (struct ls_expr * expr, basic_block bb)
638390075Sobrien{
638490075Sobrien  rtx reg, i, del;
638590075Sobrien
638690075Sobrien  if (expr->reaching_reg == NULL_RTX)
638790075Sobrien    expr->reaching_reg = gen_reg_rtx (GET_MODE (expr->pattern));
638890075Sobrien
638990075Sobrien  reg = expr->reaching_reg;
6390117395Skan
639190075Sobrien  for (i = AVAIL_STORE_LIST (expr); i; i = XEXP (i, 1))
639290075Sobrien    {
639390075Sobrien      del = XEXP (i, 0);
639490075Sobrien      if (BLOCK_FOR_INSN (del) == bb)
639590075Sobrien	{
6396117395Skan	  /* We know there is only one since we deleted redundant
639790075Sobrien	     ones during the available computation.  */
6398132718Skan	  replace_store_insn (reg, del, bb, expr);
639990075Sobrien	  break;
640090075Sobrien	}
640190075Sobrien    }
640290075Sobrien}
640390075Sobrien
640490075Sobrien/* Free memory used by store motion.  */
640590075Sobrien
6406117395Skanstatic void
6407132718Skanfree_store_memory (void)
640890075Sobrien{
640990075Sobrien  free_ldst_mems ();
6410117395Skan
641190075Sobrien  if (ae_gen)
641290075Sobrien    sbitmap_vector_free (ae_gen);
641390075Sobrien  if (ae_kill)
641490075Sobrien    sbitmap_vector_free (ae_kill);
641590075Sobrien  if (transp)
641690075Sobrien    sbitmap_vector_free (transp);
641790075Sobrien  if (st_antloc)
641890075Sobrien    sbitmap_vector_free (st_antloc);
641990075Sobrien  if (pre_insert_map)
642090075Sobrien    sbitmap_vector_free (pre_insert_map);
642190075Sobrien  if (pre_delete_map)
642290075Sobrien    sbitmap_vector_free (pre_delete_map);
642390075Sobrien  if (reg_set_in_block)
642490075Sobrien    sbitmap_vector_free (reg_set_in_block);
6425117395Skan
642690075Sobrien  ae_gen = ae_kill = transp = st_antloc = NULL;
642790075Sobrien  pre_insert_map = pre_delete_map = reg_set_in_block = NULL;
642890075Sobrien}
642990075Sobrien
643090075Sobrien/* Perform store motion. Much like gcse, except we move expressions the
643190075Sobrien   other way by looking at the flowgraph in reverse.  */
643290075Sobrien
643390075Sobrienstatic void
6434132718Skanstore_motion (void)
643590075Sobrien{
6436117395Skan  basic_block bb;
643790075Sobrien  int x;
643890075Sobrien  struct ls_expr * ptr;
643990075Sobrien  int update_flow = 0;
644090075Sobrien
6441169689Skan  if (dump_file)
644290075Sobrien    {
6443169689Skan      fprintf (dump_file, "before store motion\n");
6444169689Skan      print_rtl (dump_file, get_insns ());
644590075Sobrien    }
644690075Sobrien
644790075Sobrien  init_alias_analysis ();
644890075Sobrien
6449132718Skan  /* Find all the available and anticipatable stores.  */
645090075Sobrien  num_stores = compute_store_table ();
645190075Sobrien  if (num_stores == 0)
645290075Sobrien    {
6453169689Skan      htab_delete (pre_ldst_table);
6454169689Skan      pre_ldst_table = NULL;
645590075Sobrien      sbitmap_vector_free (reg_set_in_block);
645690075Sobrien      end_alias_analysis ();
645790075Sobrien      return;
645890075Sobrien    }
645990075Sobrien
6460132718Skan  /* Now compute kill & transp vectors.  */
6461132718Skan  build_store_vectors ();
646290075Sobrien  add_noreturn_fake_exit_edges ();
6463132718Skan  connect_infinite_loops_to_exit ();
646490075Sobrien
6465169689Skan  edge_list = pre_edge_rev_lcm (num_stores, transp, ae_gen,
6466117395Skan				st_antloc, ae_kill, &pre_insert_map,
646790075Sobrien				&pre_delete_map);
646890075Sobrien
646990075Sobrien  /* Now we want to insert the new stores which are going to be needed.  */
647090075Sobrien  for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
647190075Sobrien    {
6472169689Skan      /* If any of the edges we have above are abnormal, we can't move this
6473169689Skan	 store.  */
6474169689Skan      for (x = NUM_EDGES (edge_list) - 1; x >= 0; x--)
6475169689Skan	if (TEST_BIT (pre_insert_map[x], ptr->index)
6476169689Skan	    && (INDEX_EDGE (edge_list, x)->flags & EDGE_ABNORMAL))
6477169689Skan	  break;
6478169689Skan
6479169689Skan      if (x >= 0)
6480169689Skan	{
6481169689Skan	  if (dump_file != NULL)
6482169689Skan	    fprintf (dump_file,
6483169689Skan		     "Can't replace store %d: abnormal edge from %d to %d\n",
6484169689Skan		     ptr->index, INDEX_EDGE (edge_list, x)->src->index,
6485169689Skan		     INDEX_EDGE (edge_list, x)->dest->index);
6486169689Skan	  continue;
6487169689Skan	}
6488169689Skan
6489169689Skan      /* Now we want to insert the new stores which are going to be needed.  */
6490169689Skan
6491117395Skan      FOR_EACH_BB (bb)
6492117395Skan	if (TEST_BIT (pre_delete_map[bb->index], ptr->index))
6493117395Skan	  delete_store (ptr, bb);
649490075Sobrien
649590075Sobrien      for (x = 0; x < NUM_EDGES (edge_list); x++)
649690075Sobrien	if (TEST_BIT (pre_insert_map[x], ptr->index))
649790075Sobrien	  update_flow |= insert_store (ptr, INDEX_EDGE (edge_list, x));
649890075Sobrien    }
649990075Sobrien
650090075Sobrien  if (update_flow)
650190075Sobrien    commit_edge_insertions ();
650290075Sobrien
650390075Sobrien  free_store_memory ();
650490075Sobrien  free_edge_list (edge_list);
6505169689Skan  remove_fake_exit_edges ();
650690075Sobrien  end_alias_analysis ();
650790075Sobrien}
6508117395Skan
6509132718Skan
6510132718Skan/* Entry point for jump bypassing optimization pass.  */
6511132718Skan
6512169689Skanstatic int
6513169689Skanbypass_jumps (void)
6514132718Skan{
6515132718Skan  int changed;
6516132718Skan
6517132718Skan  /* We do not construct an accurate cfg in functions which call
6518132718Skan     setjmp, so just punt to be safe.  */
6519132718Skan  if (current_function_calls_setjmp)
6520132718Skan    return 0;
6521132718Skan
6522132718Skan  /* Identify the basic block information for this function, including
6523132718Skan     successors and predecessors.  */
6524132718Skan  max_gcse_regno = max_reg_num ();
6525132718Skan
6526169689Skan  if (dump_file)
6527169689Skan    dump_flow_info (dump_file, dump_flags);
6528132718Skan
6529132718Skan  /* Return if there's nothing to do, or it is too expensive.  */
6530169689Skan  if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1
6531169689Skan      || is_too_expensive (_ ("jump bypassing disabled")))
6532132718Skan    return 0;
6533132718Skan
6534132718Skan  gcc_obstack_init (&gcse_obstack);
6535132718Skan  bytes_used = 0;
6536132718Skan
6537132718Skan  /* We need alias.  */
6538132718Skan  init_alias_analysis ();
6539132718Skan
6540132718Skan  /* Record where pseudo-registers are set.  This data is kept accurate
6541132718Skan     during each pass.  ??? We could also record hard-reg information here
6542132718Skan     [since it's unchanging], however it is currently done during hash table
6543132718Skan     computation.
6544132718Skan
6545132718Skan     It may be tempting to compute MEM set information here too, but MEM sets
6546132718Skan     will be subject to code motion one day and thus we need to compute
6547132718Skan     information about memory sets when we build the hash tables.  */
6548132718Skan
6549132718Skan  alloc_reg_set_mem (max_gcse_regno);
6550169689Skan  compute_sets ();
6551132718Skan
6552132718Skan  max_gcse_regno = max_reg_num ();
6553169689Skan  alloc_gcse_mem ();
6554169689Skan  changed = one_cprop_pass (MAX_GCSE_PASSES + 2, true, true);
6555132718Skan  free_gcse_mem ();
6556132718Skan
6557169689Skan  if (dump_file)
6558132718Skan    {
6559169689Skan      fprintf (dump_file, "BYPASS of %s: %d basic blocks, ",
6560132718Skan	       current_function_name (), n_basic_blocks);
6561169689Skan      fprintf (dump_file, "%d bytes\n\n", bytes_used);
6562132718Skan    }
6563132718Skan
6564132718Skan  obstack_free (&gcse_obstack, NULL);
6565132718Skan  free_reg_set_mem ();
6566132718Skan
6567132718Skan  /* We are finished with alias.  */
6568132718Skan  end_alias_analysis ();
6569132718Skan  allocate_reg_info (max_reg_num (), FALSE, FALSE);
6570132718Skan
6571132718Skan  return changed;
6572132718Skan}
6573132718Skan
6574132718Skan/* Return true if the graph is too expensive to optimize. PASS is the
6575132718Skan   optimization about to be performed.  */
6576132718Skan
6577132718Skanstatic bool
6578132718Skanis_too_expensive (const char *pass)
6579132718Skan{
6580132718Skan  /* Trying to perform global optimizations on flow graphs which have
6581132718Skan     a high connectivity will take a long time and is unlikely to be
6582132718Skan     particularly useful.
6583169689Skan
6584132718Skan     In normal circumstances a cfg should have about twice as many
6585132718Skan     edges as blocks.  But we do not want to punish small functions
6586132718Skan     which have a couple switch statements.  Rather than simply
6587132718Skan     threshold the number of blocks, uses something with a more
6588132718Skan     graceful degradation.  */
6589132718Skan  if (n_edges > 20000 + n_basic_blocks * 4)
6590132718Skan    {
6591169689Skan      warning (OPT_Wdisabled_optimization,
6592169689Skan	       "%s: %d basic blocks and %d edges/basic block",
6593169689Skan	       pass, n_basic_blocks, n_edges / n_basic_blocks);
6594169689Skan
6595132718Skan      return true;
6596132718Skan    }
6597132718Skan
6598132718Skan  /* If allocating memory for the cprop bitmap would take up too much
6599132718Skan     storage it's better just to disable the optimization.  */
6600132718Skan  if ((n_basic_blocks
6601132718Skan       * SBITMAP_SET_SIZE (max_reg_num ())
6602132718Skan       * sizeof (SBITMAP_ELT_TYPE)) > MAX_GCSE_MEMORY)
6603132718Skan    {
6604169689Skan      warning (OPT_Wdisabled_optimization,
6605169689Skan	       "%s: %d basic blocks and %d registers",
6606169689Skan	       pass, n_basic_blocks, max_reg_num ());
6607132718Skan
6608132718Skan      return true;
6609132718Skan    }
6610132718Skan
6611132718Skan  return false;
6612132718Skan}
6613169689Skan
6614169689Skanstatic bool
6615169689Skangate_handle_jump_bypass (void)
6616169689Skan{
6617169689Skan  return optimize > 0 && flag_gcse;
6618169689Skan}
6619132718Skan
6620169689Skan/* Perform jump bypassing and control flow optimizations.  */
6621169689Skanstatic unsigned int
6622169689Skanrest_of_handle_jump_bypass (void)
6623169689Skan{
6624169689Skan  cleanup_cfg (CLEANUP_EXPENSIVE);
6625169689Skan  reg_scan (get_insns (), max_reg_num ());
6626169689Skan
6627169689Skan  if (bypass_jumps ())
6628169689Skan    {
6629169689Skan      rebuild_jump_labels (get_insns ());
6630169689Skan      cleanup_cfg (CLEANUP_EXPENSIVE);
6631169689Skan      delete_trivially_dead_insns (get_insns (), max_reg_num ());
6632169689Skan    }
6633169689Skan  return 0;
6634169689Skan}
6635169689Skan
6636169689Skanstruct tree_opt_pass pass_jump_bypass =
6637169689Skan{
6638169689Skan  "bypass",                             /* name */
6639169689Skan  gate_handle_jump_bypass,              /* gate */
6640169689Skan  rest_of_handle_jump_bypass,           /* execute */
6641169689Skan  NULL,                                 /* sub */
6642169689Skan  NULL,                                 /* next */
6643169689Skan  0,                                    /* static_pass_number */
6644169689Skan  TV_BYPASS,                            /* tv_id */
6645169689Skan  0,                                    /* properties_required */
6646169689Skan  0,                                    /* properties_provided */
6647169689Skan  0,                                    /* properties_destroyed */
6648169689Skan  0,                                    /* todo_flags_start */
6649169689Skan  TODO_dump_func |
6650169689Skan  TODO_ggc_collect | TODO_verify_flow,  /* todo_flags_finish */
6651169689Skan  'G'                                   /* letter */
6652169689Skan};
6653169689Skan
6654169689Skan
6655169689Skanstatic bool
6656169689Skangate_handle_gcse (void)
6657169689Skan{
6658169689Skan  return optimize > 0 && flag_gcse;
6659169689Skan}
6660169689Skan
6661169689Skan
6662169689Skanstatic unsigned int
6663169689Skanrest_of_handle_gcse (void)
6664169689Skan{
6665169689Skan  int save_csb, save_cfj;
6666169689Skan  int tem2 = 0, tem;
6667169689Skan
6668169689Skan  tem = gcse_main (get_insns ());
6669169689Skan  rebuild_jump_labels (get_insns ());
6670169689Skan  delete_trivially_dead_insns (get_insns (), max_reg_num ());
6671169689Skan
6672169689Skan  save_csb = flag_cse_skip_blocks;
6673169689Skan  save_cfj = flag_cse_follow_jumps;
6674169689Skan  flag_cse_skip_blocks = flag_cse_follow_jumps = 0;
6675169689Skan
6676169689Skan  /* If -fexpensive-optimizations, re-run CSE to clean up things done
6677169689Skan     by gcse.  */
6678169689Skan  if (flag_expensive_optimizations)
6679169689Skan    {
6680169689Skan      timevar_push (TV_CSE);
6681169689Skan      reg_scan (get_insns (), max_reg_num ());
6682169689Skan      tem2 = cse_main (get_insns (), max_reg_num ());
6683169689Skan      purge_all_dead_edges ();
6684169689Skan      delete_trivially_dead_insns (get_insns (), max_reg_num ());
6685169689Skan      timevar_pop (TV_CSE);
6686169689Skan      cse_not_expected = !flag_rerun_cse_after_loop;
6687169689Skan    }
6688169689Skan
6689169689Skan  /* If gcse or cse altered any jumps, rerun jump optimizations to clean
6690169689Skan     things up.  */
6691169689Skan  if (tem || tem2)
6692169689Skan    {
6693169689Skan      timevar_push (TV_JUMP);
6694169689Skan      rebuild_jump_labels (get_insns ());
6695169689Skan      delete_dead_jumptables ();
6696169689Skan      cleanup_cfg (CLEANUP_EXPENSIVE);
6697169689Skan      timevar_pop (TV_JUMP);
6698169689Skan    }
6699169689Skan
6700169689Skan  flag_cse_skip_blocks = save_csb;
6701169689Skan  flag_cse_follow_jumps = save_cfj;
6702169689Skan  return 0;
6703169689Skan}
6704169689Skan
6705169689Skanstruct tree_opt_pass pass_gcse =
6706169689Skan{
6707169689Skan  "gcse1",                              /* name */
6708169689Skan  gate_handle_gcse,                     /* gate */
6709169689Skan  rest_of_handle_gcse,			/* execute */
6710169689Skan  NULL,                                 /* sub */
6711169689Skan  NULL,                                 /* next */
6712169689Skan  0,                                    /* static_pass_number */
6713169689Skan  TV_GCSE,                              /* tv_id */
6714169689Skan  0,                                    /* properties_required */
6715169689Skan  0,                                    /* properties_provided */
6716169689Skan  0,                                    /* properties_destroyed */
6717169689Skan  0,                                    /* todo_flags_start */
6718169689Skan  TODO_dump_func |
6719169689Skan  TODO_verify_flow | TODO_ggc_collect,  /* todo_flags_finish */
6720169689Skan  'G'                                   /* letter */
6721169689Skan};
6722169689Skan
6723169689Skan
6724117395Skan#include "gt-gcse.h"
6725