xref: /dflybsd-src/contrib/gcc-4.7/gcc/gcse.c (revision 81fc95a5293ee307c688a350a3feb4734aaddbb4)
1e4b17023SJohn Marino /* Partial redundancy elimination / Hoisting for RTL.
2e4b17023SJohn Marino    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3e4b17023SJohn Marino    2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4e4b17023SJohn Marino 
5e4b17023SJohn Marino This file is part of GCC.
6e4b17023SJohn Marino 
7e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
8e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
9e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
10e4b17023SJohn Marino version.
11e4b17023SJohn Marino 
12e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
14e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15e4b17023SJohn Marino for more details.
16e4b17023SJohn Marino 
17e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
19e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
20e4b17023SJohn Marino 
21e4b17023SJohn Marino /* TODO
22e4b17023SJohn Marino    - reordering of memory allocation and freeing to be more space efficient
23e4b17023SJohn Marino    - do rough calc of how many regs are needed in each block, and a rough
24e4b17023SJohn Marino      calc of how many regs are available in each class and use that to
25e4b17023SJohn Marino      throttle back the code in cases where RTX_COST is minimal.
26e4b17023SJohn Marino */
27e4b17023SJohn Marino 
28e4b17023SJohn Marino /* References searched while implementing this.
29e4b17023SJohn Marino 
30e4b17023SJohn Marino    Compilers Principles, Techniques and Tools
31e4b17023SJohn Marino    Aho, Sethi, Ullman
32e4b17023SJohn Marino    Addison-Wesley, 1988
33e4b17023SJohn Marino 
34e4b17023SJohn Marino    Global Optimization by Suppression of Partial Redundancies
35e4b17023SJohn Marino    E. Morel, C. Renvoise
36e4b17023SJohn Marino    communications of the acm, Vol. 22, Num. 2, Feb. 1979
37e4b17023SJohn Marino 
38e4b17023SJohn Marino    A Portable Machine-Independent Global Optimizer - Design and Measurements
39e4b17023SJohn Marino    Frederick Chow
40e4b17023SJohn Marino    Stanford Ph.D. thesis, Dec. 1983
41e4b17023SJohn Marino 
42e4b17023SJohn Marino    A Fast Algorithm for Code Movement Optimization
43e4b17023SJohn Marino    D.M. Dhamdhere
44e4b17023SJohn Marino    SIGPLAN Notices, Vol. 23, Num. 10, Oct. 1988
45e4b17023SJohn Marino 
46e4b17023SJohn Marino    A Solution to a Problem with Morel and Renvoise's
47e4b17023SJohn Marino    Global Optimization by Suppression of Partial Redundancies
48e4b17023SJohn Marino    K-H Drechsler, M.P. Stadel
49e4b17023SJohn Marino    ACM TOPLAS, Vol. 10, Num. 4, Oct. 1988
50e4b17023SJohn Marino 
51e4b17023SJohn Marino    Practical Adaptation of the Global Optimization
52e4b17023SJohn Marino    Algorithm of Morel and Renvoise
53e4b17023SJohn Marino    D.M. Dhamdhere
54e4b17023SJohn Marino    ACM TOPLAS, Vol. 13, Num. 2. Apr. 1991
55e4b17023SJohn Marino 
56e4b17023SJohn Marino    Efficiently Computing Static Single Assignment Form and the Control
57e4b17023SJohn Marino    Dependence Graph
58e4b17023SJohn Marino    R. Cytron, J. Ferrante, B.K. Rosen, M.N. Wegman, and F.K. Zadeck
59e4b17023SJohn Marino    ACM TOPLAS, Vol. 13, Num. 4, Oct. 1991
60e4b17023SJohn Marino 
61e4b17023SJohn Marino    Lazy Code Motion
62e4b17023SJohn Marino    J. Knoop, O. Ruthing, B. Steffen
63e4b17023SJohn Marino    ACM SIGPLAN Notices Vol. 27, Num. 7, Jul. 1992, '92 Conference on PLDI
64e4b17023SJohn Marino 
65e4b17023SJohn Marino    What's In a Region?  Or Computing Control Dependence Regions in Near-Linear
66e4b17023SJohn Marino    Time for Reducible Flow Control
67e4b17023SJohn Marino    Thomas Ball
68e4b17023SJohn Marino    ACM Letters on Programming Languages and Systems,
69e4b17023SJohn Marino    Vol. 2, Num. 1-4, Mar-Dec 1993
70e4b17023SJohn Marino 
71e4b17023SJohn Marino    An Efficient Representation for Sparse Sets
72e4b17023SJohn Marino    Preston Briggs, Linda Torczon
73e4b17023SJohn Marino    ACM Letters on Programming Languages and Systems,
74e4b17023SJohn Marino    Vol. 2, Num. 1-4, Mar-Dec 1993
75e4b17023SJohn Marino 
76e4b17023SJohn Marino    A Variation of Knoop, Ruthing, and Steffen's Lazy Code Motion
77e4b17023SJohn Marino    K-H Drechsler, M.P. Stadel
78e4b17023SJohn Marino    ACM SIGPLAN Notices, Vol. 28, Num. 5, May 1993
79e4b17023SJohn Marino 
80e4b17023SJohn Marino    Partial Dead Code Elimination
81e4b17023SJohn Marino    J. Knoop, O. Ruthing, B. Steffen
82e4b17023SJohn Marino    ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994
83e4b17023SJohn Marino 
84e4b17023SJohn Marino    Effective Partial Redundancy Elimination
85e4b17023SJohn Marino    P. Briggs, K.D. Cooper
86e4b17023SJohn Marino    ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994
87e4b17023SJohn Marino 
88e4b17023SJohn Marino    The Program Structure Tree: Computing Control Regions in Linear Time
89e4b17023SJohn Marino    R. Johnson, D. Pearson, K. Pingali
90e4b17023SJohn Marino    ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994
91e4b17023SJohn Marino 
92e4b17023SJohn Marino    Optimal Code Motion: Theory and Practice
93e4b17023SJohn Marino    J. Knoop, O. Ruthing, B. Steffen
94e4b17023SJohn Marino    ACM TOPLAS, Vol. 16, Num. 4, Jul. 1994
95e4b17023SJohn Marino 
96e4b17023SJohn Marino    The power of assignment motion
97e4b17023SJohn Marino    J. Knoop, O. Ruthing, B. Steffen
98e4b17023SJohn Marino    ACM SIGPLAN Notices Vol. 30, Num. 6, Jun. 1995, '95 Conference on PLDI
99e4b17023SJohn Marino 
100e4b17023SJohn Marino    Global code motion / global value numbering
101e4b17023SJohn Marino    C. Click
102e4b17023SJohn Marino    ACM SIGPLAN Notices Vol. 30, Num. 6, Jun. 1995, '95 Conference on PLDI
103e4b17023SJohn Marino 
104e4b17023SJohn Marino    Value Driven Redundancy Elimination
105e4b17023SJohn Marino    L.T. Simpson
106e4b17023SJohn Marino    Rice University Ph.D. thesis, Apr. 1996
107e4b17023SJohn Marino 
108e4b17023SJohn Marino    Value Numbering
109e4b17023SJohn Marino    L.T. Simpson
110e4b17023SJohn Marino    Massively Scalar Compiler Project, Rice University, Sep. 1996
111e4b17023SJohn Marino 
112e4b17023SJohn Marino    High Performance Compilers for Parallel Computing
113e4b17023SJohn Marino    Michael Wolfe
114e4b17023SJohn Marino    Addison-Wesley, 1996
115e4b17023SJohn Marino 
116e4b17023SJohn Marino    Advanced Compiler Design and Implementation
117e4b17023SJohn Marino    Steven Muchnick
118e4b17023SJohn Marino    Morgan Kaufmann, 1997
119e4b17023SJohn Marino 
120e4b17023SJohn Marino    Building an Optimizing Compiler
121e4b17023SJohn Marino    Robert Morgan
122e4b17023SJohn Marino    Digital Press, 1998
123e4b17023SJohn Marino 
124e4b17023SJohn Marino    People wishing to speed up the code here should read:
125e4b17023SJohn Marino      Elimination Algorithms for Data Flow Analysis
126e4b17023SJohn Marino      B.G. Ryder, M.C. Paull
127e4b17023SJohn Marino      ACM Computing Surveys, Vol. 18, Num. 3, Sep. 1986
128e4b17023SJohn Marino 
129e4b17023SJohn Marino      How to Analyze Large Programs Efficiently and Informatively
130e4b17023SJohn Marino      D.M. Dhamdhere, B.K. Rosen, F.K. Zadeck
131e4b17023SJohn Marino      ACM SIGPLAN Notices Vol. 27, Num. 7, Jul. 1992, '92 Conference on PLDI
132e4b17023SJohn Marino 
133e4b17023SJohn Marino    People wishing to do something different can find various possibilities
134e4b17023SJohn Marino    in the above papers and elsewhere.
135e4b17023SJohn Marino */
136e4b17023SJohn Marino 
137e4b17023SJohn Marino #include "config.h"
138e4b17023SJohn Marino #include "system.h"
139e4b17023SJohn Marino #include "coretypes.h"
140e4b17023SJohn Marino #include "tm.h"
141e4b17023SJohn Marino #include "diagnostic-core.h"
142e4b17023SJohn Marino #include "toplev.h"
143e4b17023SJohn Marino 
144e4b17023SJohn Marino #include "rtl.h"
145e4b17023SJohn Marino #include "tree.h"
146e4b17023SJohn Marino #include "tm_p.h"
147e4b17023SJohn Marino #include "regs.h"
148e4b17023SJohn Marino #include "hard-reg-set.h"
149e4b17023SJohn Marino #include "flags.h"
150e4b17023SJohn Marino #include "insn-config.h"
151e4b17023SJohn Marino #include "recog.h"
152e4b17023SJohn Marino #include "basic-block.h"
153e4b17023SJohn Marino #include "output.h"
154e4b17023SJohn Marino #include "function.h"
155e4b17023SJohn Marino #include "expr.h"
156e4b17023SJohn Marino #include "except.h"
157e4b17023SJohn Marino #include "ggc.h"
158e4b17023SJohn Marino #include "params.h"
159e4b17023SJohn Marino #include "cselib.h"
160e4b17023SJohn Marino #include "intl.h"
161e4b17023SJohn Marino #include "obstack.h"
162e4b17023SJohn Marino #include "timevar.h"
163e4b17023SJohn Marino #include "tree-pass.h"
164e4b17023SJohn Marino #include "hashtab.h"
165e4b17023SJohn Marino #include "df.h"
166e4b17023SJohn Marino #include "dbgcnt.h"
167e4b17023SJohn Marino #include "target.h"
168e4b17023SJohn Marino #include "gcse.h"
169e4b17023SJohn Marino 
170e4b17023SJohn Marino /* We support GCSE via Partial Redundancy Elimination.  PRE optimizations
171e4b17023SJohn Marino    are a superset of those done by classic GCSE.
172e4b17023SJohn Marino 
173e4b17023SJohn Marino    Two passes of copy/constant propagation are done around PRE or hoisting
174e4b17023SJohn Marino    because the first one enables more GCSE and the second one helps to clean
175e4b17023SJohn Marino    up the copies that PRE and HOIST create.  This is needed more for PRE than
176e4b17023SJohn Marino    for HOIST because code hoisting will try to use an existing register
177e4b17023SJohn Marino    containing the common subexpression rather than create a new one.  This is
178e4b17023SJohn Marino    harder to do for PRE because of the code motion (which HOIST doesn't do).
179e4b17023SJohn Marino 
180e4b17023SJohn Marino    Expressions we are interested in GCSE-ing are of the form
181e4b17023SJohn Marino    (set (pseudo-reg) (expression)).
182e4b17023SJohn Marino    Function want_to_gcse_p says what these are.
183e4b17023SJohn Marino 
184e4b17023SJohn Marino    In addition, expressions in REG_EQUAL notes are candidates for GCSE-ing.
185e4b17023SJohn Marino    This allows PRE to hoist expressions that are expressed in multiple insns,
186e4b17023SJohn Marino    such as complex address calculations (e.g. for PIC code, or loads with a
187e4b17023SJohn Marino    high part and a low part).
188e4b17023SJohn Marino 
189e4b17023SJohn Marino    PRE handles moving invariant expressions out of loops (by treating them as
190e4b17023SJohn Marino    partially redundant).
191e4b17023SJohn Marino 
192e4b17023SJohn Marino    **********************
193e4b17023SJohn Marino 
194e4b17023SJohn Marino    We used to support multiple passes but there are diminishing returns in
195e4b17023SJohn Marino    doing so.  The first pass usually makes 90% of the changes that are doable.
196e4b17023SJohn Marino    A second pass can make a few more changes made possible by the first pass.
197e4b17023SJohn Marino    Experiments show any further passes don't make enough changes to justify
198e4b17023SJohn Marino    the expense.
199e4b17023SJohn Marino 
200e4b17023SJohn Marino    A study of spec92 using an unlimited number of passes:
201e4b17023SJohn Marino    [1 pass] = 1208 substitutions, [2] = 577, [3] = 202, [4] = 192, [5] = 83,
202e4b17023SJohn Marino    [6] = 34, [7] = 17, [8] = 9, [9] = 4, [10] = 4, [11] = 2,
203e4b17023SJohn Marino    [12] = 2, [13] = 1, [15] = 1, [16] = 2, [41] = 1
204e4b17023SJohn Marino 
205e4b17023SJohn Marino    It was found doing copy propagation between each pass enables further
206e4b17023SJohn Marino    substitutions.
207e4b17023SJohn Marino 
208e4b17023SJohn Marino    This study was done before expressions in REG_EQUAL notes were added as
209e4b17023SJohn Marino    candidate expressions for optimization, and before the GIMPLE optimizers
210e4b17023SJohn Marino    were added.  Probably, multiple passes is even less efficient now than
211e4b17023SJohn Marino    at the time when the study was conducted.
212e4b17023SJohn Marino 
213e4b17023SJohn Marino    PRE is quite expensive in complicated functions because the DFA can take
214e4b17023SJohn Marino    a while to converge.  Hence we only perform one pass.
215e4b17023SJohn Marino 
216e4b17023SJohn Marino    **********************
217e4b17023SJohn Marino 
218e4b17023SJohn Marino    The steps for PRE are:
219e4b17023SJohn Marino 
220e4b17023SJohn Marino    1) Build the hash table of expressions we wish to GCSE (expr_hash_table).
221e4b17023SJohn Marino 
222e4b17023SJohn Marino    2) Perform the data flow analysis for PRE.
223e4b17023SJohn Marino 
224e4b17023SJohn Marino    3) Delete the redundant instructions
225e4b17023SJohn Marino 
226e4b17023SJohn Marino    4) Insert the required copies [if any] that make the partially
227e4b17023SJohn Marino       redundant instructions fully redundant.
228e4b17023SJohn Marino 
229e4b17023SJohn Marino    5) For other reaching expressions, insert an instruction to copy the value
230e4b17023SJohn Marino       to a newly created pseudo that will reach the redundant instruction.
231e4b17023SJohn Marino 
232e4b17023SJohn Marino    The deletion is done first so that when we do insertions we
233e4b17023SJohn Marino    know which pseudo reg to use.
234e4b17023SJohn Marino 
235e4b17023SJohn Marino    Various papers have argued that PRE DFA is expensive (O(n^2)) and others
236e4b17023SJohn Marino    argue it is not.  The number of iterations for the algorithm to converge
237e4b17023SJohn Marino    is typically 2-4 so I don't view it as that expensive (relatively speaking).
238e4b17023SJohn Marino 
239e4b17023SJohn Marino    PRE GCSE depends heavily on the second CPROP pass to clean up the copies
240e4b17023SJohn Marino    we create.  To make an expression reach the place where it's redundant,
241e4b17023SJohn Marino    the result of the expression is copied to a new register, and the redundant
242e4b17023SJohn Marino    expression is deleted by replacing it with this new register.  Classic GCSE
243e4b17023SJohn Marino    doesn't have this problem as much as it computes the reaching defs of
244e4b17023SJohn Marino    each register in each block and thus can try to use an existing
245e4b17023SJohn Marino    register.  */
246e4b17023SJohn Marino 
247e4b17023SJohn Marino /* GCSE global vars.  */
248e4b17023SJohn Marino 
249e4b17023SJohn Marino struct target_gcse default_target_gcse;
250e4b17023SJohn Marino #if SWITCHABLE_TARGET
251e4b17023SJohn Marino struct target_gcse *this_target_gcse = &default_target_gcse;
252e4b17023SJohn Marino #endif
253e4b17023SJohn Marino 
254e4b17023SJohn Marino /* Set to non-zero if CSE should run after all GCSE optimizations are done.  */
255e4b17023SJohn Marino int flag_rerun_cse_after_global_opts;
256e4b17023SJohn Marino 
257e4b17023SJohn Marino /* An obstack for our working variables.  */
258e4b17023SJohn Marino static struct obstack gcse_obstack;
259e4b17023SJohn Marino 
260e4b17023SJohn Marino struct reg_use {rtx reg_rtx; };
261e4b17023SJohn Marino 
262e4b17023SJohn Marino /* Hash table of expressions.  */
263e4b17023SJohn Marino 
264e4b17023SJohn Marino struct expr
265e4b17023SJohn Marino {
266e4b17023SJohn Marino   /* The expression.  */
267e4b17023SJohn Marino   rtx expr;
268e4b17023SJohn Marino   /* Index in the available expression bitmaps.  */
269e4b17023SJohn Marino   int bitmap_index;
270e4b17023SJohn Marino   /* Next entry with the same hash.  */
271e4b17023SJohn Marino   struct expr *next_same_hash;
272e4b17023SJohn Marino   /* List of anticipatable occurrences in basic blocks in the function.
273e4b17023SJohn Marino      An "anticipatable occurrence" is one that is the first occurrence in the
274e4b17023SJohn Marino      basic block, the operands are not modified in the basic block prior
275e4b17023SJohn Marino      to the occurrence and the output is not used between the start of
276e4b17023SJohn Marino      the block and the occurrence.  */
277e4b17023SJohn Marino   struct occr *antic_occr;
278e4b17023SJohn Marino   /* List of available occurrence in basic blocks in the function.
279e4b17023SJohn Marino      An "available occurrence" is one that is the last occurrence in the
280e4b17023SJohn Marino      basic block and the operands are not modified by following statements in
281e4b17023SJohn Marino      the basic block [including this insn].  */
282e4b17023SJohn Marino   struct occr *avail_occr;
283e4b17023SJohn Marino   /* Non-null if the computation is PRE redundant.
284e4b17023SJohn Marino      The value is the newly created pseudo-reg to record a copy of the
285e4b17023SJohn Marino      expression in all the places that reach the redundant copy.  */
286e4b17023SJohn Marino   rtx reaching_reg;
287e4b17023SJohn Marino   /* Maximum distance in instructions this expression can travel.
288e4b17023SJohn Marino      We avoid moving simple expressions for more than a few instructions
289e4b17023SJohn Marino      to keep register pressure under control.
290e4b17023SJohn Marino      A value of "0" removes restrictions on how far the expression can
291e4b17023SJohn Marino      travel.  */
292e4b17023SJohn Marino   int max_distance;
293e4b17023SJohn Marino };
294e4b17023SJohn Marino 
295e4b17023SJohn Marino /* Occurrence of an expression.
296e4b17023SJohn Marino    There is one per basic block.  If a pattern appears more than once the
297e4b17023SJohn Marino    last appearance is used [or first for anticipatable expressions].  */
298e4b17023SJohn Marino 
299e4b17023SJohn Marino struct occr
300e4b17023SJohn Marino {
301e4b17023SJohn Marino   /* Next occurrence of this expression.  */
302e4b17023SJohn Marino   struct occr *next;
303e4b17023SJohn Marino   /* The insn that computes the expression.  */
304e4b17023SJohn Marino   rtx insn;
305e4b17023SJohn Marino   /* Nonzero if this [anticipatable] occurrence has been deleted.  */
306e4b17023SJohn Marino   char deleted_p;
307e4b17023SJohn Marino   /* Nonzero if this [available] occurrence has been copied to
308e4b17023SJohn Marino      reaching_reg.  */
309e4b17023SJohn Marino   /* ??? This is mutually exclusive with deleted_p, so they could share
310e4b17023SJohn Marino      the same byte.  */
311e4b17023SJohn Marino   char copied_p;
312e4b17023SJohn Marino };
313e4b17023SJohn Marino 
314e4b17023SJohn Marino typedef struct occr *occr_t;
315e4b17023SJohn Marino DEF_VEC_P (occr_t);
316e4b17023SJohn Marino DEF_VEC_ALLOC_P (occr_t, heap);
317e4b17023SJohn Marino 
318e4b17023SJohn Marino /* Expression hash tables.
319e4b17023SJohn Marino    Each hash table is an array of buckets.
320e4b17023SJohn Marino    ??? It is known that if it were an array of entries, structure elements
321e4b17023SJohn Marino    `next_same_hash' and `bitmap_index' wouldn't be necessary.  However, it is
322e4b17023SJohn Marino    not clear whether in the final analysis a sufficient amount of memory would
323e4b17023SJohn Marino    be saved as the size of the available expression bitmaps would be larger
324e4b17023SJohn Marino    [one could build a mapping table without holes afterwards though].
325e4b17023SJohn Marino    Someday I'll perform the computation and figure it out.  */
326e4b17023SJohn Marino 
327e4b17023SJohn Marino struct hash_table_d
328e4b17023SJohn Marino {
329e4b17023SJohn Marino   /* The table itself.
330e4b17023SJohn Marino      This is an array of `expr_hash_table_size' elements.  */
331e4b17023SJohn Marino   struct expr **table;
332e4b17023SJohn Marino 
333e4b17023SJohn Marino   /* Size of the hash table, in elements.  */
334e4b17023SJohn Marino   unsigned int size;
335e4b17023SJohn Marino 
336e4b17023SJohn Marino   /* Number of hash table elements.  */
337e4b17023SJohn Marino   unsigned int n_elems;
338e4b17023SJohn Marino };
339e4b17023SJohn Marino 
340e4b17023SJohn Marino /* Expression hash table.  */
341e4b17023SJohn Marino static struct hash_table_d expr_hash_table;
342e4b17023SJohn Marino 
343e4b17023SJohn Marino /* This is a list of expressions which are MEMs and will be used by load
344e4b17023SJohn Marino    or store motion.
345e4b17023SJohn Marino    Load motion tracks MEMs which aren't killed by anything except itself,
346e4b17023SJohn Marino    i.e. loads and stores to a single location.
347e4b17023SJohn Marino    We can then allow movement of these MEM refs with a little special
348e4b17023SJohn Marino    allowance. (all stores copy the same value to the reaching reg used
349e4b17023SJohn Marino    for the loads).  This means all values used to store into memory must have
350e4b17023SJohn Marino    no side effects so we can re-issue the setter value.  */
351e4b17023SJohn Marino 
352e4b17023SJohn Marino struct ls_expr
353e4b17023SJohn Marino {
354e4b17023SJohn Marino   struct expr * expr;		/* Gcse expression reference for LM.  */
355e4b17023SJohn Marino   rtx pattern;			/* Pattern of this mem.  */
356e4b17023SJohn Marino   rtx pattern_regs;		/* List of registers mentioned by the mem.  */
357e4b17023SJohn Marino   rtx loads;			/* INSN list of loads seen.  */
358e4b17023SJohn Marino   rtx stores;			/* INSN list of stores seen.  */
359e4b17023SJohn Marino   struct ls_expr * next;	/* Next in the list.  */
360e4b17023SJohn Marino   int invalid;			/* Invalid for some reason.  */
361e4b17023SJohn Marino   int index;			/* If it maps to a bitmap index.  */
362e4b17023SJohn Marino   unsigned int hash_index;	/* Index when in a hash table.  */
363e4b17023SJohn Marino   rtx reaching_reg;		/* Register to use when re-writing.  */
364e4b17023SJohn Marino };
365e4b17023SJohn Marino 
366e4b17023SJohn Marino /* Head of the list of load/store memory refs.  */
367e4b17023SJohn Marino static struct ls_expr * pre_ldst_mems = NULL;
368e4b17023SJohn Marino 
369e4b17023SJohn Marino /* Hashtable for the load/store memory refs.  */
370e4b17023SJohn Marino static htab_t pre_ldst_table = NULL;
371e4b17023SJohn Marino 
372e4b17023SJohn Marino /* Bitmap containing one bit for each register in the program.
373e4b17023SJohn Marino    Used when performing GCSE to track which registers have been set since
374e4b17023SJohn Marino    the start of the basic block.  */
375e4b17023SJohn Marino static regset reg_set_bitmap;
376e4b17023SJohn Marino 
377e4b17023SJohn Marino /* Array, indexed by basic block number for a list of insns which modify
378e4b17023SJohn Marino    memory within that block.  */
VEC(rtx,heap)379e4b17023SJohn Marino static VEC (rtx,heap) **modify_mem_list;
380e4b17023SJohn Marino static bitmap modify_mem_list_set;
381e4b17023SJohn Marino 
382e4b17023SJohn Marino typedef struct modify_pair_s
383e4b17023SJohn Marino {
384e4b17023SJohn Marino   rtx dest;			/* A MEM.  */
385e4b17023SJohn Marino   rtx dest_addr;		/* The canonical address of `dest'.  */
386e4b17023SJohn Marino } modify_pair;
387e4b17023SJohn Marino 
388e4b17023SJohn Marino DEF_VEC_O(modify_pair);
389e4b17023SJohn Marino DEF_VEC_ALLOC_O(modify_pair,heap);
390e4b17023SJohn Marino 
391e4b17023SJohn Marino /* This array parallels modify_mem_list, except that it stores MEMs
392e4b17023SJohn Marino    being set and their canonicalized memory addresses.  */
393e4b17023SJohn Marino static VEC (modify_pair,heap) **canon_modify_mem_list;
394e4b17023SJohn Marino 
395e4b17023SJohn Marino /* Bitmap indexed by block numbers to record which blocks contain
396e4b17023SJohn Marino    function calls.  */
397e4b17023SJohn Marino static bitmap blocks_with_calls;
398e4b17023SJohn Marino 
399e4b17023SJohn Marino /* Various variables for statistics gathering.  */
400e4b17023SJohn Marino 
401e4b17023SJohn Marino /* Memory used in a pass.
402e4b17023SJohn Marino    This isn't intended to be absolutely precise.  Its intent is only
403e4b17023SJohn Marino    to keep an eye on memory usage.  */
404e4b17023SJohn Marino static int bytes_used;
405e4b17023SJohn Marino 
406e4b17023SJohn Marino /* GCSE substitutions made.  */
407e4b17023SJohn Marino static int gcse_subst_count;
408e4b17023SJohn Marino /* Number of copy instructions created.  */
409e4b17023SJohn Marino static int gcse_create_count;
410e4b17023SJohn Marino 
411e4b17023SJohn Marino /* Doing code hoisting.  */
412e4b17023SJohn Marino static bool doing_code_hoisting_p = false;
413e4b17023SJohn Marino 
414e4b17023SJohn Marino /* For available exprs */
415e4b17023SJohn Marino static sbitmap *ae_kill;
416e4b17023SJohn Marino 
417e4b17023SJohn Marino static void compute_can_copy (void);
418e4b17023SJohn Marino static void *gmalloc (size_t) ATTRIBUTE_MALLOC;
419e4b17023SJohn Marino static void *gcalloc (size_t, size_t) ATTRIBUTE_MALLOC;
420e4b17023SJohn Marino static void *gcse_alloc (unsigned long);
421e4b17023SJohn Marino static void alloc_gcse_mem (void);
422e4b17023SJohn Marino static void free_gcse_mem (void);
423e4b17023SJohn Marino static void hash_scan_insn (rtx, struct hash_table_d *);
424e4b17023SJohn Marino static void hash_scan_set (rtx, rtx, struct hash_table_d *);
425e4b17023SJohn Marino static void hash_scan_clobber (rtx, rtx, struct hash_table_d *);
426e4b17023SJohn Marino static void hash_scan_call (rtx, rtx, struct hash_table_d *);
427e4b17023SJohn Marino static int want_to_gcse_p (rtx, int *);
428e4b17023SJohn Marino static int oprs_unchanged_p (const_rtx, const_rtx, int);
429e4b17023SJohn Marino static int oprs_anticipatable_p (const_rtx, const_rtx);
430e4b17023SJohn Marino static int oprs_available_p (const_rtx, const_rtx);
431e4b17023SJohn Marino static void insert_expr_in_table (rtx, enum machine_mode, rtx, int, int, int,
432e4b17023SJohn Marino 				  struct hash_table_d *);
433e4b17023SJohn Marino static unsigned int hash_expr (const_rtx, enum machine_mode, int *, int);
434e4b17023SJohn Marino static int expr_equiv_p (const_rtx, const_rtx);
435e4b17023SJohn Marino static void record_last_reg_set_info (rtx, int);
436e4b17023SJohn Marino static void record_last_mem_set_info (rtx);
437e4b17023SJohn Marino static void record_last_set_info (rtx, const_rtx, void *);
438e4b17023SJohn Marino static void compute_hash_table (struct hash_table_d *);
439e4b17023SJohn Marino static void alloc_hash_table (struct hash_table_d *);
440e4b17023SJohn Marino static void free_hash_table (struct hash_table_d *);
441e4b17023SJohn Marino static void compute_hash_table_work (struct hash_table_d *);
442e4b17023SJohn Marino static void dump_hash_table (FILE *, const char *, struct hash_table_d *);
443e4b17023SJohn Marino static void compute_transp (const_rtx, int, sbitmap *);
444e4b17023SJohn Marino static void compute_local_properties (sbitmap *, sbitmap *, sbitmap *,
445e4b17023SJohn Marino 				      struct hash_table_d *);
446e4b17023SJohn Marino static void mems_conflict_for_gcse_p (rtx, const_rtx, void *);
447e4b17023SJohn Marino static int load_killed_in_block_p (const_basic_block, int, const_rtx, int);
448e4b17023SJohn Marino static void canon_list_insert (rtx, const_rtx, void *);
449e4b17023SJohn Marino static void alloc_pre_mem (int, int);
450e4b17023SJohn Marino static void free_pre_mem (void);
451e4b17023SJohn Marino static struct edge_list *compute_pre_data (void);
452e4b17023SJohn Marino static int pre_expr_reaches_here_p (basic_block, struct expr *,
453e4b17023SJohn Marino 				    basic_block);
454e4b17023SJohn Marino static void insert_insn_end_basic_block (struct expr *, basic_block);
455e4b17023SJohn Marino static void pre_insert_copy_insn (struct expr *, rtx);
456e4b17023SJohn Marino static void pre_insert_copies (void);
457e4b17023SJohn Marino static int pre_delete (void);
458e4b17023SJohn Marino static int pre_gcse (struct edge_list *);
459e4b17023SJohn Marino static int one_pre_gcse_pass (void);
460e4b17023SJohn Marino static void add_label_notes (rtx, rtx);
461e4b17023SJohn Marino static void alloc_code_hoist_mem (int, int);
462e4b17023SJohn Marino static void free_code_hoist_mem (void);
463e4b17023SJohn Marino static void compute_code_hoist_vbeinout (void);
464e4b17023SJohn Marino static void compute_code_hoist_data (void);
465e4b17023SJohn Marino static int hoist_expr_reaches_here_p (basic_block, int, basic_block, char *,
466e4b17023SJohn Marino 				      int, int *);
467e4b17023SJohn Marino static int hoist_code (void);
468e4b17023SJohn Marino static int one_code_hoisting_pass (void);
469e4b17023SJohn Marino static rtx process_insert_insn (struct expr *);
470e4b17023SJohn Marino static int pre_edge_insert (struct edge_list *, struct expr **);
471e4b17023SJohn Marino static int pre_expr_reaches_here_p_work (basic_block, struct expr *,
472e4b17023SJohn Marino 					 basic_block, char *);
473e4b17023SJohn Marino static struct ls_expr * ldst_entry (rtx);
474e4b17023SJohn Marino static void free_ldst_entry (struct ls_expr *);
475e4b17023SJohn Marino static void free_ld_motion_mems (void);
476e4b17023SJohn Marino static void print_ldst_list (FILE *);
477e4b17023SJohn Marino static struct ls_expr * find_rtx_in_ldst (rtx);
478e4b17023SJohn Marino static int simple_mem (const_rtx);
479e4b17023SJohn Marino static void invalidate_any_buried_refs (rtx);
480e4b17023SJohn Marino static void compute_ld_motion_mems (void);
481e4b17023SJohn Marino static void trim_ld_motion_mems (void);
482e4b17023SJohn Marino static void update_ld_motion_stores (struct expr *);
483e4b17023SJohn Marino static void clear_modify_mem_tables (void);
484e4b17023SJohn Marino static void free_modify_mem_tables (void);
485e4b17023SJohn Marino static rtx gcse_emit_move_after (rtx, rtx, rtx);
486e4b17023SJohn Marino static bool is_too_expensive (const char *);
487e4b17023SJohn Marino 
488e4b17023SJohn Marino #define GNEW(T)			((T *) gmalloc (sizeof (T)))
489e4b17023SJohn Marino #define GCNEW(T)		((T *) gcalloc (1, sizeof (T)))
490e4b17023SJohn Marino 
491e4b17023SJohn Marino #define GNEWVEC(T, N)		((T *) gmalloc (sizeof (T) * (N)))
492e4b17023SJohn Marino #define GCNEWVEC(T, N)		((T *) gcalloc ((N), sizeof (T)))
493e4b17023SJohn Marino 
494e4b17023SJohn Marino #define GNEWVAR(T, S)		((T *) gmalloc ((S)))
495e4b17023SJohn Marino #define GCNEWVAR(T, S)		((T *) gcalloc (1, (S)))
496e4b17023SJohn Marino 
497e4b17023SJohn Marino #define GOBNEW(T)		((T *) gcse_alloc (sizeof (T)))
498e4b17023SJohn Marino #define GOBNEWVAR(T, S)		((T *) gcse_alloc ((S)))
499e4b17023SJohn Marino 
500e4b17023SJohn Marino /* Misc. utilities.  */
501e4b17023SJohn Marino 
502e4b17023SJohn Marino #define can_copy \
503e4b17023SJohn Marino   (this_target_gcse->x_can_copy)
504e4b17023SJohn Marino #define can_copy_init_p \
505e4b17023SJohn Marino   (this_target_gcse->x_can_copy_init_p)
506e4b17023SJohn Marino 
507e4b17023SJohn Marino /* Compute which modes support reg/reg copy operations.  */
508e4b17023SJohn Marino 
509e4b17023SJohn Marino static void
compute_can_copy(void)510e4b17023SJohn Marino compute_can_copy (void)
511e4b17023SJohn Marino {
512e4b17023SJohn Marino   int i;
513e4b17023SJohn Marino #ifndef AVOID_CCMODE_COPIES
514e4b17023SJohn Marino   rtx reg, insn;
515e4b17023SJohn Marino #endif
516e4b17023SJohn Marino   memset (can_copy, 0, NUM_MACHINE_MODES);
517e4b17023SJohn Marino 
518e4b17023SJohn Marino   start_sequence ();
519e4b17023SJohn Marino   for (i = 0; i < NUM_MACHINE_MODES; i++)
520e4b17023SJohn Marino     if (GET_MODE_CLASS (i) == MODE_CC)
521e4b17023SJohn Marino       {
522e4b17023SJohn Marino #ifdef AVOID_CCMODE_COPIES
523e4b17023SJohn Marino 	can_copy[i] = 0;
524e4b17023SJohn Marino #else
525e4b17023SJohn Marino 	reg = gen_rtx_REG ((enum machine_mode) i, LAST_VIRTUAL_REGISTER + 1);
526e4b17023SJohn Marino 	insn = emit_insn (gen_rtx_SET (VOIDmode, reg, reg));
527e4b17023SJohn Marino 	if (recog (PATTERN (insn), insn, NULL) >= 0)
528e4b17023SJohn Marino 	  can_copy[i] = 1;
529e4b17023SJohn Marino #endif
530e4b17023SJohn Marino       }
531e4b17023SJohn Marino     else
532e4b17023SJohn Marino       can_copy[i] = 1;
533e4b17023SJohn Marino 
534e4b17023SJohn Marino   end_sequence ();
535e4b17023SJohn Marino }
536e4b17023SJohn Marino 
537e4b17023SJohn Marino /* Returns whether the mode supports reg/reg copy operations.  */
538e4b17023SJohn Marino 
539e4b17023SJohn Marino bool
can_copy_p(enum machine_mode mode)540e4b17023SJohn Marino can_copy_p (enum machine_mode mode)
541e4b17023SJohn Marino {
542e4b17023SJohn Marino   if (! can_copy_init_p)
543e4b17023SJohn Marino     {
544e4b17023SJohn Marino       compute_can_copy ();
545e4b17023SJohn Marino       can_copy_init_p = true;
546e4b17023SJohn Marino     }
547e4b17023SJohn Marino 
548e4b17023SJohn Marino   return can_copy[mode] != 0;
549e4b17023SJohn Marino }
550e4b17023SJohn Marino 
551e4b17023SJohn Marino /* Cover function to xmalloc to record bytes allocated.  */
552e4b17023SJohn Marino 
553e4b17023SJohn Marino static void *
gmalloc(size_t size)554e4b17023SJohn Marino gmalloc (size_t size)
555e4b17023SJohn Marino {
556e4b17023SJohn Marino   bytes_used += size;
557e4b17023SJohn Marino   return xmalloc (size);
558e4b17023SJohn Marino }
559e4b17023SJohn Marino 
560e4b17023SJohn Marino /* Cover function to xcalloc to record bytes allocated.  */
561e4b17023SJohn Marino 
562e4b17023SJohn Marino static void *
gcalloc(size_t nelem,size_t elsize)563e4b17023SJohn Marino gcalloc (size_t nelem, size_t elsize)
564e4b17023SJohn Marino {
565e4b17023SJohn Marino   bytes_used += nelem * elsize;
566e4b17023SJohn Marino   return xcalloc (nelem, elsize);
567e4b17023SJohn Marino }
568e4b17023SJohn Marino 
569e4b17023SJohn Marino /* Cover function to obstack_alloc.  */
570e4b17023SJohn Marino 
571e4b17023SJohn Marino static void *
gcse_alloc(unsigned long size)572e4b17023SJohn Marino gcse_alloc (unsigned long size)
573e4b17023SJohn Marino {
574e4b17023SJohn Marino   bytes_used += size;
575e4b17023SJohn Marino   return obstack_alloc (&gcse_obstack, size);
576e4b17023SJohn Marino }
577e4b17023SJohn Marino 
578e4b17023SJohn Marino /* Allocate memory for the reg/memory set tracking tables.
579e4b17023SJohn Marino    This is called at the start of each pass.  */
580e4b17023SJohn Marino 
581e4b17023SJohn Marino static void
alloc_gcse_mem(void)582e4b17023SJohn Marino alloc_gcse_mem (void)
583e4b17023SJohn Marino {
584e4b17023SJohn Marino   /* Allocate vars to track sets of regs.  */
585e4b17023SJohn Marino   reg_set_bitmap = ALLOC_REG_SET (NULL);
586e4b17023SJohn Marino 
587e4b17023SJohn Marino   /* Allocate array to keep a list of insns which modify memory in each
588e4b17023SJohn Marino      basic block.  */
589e4b17023SJohn Marino   modify_mem_list = GCNEWVEC (VEC (rtx,heap) *, last_basic_block);
590e4b17023SJohn Marino   canon_modify_mem_list = GCNEWVEC (VEC (modify_pair,heap) *,
591e4b17023SJohn Marino 				    last_basic_block);
592e4b17023SJohn Marino   modify_mem_list_set = BITMAP_ALLOC (NULL);
593e4b17023SJohn Marino   blocks_with_calls = BITMAP_ALLOC (NULL);
594e4b17023SJohn Marino }
595e4b17023SJohn Marino 
596e4b17023SJohn Marino /* Free memory allocated by alloc_gcse_mem.  */
597e4b17023SJohn Marino 
598e4b17023SJohn Marino static void
free_gcse_mem(void)599e4b17023SJohn Marino free_gcse_mem (void)
600e4b17023SJohn Marino {
601e4b17023SJohn Marino   FREE_REG_SET (reg_set_bitmap);
602e4b17023SJohn Marino 
603e4b17023SJohn Marino   free_modify_mem_tables ();
604e4b17023SJohn Marino   BITMAP_FREE (modify_mem_list_set);
605e4b17023SJohn Marino   BITMAP_FREE (blocks_with_calls);
606e4b17023SJohn Marino }
607e4b17023SJohn Marino 
608e4b17023SJohn Marino /* Compute the local properties of each recorded expression.
609e4b17023SJohn Marino 
610e4b17023SJohn Marino    Local properties are those that are defined by the block, irrespective of
611e4b17023SJohn Marino    other blocks.
612e4b17023SJohn Marino 
613e4b17023SJohn Marino    An expression is transparent in a block if its operands are not modified
614e4b17023SJohn Marino    in the block.
615e4b17023SJohn Marino 
616e4b17023SJohn Marino    An expression is computed (locally available) in a block if it is computed
617e4b17023SJohn Marino    at least once and expression would contain the same value if the
618e4b17023SJohn Marino    computation was moved to the end of the block.
619e4b17023SJohn Marino 
620e4b17023SJohn Marino    An expression is locally anticipatable in a block if it is computed at
621e4b17023SJohn Marino    least once and expression would contain the same value if the computation
622e4b17023SJohn Marino    was moved to the beginning of the block.
623e4b17023SJohn Marino 
624e4b17023SJohn Marino    We call this routine for pre and code hoisting.  They all compute
625e4b17023SJohn Marino    basically the same information and thus can easily share this code.
626e4b17023SJohn Marino 
627e4b17023SJohn Marino    TRANSP, COMP, and ANTLOC are destination sbitmaps for recording local
628e4b17023SJohn Marino    properties.  If NULL, then it is not necessary to compute or record that
629e4b17023SJohn Marino    particular property.
630e4b17023SJohn Marino 
631e4b17023SJohn Marino    TABLE controls which hash table to look at.  */
632e4b17023SJohn Marino 
633e4b17023SJohn Marino static void
compute_local_properties(sbitmap * transp,sbitmap * comp,sbitmap * antloc,struct hash_table_d * table)634e4b17023SJohn Marino compute_local_properties (sbitmap *transp, sbitmap *comp, sbitmap *antloc,
635e4b17023SJohn Marino 			  struct hash_table_d *table)
636e4b17023SJohn Marino {
637e4b17023SJohn Marino   unsigned int i;
638e4b17023SJohn Marino 
639e4b17023SJohn Marino   /* Initialize any bitmaps that were passed in.  */
640e4b17023SJohn Marino   if (transp)
641e4b17023SJohn Marino     {
642e4b17023SJohn Marino       sbitmap_vector_ones (transp, last_basic_block);
643e4b17023SJohn Marino     }
644e4b17023SJohn Marino 
645e4b17023SJohn Marino   if (comp)
646e4b17023SJohn Marino     sbitmap_vector_zero (comp, last_basic_block);
647e4b17023SJohn Marino   if (antloc)
648e4b17023SJohn Marino     sbitmap_vector_zero (antloc, last_basic_block);
649e4b17023SJohn Marino 
650e4b17023SJohn Marino   for (i = 0; i < table->size; i++)
651e4b17023SJohn Marino     {
652e4b17023SJohn Marino       struct expr *expr;
653e4b17023SJohn Marino 
654e4b17023SJohn Marino       for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
655e4b17023SJohn Marino 	{
656e4b17023SJohn Marino 	  int indx = expr->bitmap_index;
657e4b17023SJohn Marino 	  struct occr *occr;
658e4b17023SJohn Marino 
659e4b17023SJohn Marino 	  /* The expression is transparent in this block if it is not killed.
660e4b17023SJohn Marino 	     We start by assuming all are transparent [none are killed], and
661e4b17023SJohn Marino 	     then reset the bits for those that are.  */
662e4b17023SJohn Marino 	  if (transp)
663e4b17023SJohn Marino 	    compute_transp (expr->expr, indx, transp);
664e4b17023SJohn Marino 
665e4b17023SJohn Marino 	  /* The occurrences recorded in antic_occr are exactly those that
666e4b17023SJohn Marino 	     we want to set to nonzero in ANTLOC.  */
667e4b17023SJohn Marino 	  if (antloc)
668e4b17023SJohn Marino 	    for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
669e4b17023SJohn Marino 	      {
670e4b17023SJohn Marino 		SET_BIT (antloc[BLOCK_FOR_INSN (occr->insn)->index], indx);
671e4b17023SJohn Marino 
672e4b17023SJohn Marino 		/* While we're scanning the table, this is a good place to
673e4b17023SJohn Marino 		   initialize this.  */
674e4b17023SJohn Marino 		occr->deleted_p = 0;
675e4b17023SJohn Marino 	      }
676e4b17023SJohn Marino 
677e4b17023SJohn Marino 	  /* The occurrences recorded in avail_occr are exactly those that
678e4b17023SJohn Marino 	     we want to set to nonzero in COMP.  */
679e4b17023SJohn Marino 	  if (comp)
680e4b17023SJohn Marino 	    for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
681e4b17023SJohn Marino 	      {
682e4b17023SJohn Marino 		SET_BIT (comp[BLOCK_FOR_INSN (occr->insn)->index], indx);
683e4b17023SJohn Marino 
684e4b17023SJohn Marino 		/* While we're scanning the table, this is a good place to
685e4b17023SJohn Marino 		   initialize this.  */
686e4b17023SJohn Marino 		occr->copied_p = 0;
687e4b17023SJohn Marino 	      }
688e4b17023SJohn Marino 
689e4b17023SJohn Marino 	  /* While we're scanning the table, this is a good place to
690e4b17023SJohn Marino 	     initialize this.  */
691e4b17023SJohn Marino 	  expr->reaching_reg = 0;
692e4b17023SJohn Marino 	}
693e4b17023SJohn Marino     }
694e4b17023SJohn Marino }
695e4b17023SJohn Marino 
696e4b17023SJohn Marino /* Hash table support.  */
697e4b17023SJohn Marino 
698e4b17023SJohn Marino struct reg_avail_info
699e4b17023SJohn Marino {
700e4b17023SJohn Marino   basic_block last_bb;
701e4b17023SJohn Marino   int first_set;
702e4b17023SJohn Marino   int last_set;
703e4b17023SJohn Marino };
704e4b17023SJohn Marino 
705e4b17023SJohn Marino static struct reg_avail_info *reg_avail_info;
706e4b17023SJohn Marino static basic_block current_bb;
707e4b17023SJohn Marino 
708e4b17023SJohn Marino /* See whether X, the source of a set, is something we want to consider for
709e4b17023SJohn Marino    GCSE.  */
710e4b17023SJohn Marino 
711e4b17023SJohn Marino static int
want_to_gcse_p(rtx x,int * max_distance_ptr)712e4b17023SJohn Marino want_to_gcse_p (rtx x, int *max_distance_ptr)
713e4b17023SJohn Marino {
714e4b17023SJohn Marino #ifdef STACK_REGS
715e4b17023SJohn Marino   /* On register stack architectures, don't GCSE constants from the
716e4b17023SJohn Marino      constant pool, as the benefits are often swamped by the overhead
717e4b17023SJohn Marino      of shuffling the register stack between basic blocks.  */
718e4b17023SJohn Marino   if (IS_STACK_MODE (GET_MODE (x)))
719e4b17023SJohn Marino     x = avoid_constant_pool_reference (x);
720e4b17023SJohn Marino #endif
721e4b17023SJohn Marino 
722e4b17023SJohn Marino   /* GCSE'ing constants:
723e4b17023SJohn Marino 
724e4b17023SJohn Marino      We do not specifically distinguish between constant and non-constant
725e4b17023SJohn Marino      expressions in PRE and Hoist.  We use set_src_cost below to limit
726e4b17023SJohn Marino      the maximum distance simple expressions can travel.
727e4b17023SJohn Marino 
728e4b17023SJohn Marino      Nevertheless, constants are much easier to GCSE, and, hence,
729e4b17023SJohn Marino      it is easy to overdo the optimizations.  Usually, excessive PRE and
730e4b17023SJohn Marino      Hoisting of constant leads to increased register pressure.
731e4b17023SJohn Marino 
732e4b17023SJohn Marino      RA can deal with this by rematerialing some of the constants.
733e4b17023SJohn Marino      Therefore, it is important that the back-end generates sets of constants
734e4b17023SJohn Marino      in a way that allows reload rematerialize them under high register
735e4b17023SJohn Marino      pressure, i.e., a pseudo register with REG_EQUAL to constant
736e4b17023SJohn Marino      is set only once.  Failing to do so will result in IRA/reload
737e4b17023SJohn Marino      spilling such constants under high register pressure instead of
738e4b17023SJohn Marino      rematerializing them.  */
739e4b17023SJohn Marino 
740e4b17023SJohn Marino   switch (GET_CODE (x))
741e4b17023SJohn Marino     {
742e4b17023SJohn Marino     case REG:
743e4b17023SJohn Marino     case SUBREG:
744e4b17023SJohn Marino     case CALL:
745e4b17023SJohn Marino       return 0;
746e4b17023SJohn Marino 
747e4b17023SJohn Marino     case CONST_INT:
748e4b17023SJohn Marino     case CONST_DOUBLE:
749e4b17023SJohn Marino     case CONST_FIXED:
750e4b17023SJohn Marino     case CONST_VECTOR:
751e4b17023SJohn Marino       if (!doing_code_hoisting_p)
752e4b17023SJohn Marino 	/* Do not PRE constants.  */
753e4b17023SJohn Marino 	return 0;
754e4b17023SJohn Marino 
755e4b17023SJohn Marino       /* FALLTHRU */
756e4b17023SJohn Marino 
757e4b17023SJohn Marino     default:
758e4b17023SJohn Marino       if (doing_code_hoisting_p)
759e4b17023SJohn Marino 	/* PRE doesn't implement max_distance restriction.  */
760e4b17023SJohn Marino 	{
761e4b17023SJohn Marino 	  int cost;
762e4b17023SJohn Marino 	  int max_distance;
763e4b17023SJohn Marino 
764e4b17023SJohn Marino 	  gcc_assert (!optimize_function_for_speed_p (cfun)
765e4b17023SJohn Marino 		      && optimize_function_for_size_p (cfun));
766e4b17023SJohn Marino 	  cost = set_src_cost (x, 0);
767e4b17023SJohn Marino 
768e4b17023SJohn Marino 	  if (cost < COSTS_N_INSNS (GCSE_UNRESTRICTED_COST))
769e4b17023SJohn Marino 	    {
770e4b17023SJohn Marino 	      max_distance = (GCSE_COST_DISTANCE_RATIO * cost) / 10;
771e4b17023SJohn Marino 	      if (max_distance == 0)
772e4b17023SJohn Marino 		return 0;
773e4b17023SJohn Marino 
774e4b17023SJohn Marino 	      gcc_assert (max_distance > 0);
775e4b17023SJohn Marino 	    }
776e4b17023SJohn Marino 	  else
777e4b17023SJohn Marino 	    max_distance = 0;
778e4b17023SJohn Marino 
779e4b17023SJohn Marino 	  if (max_distance_ptr)
780e4b17023SJohn Marino 	    *max_distance_ptr = max_distance;
781e4b17023SJohn Marino 	}
782e4b17023SJohn Marino 
783e4b17023SJohn Marino       return can_assign_to_reg_without_clobbers_p (x);
784e4b17023SJohn Marino     }
785e4b17023SJohn Marino }
786e4b17023SJohn Marino 
787e4b17023SJohn Marino /* Used internally by can_assign_to_reg_without_clobbers_p.  */
788e4b17023SJohn Marino 
789e4b17023SJohn Marino static GTY(()) rtx test_insn;
790e4b17023SJohn Marino 
791e4b17023SJohn Marino /* Return true if we can assign X to a pseudo register such that the
792e4b17023SJohn Marino    resulting insn does not result in clobbering a hard register as a
793e4b17023SJohn Marino    side-effect.
794e4b17023SJohn Marino 
795e4b17023SJohn Marino    Additionally, if the target requires it, check that the resulting insn
796e4b17023SJohn Marino    can be copied.  If it cannot, this means that X is special and probably
797e4b17023SJohn Marino    has hidden side-effects we don't want to mess with.
798e4b17023SJohn Marino 
799e4b17023SJohn Marino    This function is typically used by code motion passes, to verify
800e4b17023SJohn Marino    that it is safe to insert an insn without worrying about clobbering
801e4b17023SJohn Marino    maybe live hard regs.  */
802e4b17023SJohn Marino 
803e4b17023SJohn Marino bool
can_assign_to_reg_without_clobbers_p(rtx x)804e4b17023SJohn Marino can_assign_to_reg_without_clobbers_p (rtx x)
805e4b17023SJohn Marino {
806e4b17023SJohn Marino   int num_clobbers = 0;
807e4b17023SJohn Marino   int icode;
808e4b17023SJohn Marino 
809e4b17023SJohn Marino   /* If this is a valid operand, we are OK.  If it's VOIDmode, we aren't.  */
810e4b17023SJohn Marino   if (general_operand (x, GET_MODE (x)))
811e4b17023SJohn Marino     return 1;
812e4b17023SJohn Marino   else if (GET_MODE (x) == VOIDmode)
813e4b17023SJohn Marino     return 0;
814e4b17023SJohn Marino 
815e4b17023SJohn Marino   /* Otherwise, check if we can make a valid insn from it.  First initialize
816e4b17023SJohn Marino      our test insn if we haven't already.  */
817e4b17023SJohn Marino   if (test_insn == 0)
818e4b17023SJohn Marino     {
819e4b17023SJohn Marino       test_insn
820e4b17023SJohn Marino 	= make_insn_raw (gen_rtx_SET (VOIDmode,
821e4b17023SJohn Marino 				      gen_rtx_REG (word_mode,
822e4b17023SJohn Marino 						   FIRST_PSEUDO_REGISTER * 2),
823e4b17023SJohn Marino 				      const0_rtx));
824e4b17023SJohn Marino       NEXT_INSN (test_insn) = PREV_INSN (test_insn) = 0;
825e4b17023SJohn Marino     }
826e4b17023SJohn Marino 
827e4b17023SJohn Marino   /* Now make an insn like the one we would make when GCSE'ing and see if
828e4b17023SJohn Marino      valid.  */
829e4b17023SJohn Marino   PUT_MODE (SET_DEST (PATTERN (test_insn)), GET_MODE (x));
830e4b17023SJohn Marino   SET_SRC (PATTERN (test_insn)) = x;
831e4b17023SJohn Marino 
832e4b17023SJohn Marino   icode = recog (PATTERN (test_insn), test_insn, &num_clobbers);
833e4b17023SJohn Marino   if (icode < 0)
834e4b17023SJohn Marino     return false;
835e4b17023SJohn Marino 
836e4b17023SJohn Marino   if (num_clobbers > 0 && added_clobbers_hard_reg_p (icode))
837e4b17023SJohn Marino     return false;
838e4b17023SJohn Marino 
839e4b17023SJohn Marino   if (targetm.cannot_copy_insn_p && targetm.cannot_copy_insn_p (test_insn))
840e4b17023SJohn Marino     return false;
841e4b17023SJohn Marino 
842e4b17023SJohn Marino   return true;
843e4b17023SJohn Marino }
844e4b17023SJohn Marino 
845e4b17023SJohn Marino /* Return nonzero if the operands of expression X are unchanged from the
846e4b17023SJohn Marino    start of INSN's basic block up to but not including INSN (if AVAIL_P == 0),
847e4b17023SJohn Marino    or from INSN to the end of INSN's basic block (if AVAIL_P != 0).  */
848e4b17023SJohn Marino 
849e4b17023SJohn Marino static int
oprs_unchanged_p(const_rtx x,const_rtx insn,int avail_p)850e4b17023SJohn Marino oprs_unchanged_p (const_rtx x, const_rtx insn, int avail_p)
851e4b17023SJohn Marino {
852e4b17023SJohn Marino   int i, j;
853e4b17023SJohn Marino   enum rtx_code code;
854e4b17023SJohn Marino   const char *fmt;
855e4b17023SJohn Marino 
856e4b17023SJohn Marino   if (x == 0)
857e4b17023SJohn Marino     return 1;
858e4b17023SJohn Marino 
859e4b17023SJohn Marino   code = GET_CODE (x);
860e4b17023SJohn Marino   switch (code)
861e4b17023SJohn Marino     {
862e4b17023SJohn Marino     case REG:
863e4b17023SJohn Marino       {
864e4b17023SJohn Marino 	struct reg_avail_info *info = &reg_avail_info[REGNO (x)];
865e4b17023SJohn Marino 
866e4b17023SJohn Marino 	if (info->last_bb != current_bb)
867e4b17023SJohn Marino 	  return 1;
868e4b17023SJohn Marino 	if (avail_p)
869e4b17023SJohn Marino 	  return info->last_set < DF_INSN_LUID (insn);
870e4b17023SJohn Marino 	else
871e4b17023SJohn Marino 	  return info->first_set >= DF_INSN_LUID (insn);
872e4b17023SJohn Marino       }
873e4b17023SJohn Marino 
874e4b17023SJohn Marino     case MEM:
875e4b17023SJohn Marino       if (load_killed_in_block_p (current_bb, DF_INSN_LUID (insn),
876e4b17023SJohn Marino 				  x, avail_p))
877e4b17023SJohn Marino 	return 0;
878e4b17023SJohn Marino       else
879e4b17023SJohn Marino 	return oprs_unchanged_p (XEXP (x, 0), insn, avail_p);
880e4b17023SJohn Marino 
881e4b17023SJohn Marino     case PRE_DEC:
882e4b17023SJohn Marino     case PRE_INC:
883e4b17023SJohn Marino     case POST_DEC:
884e4b17023SJohn Marino     case POST_INC:
885e4b17023SJohn Marino     case PRE_MODIFY:
886e4b17023SJohn Marino     case POST_MODIFY:
887e4b17023SJohn Marino       return 0;
888e4b17023SJohn Marino 
889e4b17023SJohn Marino     case PC:
890e4b17023SJohn Marino     case CC0: /*FIXME*/
891e4b17023SJohn Marino     case CONST:
892e4b17023SJohn Marino     case CONST_INT:
893e4b17023SJohn Marino     case CONST_DOUBLE:
894e4b17023SJohn Marino     case CONST_FIXED:
895e4b17023SJohn Marino     case CONST_VECTOR:
896e4b17023SJohn Marino     case SYMBOL_REF:
897e4b17023SJohn Marino     case LABEL_REF:
898e4b17023SJohn Marino     case ADDR_VEC:
899e4b17023SJohn Marino     case ADDR_DIFF_VEC:
900e4b17023SJohn Marino       return 1;
901e4b17023SJohn Marino 
902e4b17023SJohn Marino     default:
903e4b17023SJohn Marino       break;
904e4b17023SJohn Marino     }
905e4b17023SJohn Marino 
906e4b17023SJohn Marino   for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
907e4b17023SJohn Marino     {
908e4b17023SJohn Marino       if (fmt[i] == 'e')
909e4b17023SJohn Marino 	{
910e4b17023SJohn Marino 	  /* If we are about to do the last recursive call needed at this
911e4b17023SJohn Marino 	     level, change it into iteration.  This function is called enough
912e4b17023SJohn Marino 	     to be worth it.  */
913e4b17023SJohn Marino 	  if (i == 0)
914e4b17023SJohn Marino 	    return oprs_unchanged_p (XEXP (x, i), insn, avail_p);
915e4b17023SJohn Marino 
916e4b17023SJohn Marino 	  else if (! oprs_unchanged_p (XEXP (x, i), insn, avail_p))
917e4b17023SJohn Marino 	    return 0;
918e4b17023SJohn Marino 	}
919e4b17023SJohn Marino       else if (fmt[i] == 'E')
920e4b17023SJohn Marino 	for (j = 0; j < XVECLEN (x, i); j++)
921e4b17023SJohn Marino 	  if (! oprs_unchanged_p (XVECEXP (x, i, j), insn, avail_p))
922e4b17023SJohn Marino 	    return 0;
923e4b17023SJohn Marino     }
924e4b17023SJohn Marino 
925e4b17023SJohn Marino   return 1;
926e4b17023SJohn Marino }
927e4b17023SJohn Marino 
928e4b17023SJohn Marino /* Info passed from load_killed_in_block_p to mems_conflict_for_gcse_p.  */
929e4b17023SJohn Marino 
930e4b17023SJohn Marino struct mem_conflict_info
931e4b17023SJohn Marino {
932e4b17023SJohn Marino   /* A memory reference for a load instruction, mems_conflict_for_gcse_p will
933e4b17023SJohn Marino      see if a memory store conflicts with this memory load.  */
934e4b17023SJohn Marino   const_rtx mem;
935e4b17023SJohn Marino 
936e4b17023SJohn Marino   /* True if mems_conflict_for_gcse_p finds a conflict between two memory
937e4b17023SJohn Marino      references.  */
938e4b17023SJohn Marino   bool conflict;
939e4b17023SJohn Marino };
940e4b17023SJohn Marino 
941e4b17023SJohn Marino /* DEST is the output of an instruction.  If it is a memory reference and
942e4b17023SJohn Marino    possibly conflicts with the load found in DATA, then communicate this
943e4b17023SJohn Marino    information back through DATA.  */
944e4b17023SJohn Marino 
945e4b17023SJohn Marino static void
mems_conflict_for_gcse_p(rtx dest,const_rtx setter ATTRIBUTE_UNUSED,void * data)946e4b17023SJohn Marino mems_conflict_for_gcse_p (rtx dest, const_rtx setter ATTRIBUTE_UNUSED,
947e4b17023SJohn Marino 			  void *data)
948e4b17023SJohn Marino {
949e4b17023SJohn Marino   struct mem_conflict_info *mci = (struct mem_conflict_info *) data;
950e4b17023SJohn Marino 
951e4b17023SJohn Marino   while (GET_CODE (dest) == SUBREG
952e4b17023SJohn Marino 	 || GET_CODE (dest) == ZERO_EXTRACT
953e4b17023SJohn Marino 	 || GET_CODE (dest) == STRICT_LOW_PART)
954e4b17023SJohn Marino     dest = XEXP (dest, 0);
955e4b17023SJohn Marino 
956e4b17023SJohn Marino   /* If DEST is not a MEM, then it will not conflict with the load.  Note
957e4b17023SJohn Marino      that function calls are assumed to clobber memory, but are handled
958e4b17023SJohn Marino      elsewhere.  */
959e4b17023SJohn Marino   if (! MEM_P (dest))
960e4b17023SJohn Marino     return;
961e4b17023SJohn Marino 
962e4b17023SJohn Marino   /* If we are setting a MEM in our list of specially recognized MEMs,
963e4b17023SJohn Marino      don't mark as killed this time.  */
964e4b17023SJohn Marino   if (pre_ldst_mems != NULL && expr_equiv_p (dest, mci->mem))
965e4b17023SJohn Marino     {
966e4b17023SJohn Marino       if (!find_rtx_in_ldst (dest))
967e4b17023SJohn Marino 	mci->conflict = true;
968e4b17023SJohn Marino       return;
969e4b17023SJohn Marino     }
970e4b17023SJohn Marino 
971e4b17023SJohn Marino   if (true_dependence (dest, GET_MODE (dest), mci->mem))
972e4b17023SJohn Marino     mci->conflict = true;
973e4b17023SJohn Marino }
974e4b17023SJohn Marino 
975e4b17023SJohn Marino /* Return nonzero if the expression in X (a memory reference) is killed
976e4b17023SJohn Marino    in block BB before or after the insn with the LUID in UID_LIMIT.
977e4b17023SJohn Marino    AVAIL_P is nonzero for kills after UID_LIMIT, and zero for kills
978e4b17023SJohn Marino    before UID_LIMIT.
979e4b17023SJohn Marino 
980e4b17023SJohn Marino    To check the entire block, set UID_LIMIT to max_uid + 1 and
981e4b17023SJohn Marino    AVAIL_P to 0.  */
982e4b17023SJohn Marino 
983e4b17023SJohn Marino static int
load_killed_in_block_p(const_basic_block bb,int uid_limit,const_rtx x,int avail_p)984e4b17023SJohn Marino load_killed_in_block_p (const_basic_block bb, int uid_limit, const_rtx x,
985e4b17023SJohn Marino 			int avail_p)
986e4b17023SJohn Marino {
987e4b17023SJohn Marino   VEC (rtx,heap) *list = modify_mem_list[bb->index];
988e4b17023SJohn Marino   rtx setter;
989e4b17023SJohn Marino   unsigned ix;
990e4b17023SJohn Marino 
991e4b17023SJohn Marino   /* If this is a readonly then we aren't going to be changing it.  */
992e4b17023SJohn Marino   if (MEM_READONLY_P (x))
993e4b17023SJohn Marino     return 0;
994e4b17023SJohn Marino 
995e4b17023SJohn Marino   FOR_EACH_VEC_ELT_REVERSE (rtx, list, ix, setter)
996e4b17023SJohn Marino     {
997e4b17023SJohn Marino       struct mem_conflict_info mci;
998e4b17023SJohn Marino 
999e4b17023SJohn Marino       /* Ignore entries in the list that do not apply.  */
1000e4b17023SJohn Marino       if ((avail_p
1001e4b17023SJohn Marino 	   && DF_INSN_LUID (setter) < uid_limit)
1002e4b17023SJohn Marino 	  || (! avail_p
1003e4b17023SJohn Marino 	      && DF_INSN_LUID (setter) > uid_limit))
1004e4b17023SJohn Marino 	continue;
1005e4b17023SJohn Marino 
1006e4b17023SJohn Marino       /* If SETTER is a call everything is clobbered.  Note that calls
1007e4b17023SJohn Marino 	 to pure functions are never put on the list, so we need not
1008e4b17023SJohn Marino 	 worry about them.  */
1009e4b17023SJohn Marino       if (CALL_P (setter))
1010e4b17023SJohn Marino 	return 1;
1011e4b17023SJohn Marino 
1012e4b17023SJohn Marino       /* SETTER must be an INSN of some kind that sets memory.  Call
1013e4b17023SJohn Marino 	 note_stores to examine each hunk of memory that is modified.  */
1014e4b17023SJohn Marino       mci.mem = x;
1015e4b17023SJohn Marino       mci.conflict = false;
1016e4b17023SJohn Marino       note_stores (PATTERN (setter), mems_conflict_for_gcse_p, &mci);
1017e4b17023SJohn Marino       if (mci.conflict)
1018e4b17023SJohn Marino 	return 1;
1019e4b17023SJohn Marino     }
1020e4b17023SJohn Marino   return 0;
1021e4b17023SJohn Marino }
1022e4b17023SJohn Marino 
1023e4b17023SJohn Marino /* Return nonzero if the operands of expression X are unchanged from
1024e4b17023SJohn Marino    the start of INSN's basic block up to but not including INSN.  */
1025e4b17023SJohn Marino 
1026e4b17023SJohn Marino static int
oprs_anticipatable_p(const_rtx x,const_rtx insn)1027e4b17023SJohn Marino oprs_anticipatable_p (const_rtx x, const_rtx insn)
1028e4b17023SJohn Marino {
1029e4b17023SJohn Marino   return oprs_unchanged_p (x, insn, 0);
1030e4b17023SJohn Marino }
1031e4b17023SJohn Marino 
1032e4b17023SJohn Marino /* Return nonzero if the operands of expression X are unchanged from
1033e4b17023SJohn Marino    INSN to the end of INSN's basic block.  */
1034e4b17023SJohn Marino 
1035e4b17023SJohn Marino static int
oprs_available_p(const_rtx x,const_rtx insn)1036e4b17023SJohn Marino oprs_available_p (const_rtx x, const_rtx insn)
1037e4b17023SJohn Marino {
1038e4b17023SJohn Marino   return oprs_unchanged_p (x, insn, 1);
1039e4b17023SJohn Marino }
1040e4b17023SJohn Marino 
1041e4b17023SJohn Marino /* Hash expression X.
1042e4b17023SJohn Marino 
1043e4b17023SJohn Marino    MODE is only used if X is a CONST_INT.  DO_NOT_RECORD_P is a boolean
1044e4b17023SJohn Marino    indicating if a volatile operand is found or if the expression contains
1045e4b17023SJohn Marino    something we don't want to insert in the table.  HASH_TABLE_SIZE is
1046e4b17023SJohn Marino    the current size of the hash table to be probed.  */
1047e4b17023SJohn Marino 
1048e4b17023SJohn Marino static unsigned int
hash_expr(const_rtx x,enum machine_mode mode,int * do_not_record_p,int hash_table_size)1049e4b17023SJohn Marino hash_expr (const_rtx x, enum machine_mode mode, int *do_not_record_p,
1050e4b17023SJohn Marino 	   int hash_table_size)
1051e4b17023SJohn Marino {
1052e4b17023SJohn Marino   unsigned int hash;
1053e4b17023SJohn Marino 
1054e4b17023SJohn Marino   *do_not_record_p = 0;
1055e4b17023SJohn Marino 
1056e4b17023SJohn Marino   hash = hash_rtx (x, mode, do_not_record_p, NULL, /*have_reg_qty=*/false);
1057e4b17023SJohn Marino   return hash % hash_table_size;
1058e4b17023SJohn Marino }
1059e4b17023SJohn Marino 
1060e4b17023SJohn Marino /* Return nonzero if exp1 is equivalent to exp2.  */
1061e4b17023SJohn Marino 
1062e4b17023SJohn Marino static int
expr_equiv_p(const_rtx x,const_rtx y)1063e4b17023SJohn Marino expr_equiv_p (const_rtx x, const_rtx y)
1064e4b17023SJohn Marino {
1065e4b17023SJohn Marino   return exp_equiv_p (x, y, 0, true);
1066e4b17023SJohn Marino }
1067e4b17023SJohn Marino 
1068e4b17023SJohn Marino /* Insert expression X in INSN in the hash TABLE.
1069e4b17023SJohn Marino    If it is already present, record it as the last occurrence in INSN's
1070e4b17023SJohn Marino    basic block.
1071e4b17023SJohn Marino 
1072e4b17023SJohn Marino    MODE is the mode of the value X is being stored into.
1073e4b17023SJohn Marino    It is only used if X is a CONST_INT.
1074e4b17023SJohn Marino 
1075e4b17023SJohn Marino    ANTIC_P is nonzero if X is an anticipatable expression.
1076e4b17023SJohn Marino    AVAIL_P is nonzero if X is an available expression.
1077e4b17023SJohn Marino 
1078e4b17023SJohn Marino    MAX_DISTANCE is the maximum distance in instructions this expression can
1079e4b17023SJohn Marino    be moved.  */
1080e4b17023SJohn Marino 
1081e4b17023SJohn Marino static void
insert_expr_in_table(rtx x,enum machine_mode mode,rtx insn,int antic_p,int avail_p,int max_distance,struct hash_table_d * table)1082e4b17023SJohn Marino insert_expr_in_table (rtx x, enum machine_mode mode, rtx insn, int antic_p,
1083e4b17023SJohn Marino 		      int avail_p, int max_distance, struct hash_table_d *table)
1084e4b17023SJohn Marino {
1085e4b17023SJohn Marino   int found, do_not_record_p;
1086e4b17023SJohn Marino   unsigned int hash;
1087e4b17023SJohn Marino   struct expr *cur_expr, *last_expr = NULL;
1088e4b17023SJohn Marino   struct occr *antic_occr, *avail_occr;
1089e4b17023SJohn Marino 
1090e4b17023SJohn Marino   hash = hash_expr (x, mode, &do_not_record_p, table->size);
1091e4b17023SJohn Marino 
1092e4b17023SJohn Marino   /* Do not insert expression in table if it contains volatile operands,
1093e4b17023SJohn Marino      or if hash_expr determines the expression is something we don't want
1094e4b17023SJohn Marino      to or can't handle.  */
1095e4b17023SJohn Marino   if (do_not_record_p)
1096e4b17023SJohn Marino     return;
1097e4b17023SJohn Marino 
1098e4b17023SJohn Marino   cur_expr = table->table[hash];
1099e4b17023SJohn Marino   found = 0;
1100e4b17023SJohn Marino 
1101e4b17023SJohn Marino   while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
1102e4b17023SJohn Marino     {
1103e4b17023SJohn Marino       /* If the expression isn't found, save a pointer to the end of
1104e4b17023SJohn Marino 	 the list.  */
1105e4b17023SJohn Marino       last_expr = cur_expr;
1106e4b17023SJohn Marino       cur_expr = cur_expr->next_same_hash;
1107e4b17023SJohn Marino     }
1108e4b17023SJohn Marino 
1109e4b17023SJohn Marino   if (! found)
1110e4b17023SJohn Marino     {
1111e4b17023SJohn Marino       cur_expr = GOBNEW (struct expr);
1112e4b17023SJohn Marino       bytes_used += sizeof (struct expr);
1113e4b17023SJohn Marino       if (table->table[hash] == NULL)
1114e4b17023SJohn Marino 	/* This is the first pattern that hashed to this index.  */
1115e4b17023SJohn Marino 	table->table[hash] = cur_expr;
1116e4b17023SJohn Marino       else
1117e4b17023SJohn Marino 	/* Add EXPR to end of this hash chain.  */
1118e4b17023SJohn Marino 	last_expr->next_same_hash = cur_expr;
1119e4b17023SJohn Marino 
1120e4b17023SJohn Marino       /* Set the fields of the expr element.  */
1121e4b17023SJohn Marino       cur_expr->expr = x;
1122e4b17023SJohn Marino       cur_expr->bitmap_index = table->n_elems++;
1123e4b17023SJohn Marino       cur_expr->next_same_hash = NULL;
1124e4b17023SJohn Marino       cur_expr->antic_occr = NULL;
1125e4b17023SJohn Marino       cur_expr->avail_occr = NULL;
1126e4b17023SJohn Marino       gcc_assert (max_distance >= 0);
1127e4b17023SJohn Marino       cur_expr->max_distance = max_distance;
1128e4b17023SJohn Marino     }
1129e4b17023SJohn Marino   else
1130e4b17023SJohn Marino     gcc_assert (cur_expr->max_distance == max_distance);
1131e4b17023SJohn Marino 
1132e4b17023SJohn Marino   /* Now record the occurrence(s).  */
1133e4b17023SJohn Marino   if (antic_p)
1134e4b17023SJohn Marino     {
1135e4b17023SJohn Marino       antic_occr = cur_expr->antic_occr;
1136e4b17023SJohn Marino 
1137e4b17023SJohn Marino       if (antic_occr
1138e4b17023SJohn Marino 	  && BLOCK_FOR_INSN (antic_occr->insn) != BLOCK_FOR_INSN (insn))
1139e4b17023SJohn Marino 	antic_occr = NULL;
1140e4b17023SJohn Marino 
1141e4b17023SJohn Marino       if (antic_occr)
1142e4b17023SJohn Marino 	/* Found another instance of the expression in the same basic block.
1143e4b17023SJohn Marino 	   Prefer the currently recorded one.  We want the first one in the
1144e4b17023SJohn Marino 	   block and the block is scanned from start to end.  */
1145e4b17023SJohn Marino 	; /* nothing to do */
1146e4b17023SJohn Marino       else
1147e4b17023SJohn Marino 	{
1148e4b17023SJohn Marino 	  /* First occurrence of this expression in this basic block.  */
1149e4b17023SJohn Marino 	  antic_occr = GOBNEW (struct occr);
1150e4b17023SJohn Marino 	  bytes_used += sizeof (struct occr);
1151e4b17023SJohn Marino 	  antic_occr->insn = insn;
1152e4b17023SJohn Marino 	  antic_occr->next = cur_expr->antic_occr;
1153e4b17023SJohn Marino 	  antic_occr->deleted_p = 0;
1154e4b17023SJohn Marino 	  cur_expr->antic_occr = antic_occr;
1155e4b17023SJohn Marino 	}
1156e4b17023SJohn Marino     }
1157e4b17023SJohn Marino 
1158e4b17023SJohn Marino   if (avail_p)
1159e4b17023SJohn Marino     {
1160e4b17023SJohn Marino       avail_occr = cur_expr->avail_occr;
1161e4b17023SJohn Marino 
1162e4b17023SJohn Marino       if (avail_occr
1163e4b17023SJohn Marino 	  && BLOCK_FOR_INSN (avail_occr->insn) == BLOCK_FOR_INSN (insn))
1164e4b17023SJohn Marino 	{
1165e4b17023SJohn Marino 	  /* Found another instance of the expression in the same basic block.
1166e4b17023SJohn Marino 	     Prefer this occurrence to the currently recorded one.  We want
1167e4b17023SJohn Marino 	     the last one in the block and the block is scanned from start
1168e4b17023SJohn Marino 	     to end.  */
1169e4b17023SJohn Marino 	  avail_occr->insn = insn;
1170e4b17023SJohn Marino 	}
1171e4b17023SJohn Marino       else
1172e4b17023SJohn Marino 	{
1173e4b17023SJohn Marino 	  /* First occurrence of this expression in this basic block.  */
1174e4b17023SJohn Marino 	  avail_occr = GOBNEW (struct occr);
1175e4b17023SJohn Marino 	  bytes_used += sizeof (struct occr);
1176e4b17023SJohn Marino 	  avail_occr->insn = insn;
1177e4b17023SJohn Marino 	  avail_occr->next = cur_expr->avail_occr;
1178e4b17023SJohn Marino 	  avail_occr->deleted_p = 0;
1179e4b17023SJohn Marino 	  cur_expr->avail_occr = avail_occr;
1180e4b17023SJohn Marino 	}
1181e4b17023SJohn Marino     }
1182e4b17023SJohn Marino }
1183e4b17023SJohn Marino 
1184e4b17023SJohn Marino /* Scan SET present in INSN and add an entry to the hash TABLE.  */
1185e4b17023SJohn Marino 
1186e4b17023SJohn Marino static void
hash_scan_set(rtx set,rtx insn,struct hash_table_d * table)1187e4b17023SJohn Marino hash_scan_set (rtx set, rtx insn, struct hash_table_d *table)
1188e4b17023SJohn Marino {
1189e4b17023SJohn Marino   rtx src = SET_SRC (set);
1190e4b17023SJohn Marino   rtx dest = SET_DEST (set);
1191e4b17023SJohn Marino   rtx note;
1192e4b17023SJohn Marino 
1193e4b17023SJohn Marino   if (GET_CODE (src) == CALL)
1194e4b17023SJohn Marino     hash_scan_call (src, insn, table);
1195e4b17023SJohn Marino 
1196e4b17023SJohn Marino   else if (REG_P (dest))
1197e4b17023SJohn Marino     {
1198e4b17023SJohn Marino       unsigned int regno = REGNO (dest);
1199e4b17023SJohn Marino       int max_distance = 0;
1200e4b17023SJohn Marino 
1201e4b17023SJohn Marino       /* See if a REG_EQUAL note shows this equivalent to a simpler expression.
1202e4b17023SJohn Marino 
1203e4b17023SJohn Marino 	 This allows us to do a single GCSE pass and still eliminate
1204e4b17023SJohn Marino 	 redundant constants, addresses or other expressions that are
1205e4b17023SJohn Marino 	 constructed with multiple instructions.
1206e4b17023SJohn Marino 
1207e4b17023SJohn Marino 	 However, keep the original SRC if INSN is a simple reg-reg move.
1208e4b17023SJohn Marino 	 In this case, there will almost always be a REG_EQUAL note on the
1209e4b17023SJohn Marino 	 insn that sets SRC.  By recording the REG_EQUAL value here as SRC
1210e4b17023SJohn Marino 	 for INSN, we miss copy propagation opportunities and we perform the
1211e4b17023SJohn Marino 	 same PRE GCSE operation repeatedly on the same REG_EQUAL value if we
1212e4b17023SJohn Marino 	 do more than one PRE GCSE pass.
1213e4b17023SJohn Marino 
1214e4b17023SJohn Marino 	 Note that this does not impede profitable constant propagations.  We
1215e4b17023SJohn Marino 	 "look through" reg-reg sets in lookup_avail_set.  */
1216e4b17023SJohn Marino       note = find_reg_equal_equiv_note (insn);
1217e4b17023SJohn Marino       if (note != 0
1218e4b17023SJohn Marino 	  && REG_NOTE_KIND (note) == REG_EQUAL
1219e4b17023SJohn Marino 	  && !REG_P (src)
1220e4b17023SJohn Marino 	  && want_to_gcse_p (XEXP (note, 0), NULL))
1221e4b17023SJohn Marino 	src = XEXP (note, 0), set = gen_rtx_SET (VOIDmode, dest, src);
1222e4b17023SJohn Marino 
1223e4b17023SJohn Marino       /* Only record sets of pseudo-regs in the hash table.  */
1224e4b17023SJohn Marino       if (regno >= FIRST_PSEUDO_REGISTER
1225e4b17023SJohn Marino 	  /* Don't GCSE something if we can't do a reg/reg copy.  */
1226e4b17023SJohn Marino 	  && can_copy_p (GET_MODE (dest))
1227e4b17023SJohn Marino 	  /* GCSE commonly inserts instruction after the insn.  We can't
1228e4b17023SJohn Marino 	     do that easily for EH edges so disable GCSE on these for now.  */
1229e4b17023SJohn Marino 	  /* ??? We can now easily create new EH landing pads at the
1230e4b17023SJohn Marino 	     gimple level, for splitting edges; there's no reason we
1231e4b17023SJohn Marino 	     can't do the same thing at the rtl level.  */
1232e4b17023SJohn Marino 	  && !can_throw_internal (insn)
1233e4b17023SJohn Marino 	  /* Is SET_SRC something we want to gcse?  */
1234e4b17023SJohn Marino 	  && want_to_gcse_p (src, &max_distance)
1235e4b17023SJohn Marino 	  /* Don't CSE a nop.  */
1236e4b17023SJohn Marino 	  && ! set_noop_p (set)
1237e4b17023SJohn Marino 	  /* Don't GCSE if it has attached REG_EQUIV note.
1238e4b17023SJohn Marino 	     At this point this only function parameters should have
1239e4b17023SJohn Marino 	     REG_EQUIV notes and if the argument slot is used somewhere
1240e4b17023SJohn Marino 	     explicitly, it means address of parameter has been taken,
1241e4b17023SJohn Marino 	     so we should not extend the lifetime of the pseudo.  */
1242e4b17023SJohn Marino 	  && (note == NULL_RTX || ! MEM_P (XEXP (note, 0))))
1243e4b17023SJohn Marino 	{
1244e4b17023SJohn Marino 	  /* An expression is not anticipatable if its operands are
1245e4b17023SJohn Marino 	     modified before this insn or if this is not the only SET in
1246e4b17023SJohn Marino 	     this insn.  The latter condition does not have to mean that
1247e4b17023SJohn Marino 	     SRC itself is not anticipatable, but we just will not be
1248e4b17023SJohn Marino 	     able to handle code motion of insns with multiple sets.  */
1249e4b17023SJohn Marino 	  int antic_p = oprs_anticipatable_p (src, insn)
1250e4b17023SJohn Marino 			&& !multiple_sets (insn);
1251e4b17023SJohn Marino 	  /* An expression is not available if its operands are
1252e4b17023SJohn Marino 	     subsequently modified, including this insn.  It's also not
1253e4b17023SJohn Marino 	     available if this is a branch, because we can't insert
1254e4b17023SJohn Marino 	     a set after the branch.  */
1255e4b17023SJohn Marino 	  int avail_p = (oprs_available_p (src, insn)
1256e4b17023SJohn Marino 			 && ! JUMP_P (insn));
1257e4b17023SJohn Marino 
1258e4b17023SJohn Marino 	  insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p,
1259e4b17023SJohn Marino 				max_distance, table);
1260e4b17023SJohn Marino 	}
1261e4b17023SJohn Marino     }
1262e4b17023SJohn Marino   /* In case of store we want to consider the memory value as available in
1263e4b17023SJohn Marino      the REG stored in that memory. This makes it possible to remove
1264e4b17023SJohn Marino      redundant loads from due to stores to the same location.  */
1265e4b17023SJohn Marino   else if (flag_gcse_las && REG_P (src) && MEM_P (dest))
1266e4b17023SJohn Marino       {
1267e4b17023SJohn Marino         unsigned int regno = REGNO (src);
1268e4b17023SJohn Marino 	int max_distance = 0;
1269e4b17023SJohn Marino 
1270e4b17023SJohn Marino 	/* Only record sets of pseudo-regs in the hash table.  */
1271e4b17023SJohn Marino         if (regno >= FIRST_PSEUDO_REGISTER
1272e4b17023SJohn Marino 	   /* Don't GCSE something if we can't do a reg/reg copy.  */
1273e4b17023SJohn Marino 	   && can_copy_p (GET_MODE (src))
1274e4b17023SJohn Marino 	   /* GCSE commonly inserts instruction after the insn.  We can't
1275e4b17023SJohn Marino 	      do that easily for EH edges so disable GCSE on these for now.  */
1276e4b17023SJohn Marino 	   && !can_throw_internal (insn)
1277e4b17023SJohn Marino 	   /* Is SET_DEST something we want to gcse?  */
1278e4b17023SJohn Marino 	   && want_to_gcse_p (dest, &max_distance)
1279e4b17023SJohn Marino 	   /* Don't CSE a nop.  */
1280e4b17023SJohn Marino 	   && ! set_noop_p (set)
1281e4b17023SJohn Marino 	   /* Don't GCSE if it has attached REG_EQUIV note.
1282e4b17023SJohn Marino 	      At this point this only function parameters should have
1283e4b17023SJohn Marino 	      REG_EQUIV notes and if the argument slot is used somewhere
1284e4b17023SJohn Marino 	      explicitly, it means address of parameter has been taken,
1285e4b17023SJohn Marino 	      so we should not extend the lifetime of the pseudo.  */
1286e4b17023SJohn Marino 	   && ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) == 0
1287e4b17023SJohn Marino 	       || ! MEM_P (XEXP (note, 0))))
1288e4b17023SJohn Marino              {
1289e4b17023SJohn Marino                /* Stores are never anticipatable.  */
1290e4b17023SJohn Marino                int antic_p = 0;
1291e4b17023SJohn Marino 	       /* An expression is not available if its operands are
1292e4b17023SJohn Marino 	          subsequently modified, including this insn.  It's also not
1293e4b17023SJohn Marino 	          available if this is a branch, because we can't insert
1294e4b17023SJohn Marino 	          a set after the branch.  */
1295e4b17023SJohn Marino                int avail_p = oprs_available_p (dest, insn)
1296e4b17023SJohn Marino 			     && ! JUMP_P (insn);
1297e4b17023SJohn Marino 
1298e4b17023SJohn Marino 	       /* Record the memory expression (DEST) in the hash table.  */
1299e4b17023SJohn Marino 	       insert_expr_in_table (dest, GET_MODE (dest), insn,
1300e4b17023SJohn Marino 				     antic_p, avail_p, max_distance, table);
1301e4b17023SJohn Marino              }
1302e4b17023SJohn Marino       }
1303e4b17023SJohn Marino }
1304e4b17023SJohn Marino 
1305e4b17023SJohn Marino static void
hash_scan_clobber(rtx x ATTRIBUTE_UNUSED,rtx insn ATTRIBUTE_UNUSED,struct hash_table_d * table ATTRIBUTE_UNUSED)1306e4b17023SJohn Marino hash_scan_clobber (rtx x ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED,
1307e4b17023SJohn Marino 		   struct hash_table_d *table ATTRIBUTE_UNUSED)
1308e4b17023SJohn Marino {
1309e4b17023SJohn Marino   /* Currently nothing to do.  */
1310e4b17023SJohn Marino }
1311e4b17023SJohn Marino 
1312e4b17023SJohn Marino static void
hash_scan_call(rtx x ATTRIBUTE_UNUSED,rtx insn ATTRIBUTE_UNUSED,struct hash_table_d * table ATTRIBUTE_UNUSED)1313e4b17023SJohn Marino hash_scan_call (rtx x ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED,
1314e4b17023SJohn Marino 		struct hash_table_d *table ATTRIBUTE_UNUSED)
1315e4b17023SJohn Marino {
1316e4b17023SJohn Marino   /* Currently nothing to do.  */
1317e4b17023SJohn Marino }
1318e4b17023SJohn Marino 
1319e4b17023SJohn Marino /* Process INSN and add hash table entries as appropriate.  */
1320e4b17023SJohn Marino 
1321e4b17023SJohn Marino static void
hash_scan_insn(rtx insn,struct hash_table_d * table)1322e4b17023SJohn Marino hash_scan_insn (rtx insn, struct hash_table_d *table)
1323e4b17023SJohn Marino {
1324e4b17023SJohn Marino   rtx pat = PATTERN (insn);
1325e4b17023SJohn Marino   int i;
1326e4b17023SJohn Marino 
1327e4b17023SJohn Marino   /* Pick out the sets of INSN and for other forms of instructions record
1328e4b17023SJohn Marino      what's been modified.  */
1329e4b17023SJohn Marino 
1330e4b17023SJohn Marino   if (GET_CODE (pat) == SET)
1331e4b17023SJohn Marino     hash_scan_set (pat, insn, table);
1332e4b17023SJohn Marino 
1333e4b17023SJohn Marino   else if (GET_CODE (pat) == CLOBBER)
1334e4b17023SJohn Marino     hash_scan_clobber (pat, insn, table);
1335e4b17023SJohn Marino 
1336e4b17023SJohn Marino   else if (GET_CODE (pat) == CALL)
1337e4b17023SJohn Marino     hash_scan_call (pat, insn, table);
1338e4b17023SJohn Marino 
1339e4b17023SJohn Marino   else if (GET_CODE (pat) == PARALLEL)
1340e4b17023SJohn Marino     for (i = 0; i < XVECLEN (pat, 0); i++)
1341e4b17023SJohn Marino       {
1342e4b17023SJohn Marino 	rtx x = XVECEXP (pat, 0, i);
1343e4b17023SJohn Marino 
1344e4b17023SJohn Marino 	if (GET_CODE (x) == SET)
1345e4b17023SJohn Marino 	  hash_scan_set (x, insn, table);
1346e4b17023SJohn Marino 	else if (GET_CODE (x) == CLOBBER)
1347e4b17023SJohn Marino 	  hash_scan_clobber (x, insn, table);
1348e4b17023SJohn Marino 	else if (GET_CODE (x) == CALL)
1349e4b17023SJohn Marino 	  hash_scan_call (x, insn, table);
1350e4b17023SJohn Marino       }
1351e4b17023SJohn Marino }
1352e4b17023SJohn Marino 
1353e4b17023SJohn Marino /* Dump the hash table TABLE to file FILE under the name NAME.  */
1354e4b17023SJohn Marino 
1355e4b17023SJohn Marino static void
dump_hash_table(FILE * file,const char * name,struct hash_table_d * table)1356e4b17023SJohn Marino dump_hash_table (FILE *file, const char *name, struct hash_table_d *table)
1357e4b17023SJohn Marino {
1358e4b17023SJohn Marino   int i;
1359e4b17023SJohn Marino   /* Flattened out table, so it's printed in proper order.  */
1360e4b17023SJohn Marino   struct expr **flat_table;
1361e4b17023SJohn Marino   unsigned int *hash_val;
1362e4b17023SJohn Marino   struct expr *expr;
1363e4b17023SJohn Marino 
1364e4b17023SJohn Marino   flat_table = XCNEWVEC (struct expr *, table->n_elems);
1365e4b17023SJohn Marino   hash_val = XNEWVEC (unsigned int, table->n_elems);
1366e4b17023SJohn Marino 
1367e4b17023SJohn Marino   for (i = 0; i < (int) table->size; i++)
1368e4b17023SJohn Marino     for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
1369e4b17023SJohn Marino       {
1370e4b17023SJohn Marino 	flat_table[expr->bitmap_index] = expr;
1371e4b17023SJohn Marino 	hash_val[expr->bitmap_index] = i;
1372e4b17023SJohn Marino       }
1373e4b17023SJohn Marino 
1374e4b17023SJohn Marino   fprintf (file, "%s hash table (%d buckets, %d entries)\n",
1375e4b17023SJohn Marino 	   name, table->size, table->n_elems);
1376e4b17023SJohn Marino 
1377e4b17023SJohn Marino   for (i = 0; i < (int) table->n_elems; i++)
1378e4b17023SJohn Marino     if (flat_table[i] != 0)
1379e4b17023SJohn Marino       {
1380e4b17023SJohn Marino 	expr = flat_table[i];
1381e4b17023SJohn Marino 	fprintf (file, "Index %d (hash value %d; max distance %d)\n  ",
1382e4b17023SJohn Marino 		 expr->bitmap_index, hash_val[i], expr->max_distance);
1383e4b17023SJohn Marino 	print_rtl (file, expr->expr);
1384e4b17023SJohn Marino 	fprintf (file, "\n");
1385e4b17023SJohn Marino       }
1386e4b17023SJohn Marino 
1387e4b17023SJohn Marino   fprintf (file, "\n");
1388e4b17023SJohn Marino 
1389e4b17023SJohn Marino   free (flat_table);
1390e4b17023SJohn Marino   free (hash_val);
1391e4b17023SJohn Marino }
1392e4b17023SJohn Marino 
1393e4b17023SJohn Marino /* Record register first/last/block set information for REGNO in INSN.
1394e4b17023SJohn Marino 
1395e4b17023SJohn Marino    first_set records the first place in the block where the register
1396e4b17023SJohn Marino    is set and is used to compute "anticipatability".
1397e4b17023SJohn Marino 
1398e4b17023SJohn Marino    last_set records the last place in the block where the register
1399e4b17023SJohn Marino    is set and is used to compute "availability".
1400e4b17023SJohn Marino 
1401e4b17023SJohn Marino    last_bb records the block for which first_set and last_set are
1402e4b17023SJohn Marino    valid, as a quick test to invalidate them.  */
1403e4b17023SJohn Marino 
1404e4b17023SJohn Marino static void
record_last_reg_set_info(rtx insn,int regno)1405e4b17023SJohn Marino record_last_reg_set_info (rtx insn, int regno)
1406e4b17023SJohn Marino {
1407e4b17023SJohn Marino   struct reg_avail_info *info = &reg_avail_info[regno];
1408e4b17023SJohn Marino   int luid = DF_INSN_LUID (insn);
1409e4b17023SJohn Marino 
1410e4b17023SJohn Marino   info->last_set = luid;
1411e4b17023SJohn Marino   if (info->last_bb != current_bb)
1412e4b17023SJohn Marino     {
1413e4b17023SJohn Marino       info->last_bb = current_bb;
1414e4b17023SJohn Marino       info->first_set = luid;
1415e4b17023SJohn Marino     }
1416e4b17023SJohn Marino }
1417e4b17023SJohn Marino 
1418e4b17023SJohn Marino /* Record all of the canonicalized MEMs of record_last_mem_set_info's insn.
1419e4b17023SJohn Marino    Note we store a pair of elements in the list, so they have to be
1420e4b17023SJohn Marino    taken off pairwise.  */
1421e4b17023SJohn Marino 
1422e4b17023SJohn Marino static void
canon_list_insert(rtx dest ATTRIBUTE_UNUSED,const_rtx x ATTRIBUTE_UNUSED,void * v_insn)1423e4b17023SJohn Marino canon_list_insert (rtx dest ATTRIBUTE_UNUSED, const_rtx x ATTRIBUTE_UNUSED,
1424e4b17023SJohn Marino 		   void * v_insn)
1425e4b17023SJohn Marino {
1426e4b17023SJohn Marino   rtx dest_addr, insn;
1427e4b17023SJohn Marino   int bb;
1428e4b17023SJohn Marino   modify_pair *pair;
1429e4b17023SJohn Marino 
1430e4b17023SJohn Marino   while (GET_CODE (dest) == SUBREG
1431e4b17023SJohn Marino       || GET_CODE (dest) == ZERO_EXTRACT
1432e4b17023SJohn Marino       || GET_CODE (dest) == STRICT_LOW_PART)
1433e4b17023SJohn Marino     dest = XEXP (dest, 0);
1434e4b17023SJohn Marino 
1435e4b17023SJohn Marino   /* If DEST is not a MEM, then it will not conflict with a load.  Note
1436e4b17023SJohn Marino      that function calls are assumed to clobber memory, but are handled
1437e4b17023SJohn Marino      elsewhere.  */
1438e4b17023SJohn Marino 
1439e4b17023SJohn Marino   if (! MEM_P (dest))
1440e4b17023SJohn Marino     return;
1441e4b17023SJohn Marino 
1442e4b17023SJohn Marino   dest_addr = get_addr (XEXP (dest, 0));
1443e4b17023SJohn Marino   dest_addr = canon_rtx (dest_addr);
1444e4b17023SJohn Marino   insn = (rtx) v_insn;
1445e4b17023SJohn Marino   bb = BLOCK_FOR_INSN (insn)->index;
1446e4b17023SJohn Marino 
1447e4b17023SJohn Marino   pair = VEC_safe_push (modify_pair, heap, canon_modify_mem_list[bb], NULL);
1448e4b17023SJohn Marino   pair->dest = dest;
1449e4b17023SJohn Marino   pair->dest_addr = dest_addr;
1450e4b17023SJohn Marino }
1451e4b17023SJohn Marino 
1452e4b17023SJohn Marino /* Record memory modification information for INSN.  We do not actually care
1453e4b17023SJohn Marino    about the memory location(s) that are set, or even how they are set (consider
1454e4b17023SJohn Marino    a CALL_INSN).  We merely need to record which insns modify memory.  */
1455e4b17023SJohn Marino 
1456e4b17023SJohn Marino static void
record_last_mem_set_info(rtx insn)1457e4b17023SJohn Marino record_last_mem_set_info (rtx insn)
1458e4b17023SJohn Marino {
1459e4b17023SJohn Marino   int bb = BLOCK_FOR_INSN (insn)->index;
1460e4b17023SJohn Marino 
1461e4b17023SJohn Marino   /* load_killed_in_block_p will handle the case of calls clobbering
1462e4b17023SJohn Marino      everything.  */
1463e4b17023SJohn Marino   VEC_safe_push (rtx, heap, modify_mem_list[bb], insn);
1464e4b17023SJohn Marino   bitmap_set_bit (modify_mem_list_set, bb);
1465e4b17023SJohn Marino 
1466e4b17023SJohn Marino   if (CALL_P (insn))
1467e4b17023SJohn Marino     bitmap_set_bit (blocks_with_calls, bb);
1468e4b17023SJohn Marino   else
1469e4b17023SJohn Marino     note_stores (PATTERN (insn), canon_list_insert, (void*) insn);
1470e4b17023SJohn Marino }
1471e4b17023SJohn Marino 
1472e4b17023SJohn Marino /* Called from compute_hash_table via note_stores to handle one
1473e4b17023SJohn Marino    SET or CLOBBER in an insn.  DATA is really the instruction in which
1474e4b17023SJohn Marino    the SET is taking place.  */
1475e4b17023SJohn Marino 
1476e4b17023SJohn Marino static void
record_last_set_info(rtx dest,const_rtx setter ATTRIBUTE_UNUSED,void * data)1477e4b17023SJohn Marino record_last_set_info (rtx dest, const_rtx setter ATTRIBUTE_UNUSED, void *data)
1478e4b17023SJohn Marino {
1479e4b17023SJohn Marino   rtx last_set_insn = (rtx) data;
1480e4b17023SJohn Marino 
1481e4b17023SJohn Marino   if (GET_CODE (dest) == SUBREG)
1482e4b17023SJohn Marino     dest = SUBREG_REG (dest);
1483e4b17023SJohn Marino 
1484e4b17023SJohn Marino   if (REG_P (dest))
1485e4b17023SJohn Marino     record_last_reg_set_info (last_set_insn, REGNO (dest));
1486e4b17023SJohn Marino   else if (MEM_P (dest)
1487e4b17023SJohn Marino 	   /* Ignore pushes, they clobber nothing.  */
1488e4b17023SJohn Marino 	   && ! push_operand (dest, GET_MODE (dest)))
1489e4b17023SJohn Marino     record_last_mem_set_info (last_set_insn);
1490e4b17023SJohn Marino }
1491e4b17023SJohn Marino 
1492e4b17023SJohn Marino /* Top level function to create an expression hash table.
1493e4b17023SJohn Marino 
1494e4b17023SJohn Marino    Expression entries are placed in the hash table if
1495e4b17023SJohn Marino    - they are of the form (set (pseudo-reg) src),
1496e4b17023SJohn Marino    - src is something we want to perform GCSE on,
1497e4b17023SJohn Marino    - none of the operands are subsequently modified in the block
1498e4b17023SJohn Marino 
1499e4b17023SJohn Marino    Currently src must be a pseudo-reg or a const_int.
1500e4b17023SJohn Marino 
1501e4b17023SJohn Marino    TABLE is the table computed.  */
1502e4b17023SJohn Marino 
1503e4b17023SJohn Marino static void
compute_hash_table_work(struct hash_table_d * table)1504e4b17023SJohn Marino compute_hash_table_work (struct hash_table_d *table)
1505e4b17023SJohn Marino {
1506e4b17023SJohn Marino   int i;
1507e4b17023SJohn Marino 
1508e4b17023SJohn Marino   /* re-Cache any INSN_LIST nodes we have allocated.  */
1509e4b17023SJohn Marino   clear_modify_mem_tables ();
1510e4b17023SJohn Marino   /* Some working arrays used to track first and last set in each block.  */
1511e4b17023SJohn Marino   reg_avail_info = GNEWVEC (struct reg_avail_info, max_reg_num ());
1512e4b17023SJohn Marino 
1513e4b17023SJohn Marino   for (i = 0; i < max_reg_num (); ++i)
1514e4b17023SJohn Marino     reg_avail_info[i].last_bb = NULL;
1515e4b17023SJohn Marino 
1516e4b17023SJohn Marino   FOR_EACH_BB (current_bb)
1517e4b17023SJohn Marino     {
1518e4b17023SJohn Marino       rtx insn;
1519e4b17023SJohn Marino       unsigned int regno;
1520e4b17023SJohn Marino 
1521e4b17023SJohn Marino       /* First pass over the instructions records information used to
1522e4b17023SJohn Marino 	 determine when registers and memory are first and last set.  */
1523e4b17023SJohn Marino       FOR_BB_INSNS (current_bb, insn)
1524e4b17023SJohn Marino 	{
1525e4b17023SJohn Marino 	  if (!NONDEBUG_INSN_P (insn))
1526e4b17023SJohn Marino 	    continue;
1527e4b17023SJohn Marino 
1528e4b17023SJohn Marino 	  if (CALL_P (insn))
1529e4b17023SJohn Marino 	    {
1530e4b17023SJohn Marino 	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1531e4b17023SJohn Marino 		if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
1532e4b17023SJohn Marino 		  record_last_reg_set_info (insn, regno);
1533e4b17023SJohn Marino 
1534e4b17023SJohn Marino 	      if (! RTL_CONST_OR_PURE_CALL_P (insn))
1535e4b17023SJohn Marino 		record_last_mem_set_info (insn);
1536e4b17023SJohn Marino 	    }
1537e4b17023SJohn Marino 
1538e4b17023SJohn Marino 	  note_stores (PATTERN (insn), record_last_set_info, insn);
1539e4b17023SJohn Marino 	}
1540e4b17023SJohn Marino 
1541e4b17023SJohn Marino       /* The next pass builds the hash table.  */
1542e4b17023SJohn Marino       FOR_BB_INSNS (current_bb, insn)
1543e4b17023SJohn Marino 	if (NONDEBUG_INSN_P (insn))
1544e4b17023SJohn Marino 	  hash_scan_insn (insn, table);
1545e4b17023SJohn Marino     }
1546e4b17023SJohn Marino 
1547e4b17023SJohn Marino   free (reg_avail_info);
1548e4b17023SJohn Marino   reg_avail_info = NULL;
1549e4b17023SJohn Marino }
1550e4b17023SJohn Marino 
1551e4b17023SJohn Marino /* Allocate space for the set/expr hash TABLE.
1552e4b17023SJohn Marino    It is used to determine the number of buckets to use.  */
1553e4b17023SJohn Marino 
1554e4b17023SJohn Marino static void
alloc_hash_table(struct hash_table_d * table)1555e4b17023SJohn Marino alloc_hash_table (struct hash_table_d *table)
1556e4b17023SJohn Marino {
1557e4b17023SJohn Marino   int n;
1558e4b17023SJohn Marino 
1559e4b17023SJohn Marino   n = get_max_insn_count ();
1560e4b17023SJohn Marino 
1561e4b17023SJohn Marino   table->size = n / 4;
1562e4b17023SJohn Marino   if (table->size < 11)
1563e4b17023SJohn Marino     table->size = 11;
1564e4b17023SJohn Marino 
1565e4b17023SJohn Marino   /* Attempt to maintain efficient use of hash table.
1566e4b17023SJohn Marino      Making it an odd number is simplest for now.
1567e4b17023SJohn Marino      ??? Later take some measurements.  */
1568e4b17023SJohn Marino   table->size |= 1;
1569e4b17023SJohn Marino   n = table->size * sizeof (struct expr *);
1570e4b17023SJohn Marino   table->table = GNEWVAR (struct expr *, n);
1571e4b17023SJohn Marino }
1572e4b17023SJohn Marino 
1573e4b17023SJohn Marino /* Free things allocated by alloc_hash_table.  */
1574e4b17023SJohn Marino 
1575e4b17023SJohn Marino static void
free_hash_table(struct hash_table_d * table)1576e4b17023SJohn Marino free_hash_table (struct hash_table_d *table)
1577e4b17023SJohn Marino {
1578e4b17023SJohn Marino   free (table->table);
1579e4b17023SJohn Marino }
1580e4b17023SJohn Marino 
1581e4b17023SJohn Marino /* Compute the expression hash table TABLE.  */
1582e4b17023SJohn Marino 
1583e4b17023SJohn Marino static void
compute_hash_table(struct hash_table_d * table)1584e4b17023SJohn Marino compute_hash_table (struct hash_table_d *table)
1585e4b17023SJohn Marino {
1586e4b17023SJohn Marino   /* Initialize count of number of entries in hash table.  */
1587e4b17023SJohn Marino   table->n_elems = 0;
1588e4b17023SJohn Marino   memset (table->table, 0, table->size * sizeof (struct expr *));
1589e4b17023SJohn Marino 
1590e4b17023SJohn Marino   compute_hash_table_work (table);
1591e4b17023SJohn Marino }
1592e4b17023SJohn Marino 
1593e4b17023SJohn Marino /* Expression tracking support.  */
1594e4b17023SJohn Marino 
1595e4b17023SJohn Marino /* Clear canon_modify_mem_list and modify_mem_list tables.  */
1596e4b17023SJohn Marino static void
clear_modify_mem_tables(void)1597e4b17023SJohn Marino clear_modify_mem_tables (void)
1598e4b17023SJohn Marino {
1599e4b17023SJohn Marino   unsigned i;
1600e4b17023SJohn Marino   bitmap_iterator bi;
1601e4b17023SJohn Marino 
1602e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (modify_mem_list_set, 0, i, bi)
1603e4b17023SJohn Marino     {
1604e4b17023SJohn Marino       VEC_free (rtx, heap, modify_mem_list[i]);
1605e4b17023SJohn Marino       VEC_free (modify_pair, heap, canon_modify_mem_list[i]);
1606e4b17023SJohn Marino     }
1607e4b17023SJohn Marino   bitmap_clear (modify_mem_list_set);
1608e4b17023SJohn Marino   bitmap_clear (blocks_with_calls);
1609e4b17023SJohn Marino }
1610e4b17023SJohn Marino 
1611e4b17023SJohn Marino /* Release memory used by modify_mem_list_set.  */
1612e4b17023SJohn Marino 
1613e4b17023SJohn Marino static void
free_modify_mem_tables(void)1614e4b17023SJohn Marino free_modify_mem_tables (void)
1615e4b17023SJohn Marino {
1616e4b17023SJohn Marino   clear_modify_mem_tables ();
1617e4b17023SJohn Marino   free (modify_mem_list);
1618e4b17023SJohn Marino   free (canon_modify_mem_list);
1619e4b17023SJohn Marino   modify_mem_list = 0;
1620e4b17023SJohn Marino   canon_modify_mem_list = 0;
1621e4b17023SJohn Marino }
1622e4b17023SJohn Marino 
1623e4b17023SJohn Marino /* For each block, compute whether X is transparent.  X is either an
1624e4b17023SJohn Marino    expression or an assignment [though we don't care which, for this context
1625e4b17023SJohn Marino    an assignment is treated as an expression].  For each block where an
1626e4b17023SJohn Marino    element of X is modified, reset the INDX bit in BMAP.  */
1627e4b17023SJohn Marino 
1628e4b17023SJohn Marino static void
compute_transp(const_rtx x,int indx,sbitmap * bmap)1629e4b17023SJohn Marino compute_transp (const_rtx x, int indx, sbitmap *bmap)
1630e4b17023SJohn Marino {
1631e4b17023SJohn Marino   int i, j;
1632e4b17023SJohn Marino   enum rtx_code code;
1633e4b17023SJohn Marino   const char *fmt;
1634e4b17023SJohn Marino 
1635e4b17023SJohn Marino   /* repeat is used to turn tail-recursion into iteration since GCC
1636e4b17023SJohn Marino      can't do it when there's no return value.  */
1637e4b17023SJohn Marino  repeat:
1638e4b17023SJohn Marino 
1639e4b17023SJohn Marino   if (x == 0)
1640e4b17023SJohn Marino     return;
1641e4b17023SJohn Marino 
1642e4b17023SJohn Marino   code = GET_CODE (x);
1643e4b17023SJohn Marino   switch (code)
1644e4b17023SJohn Marino     {
1645e4b17023SJohn Marino     case REG:
1646e4b17023SJohn Marino 	{
1647e4b17023SJohn Marino 	  df_ref def;
1648e4b17023SJohn Marino 	  for (def = DF_REG_DEF_CHAIN (REGNO (x));
1649e4b17023SJohn Marino 	       def;
1650e4b17023SJohn Marino 	       def = DF_REF_NEXT_REG (def))
1651e4b17023SJohn Marino 	    RESET_BIT (bmap[DF_REF_BB (def)->index], indx);
1652e4b17023SJohn Marino 	}
1653e4b17023SJohn Marino 
1654e4b17023SJohn Marino       return;
1655e4b17023SJohn Marino 
1656e4b17023SJohn Marino     case MEM:
1657e4b17023SJohn Marino       if (! MEM_READONLY_P (x))
1658e4b17023SJohn Marino 	{
1659e4b17023SJohn Marino 	  bitmap_iterator bi;
1660e4b17023SJohn Marino 	  unsigned bb_index;
1661*5ce9237cSJohn Marino 	  rtx x_addr;
1662*5ce9237cSJohn Marino 
1663*5ce9237cSJohn Marino 	  x_addr = get_addr (XEXP (x, 0));
1664*5ce9237cSJohn Marino 	  x_addr = canon_rtx (x_addr);
1665e4b17023SJohn Marino 
1666e4b17023SJohn Marino 	  /* First handle all the blocks with calls.  We don't need to
1667e4b17023SJohn Marino 	     do any list walking for them.  */
1668e4b17023SJohn Marino 	  EXECUTE_IF_SET_IN_BITMAP (blocks_with_calls, 0, bb_index, bi)
1669e4b17023SJohn Marino 	    {
1670e4b17023SJohn Marino 	      RESET_BIT (bmap[bb_index], indx);
1671e4b17023SJohn Marino 	    }
1672e4b17023SJohn Marino 
1673e4b17023SJohn Marino 	  /* Now iterate over the blocks which have memory modifications
1674e4b17023SJohn Marino 	     but which do not have any calls.  */
1675e4b17023SJohn Marino 	  EXECUTE_IF_AND_COMPL_IN_BITMAP (modify_mem_list_set,
1676e4b17023SJohn Marino 					  blocks_with_calls,
1677e4b17023SJohn Marino 					  0, bb_index, bi)
1678e4b17023SJohn Marino 	    {
1679e4b17023SJohn Marino 	      VEC (modify_pair,heap) *list
1680e4b17023SJohn Marino 		= canon_modify_mem_list[bb_index];
1681e4b17023SJohn Marino 	      modify_pair *pair;
1682e4b17023SJohn Marino 	      unsigned ix;
1683e4b17023SJohn Marino 
1684e4b17023SJohn Marino 	      FOR_EACH_VEC_ELT_REVERSE (modify_pair, list, ix, pair)
1685e4b17023SJohn Marino 		{
1686e4b17023SJohn Marino 		  rtx dest = pair->dest;
1687e4b17023SJohn Marino 		  rtx dest_addr = pair->dest_addr;
1688e4b17023SJohn Marino 
1689e4b17023SJohn Marino 		  if (canon_true_dependence (dest, GET_MODE (dest),
1690*5ce9237cSJohn Marino 					     dest_addr, x, x_addr))
1691e4b17023SJohn Marino 		    RESET_BIT (bmap[bb_index], indx);
1692e4b17023SJohn Marino 	        }
1693e4b17023SJohn Marino 	    }
1694e4b17023SJohn Marino 	}
1695e4b17023SJohn Marino 
1696e4b17023SJohn Marino       x = XEXP (x, 0);
1697e4b17023SJohn Marino       goto repeat;
1698e4b17023SJohn Marino 
1699e4b17023SJohn Marino     case PC:
1700e4b17023SJohn Marino     case CC0: /*FIXME*/
1701e4b17023SJohn Marino     case CONST:
1702e4b17023SJohn Marino     case CONST_INT:
1703e4b17023SJohn Marino     case CONST_DOUBLE:
1704e4b17023SJohn Marino     case CONST_FIXED:
1705e4b17023SJohn Marino     case CONST_VECTOR:
1706e4b17023SJohn Marino     case SYMBOL_REF:
1707e4b17023SJohn Marino     case LABEL_REF:
1708e4b17023SJohn Marino     case ADDR_VEC:
1709e4b17023SJohn Marino     case ADDR_DIFF_VEC:
1710e4b17023SJohn Marino       return;
1711e4b17023SJohn Marino 
1712e4b17023SJohn Marino     default:
1713e4b17023SJohn Marino       break;
1714e4b17023SJohn Marino     }
1715e4b17023SJohn Marino 
1716e4b17023SJohn Marino   for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
1717e4b17023SJohn Marino     {
1718e4b17023SJohn Marino       if (fmt[i] == 'e')
1719e4b17023SJohn Marino 	{
1720e4b17023SJohn Marino 	  /* If we are about to do the last recursive call
1721e4b17023SJohn Marino 	     needed at this level, change it into iteration.
1722e4b17023SJohn Marino 	     This function is called enough to be worth it.  */
1723e4b17023SJohn Marino 	  if (i == 0)
1724e4b17023SJohn Marino 	    {
1725e4b17023SJohn Marino 	      x = XEXP (x, i);
1726e4b17023SJohn Marino 	      goto repeat;
1727e4b17023SJohn Marino 	    }
1728e4b17023SJohn Marino 
1729e4b17023SJohn Marino 	  compute_transp (XEXP (x, i), indx, bmap);
1730e4b17023SJohn Marino 	}
1731e4b17023SJohn Marino       else if (fmt[i] == 'E')
1732e4b17023SJohn Marino 	for (j = 0; j < XVECLEN (x, i); j++)
1733e4b17023SJohn Marino 	  compute_transp (XVECEXP (x, i, j), indx, bmap);
1734e4b17023SJohn Marino     }
1735e4b17023SJohn Marino }
1736e4b17023SJohn Marino 
1737e4b17023SJohn Marino /* Compute PRE+LCM working variables.  */
1738e4b17023SJohn Marino 
1739e4b17023SJohn Marino /* Local properties of expressions.  */
1740e4b17023SJohn Marino 
1741e4b17023SJohn Marino /* Nonzero for expressions that are transparent in the block.  */
1742e4b17023SJohn Marino static sbitmap *transp;
1743e4b17023SJohn Marino 
1744e4b17023SJohn Marino /* Nonzero for expressions that are computed (available) in the block.  */
1745e4b17023SJohn Marino static sbitmap *comp;
1746e4b17023SJohn Marino 
1747e4b17023SJohn Marino /* Nonzero for expressions that are locally anticipatable in the block.  */
1748e4b17023SJohn Marino static sbitmap *antloc;
1749e4b17023SJohn Marino 
1750e4b17023SJohn Marino /* Nonzero for expressions where this block is an optimal computation
1751e4b17023SJohn Marino    point.  */
1752e4b17023SJohn Marino static sbitmap *pre_optimal;
1753e4b17023SJohn Marino 
1754e4b17023SJohn Marino /* Nonzero for expressions which are redundant in a particular block.  */
1755e4b17023SJohn Marino static sbitmap *pre_redundant;
1756e4b17023SJohn Marino 
1757e4b17023SJohn Marino /* Nonzero for expressions which should be inserted on a specific edge.  */
1758e4b17023SJohn Marino static sbitmap *pre_insert_map;
1759e4b17023SJohn Marino 
1760e4b17023SJohn Marino /* Nonzero for expressions which should be deleted in a specific block.  */
1761e4b17023SJohn Marino static sbitmap *pre_delete_map;
1762e4b17023SJohn Marino 
1763e4b17023SJohn Marino /* Allocate vars used for PRE analysis.  */
1764e4b17023SJohn Marino 
1765e4b17023SJohn Marino static void
alloc_pre_mem(int n_blocks,int n_exprs)1766e4b17023SJohn Marino alloc_pre_mem (int n_blocks, int n_exprs)
1767e4b17023SJohn Marino {
1768e4b17023SJohn Marino   transp = sbitmap_vector_alloc (n_blocks, n_exprs);
1769e4b17023SJohn Marino   comp = sbitmap_vector_alloc (n_blocks, n_exprs);
1770e4b17023SJohn Marino   antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
1771e4b17023SJohn Marino 
1772e4b17023SJohn Marino   pre_optimal = NULL;
1773e4b17023SJohn Marino   pre_redundant = NULL;
1774e4b17023SJohn Marino   pre_insert_map = NULL;
1775e4b17023SJohn Marino   pre_delete_map = NULL;
1776e4b17023SJohn Marino   ae_kill = sbitmap_vector_alloc (n_blocks, n_exprs);
1777e4b17023SJohn Marino 
1778e4b17023SJohn Marino   /* pre_insert and pre_delete are allocated later.  */
1779e4b17023SJohn Marino }
1780e4b17023SJohn Marino 
1781e4b17023SJohn Marino /* Free vars used for PRE analysis.  */
1782e4b17023SJohn Marino 
1783e4b17023SJohn Marino static void
free_pre_mem(void)1784e4b17023SJohn Marino free_pre_mem (void)
1785e4b17023SJohn Marino {
1786e4b17023SJohn Marino   sbitmap_vector_free (transp);
1787e4b17023SJohn Marino   sbitmap_vector_free (comp);
1788e4b17023SJohn Marino 
1789e4b17023SJohn Marino   /* ANTLOC and AE_KILL are freed just after pre_lcm finishes.  */
1790e4b17023SJohn Marino 
1791e4b17023SJohn Marino   if (pre_optimal)
1792e4b17023SJohn Marino     sbitmap_vector_free (pre_optimal);
1793e4b17023SJohn Marino   if (pre_redundant)
1794e4b17023SJohn Marino     sbitmap_vector_free (pre_redundant);
1795e4b17023SJohn Marino   if (pre_insert_map)
1796e4b17023SJohn Marino     sbitmap_vector_free (pre_insert_map);
1797e4b17023SJohn Marino   if (pre_delete_map)
1798e4b17023SJohn Marino     sbitmap_vector_free (pre_delete_map);
1799e4b17023SJohn Marino 
1800e4b17023SJohn Marino   transp = comp = NULL;
1801e4b17023SJohn Marino   pre_optimal = pre_redundant = pre_insert_map = pre_delete_map = NULL;
1802e4b17023SJohn Marino }
1803e4b17023SJohn Marino 
1804e4b17023SJohn Marino /* Remove certain expressions from anticipatable and transparent
1805e4b17023SJohn Marino    sets of basic blocks that have incoming abnormal edge.
1806e4b17023SJohn Marino    For PRE remove potentially trapping expressions to avoid placing
1807e4b17023SJohn Marino    them on abnormal edges.  For hoisting remove memory references that
1808e4b17023SJohn Marino    can be clobbered by calls.  */
1809e4b17023SJohn Marino 
1810e4b17023SJohn Marino static void
prune_expressions(bool pre_p)1811e4b17023SJohn Marino prune_expressions (bool pre_p)
1812e4b17023SJohn Marino {
1813e4b17023SJohn Marino   sbitmap prune_exprs;
1814e4b17023SJohn Marino   struct expr *expr;
1815e4b17023SJohn Marino   unsigned int ui;
1816e4b17023SJohn Marino   basic_block bb;
1817e4b17023SJohn Marino 
1818e4b17023SJohn Marino   prune_exprs = sbitmap_alloc (expr_hash_table.n_elems);
1819e4b17023SJohn Marino   sbitmap_zero (prune_exprs);
1820e4b17023SJohn Marino   for (ui = 0; ui < expr_hash_table.size; ui++)
1821e4b17023SJohn Marino     {
1822e4b17023SJohn Marino       for (expr = expr_hash_table.table[ui]; expr; expr = expr->next_same_hash)
1823e4b17023SJohn Marino 	{
1824e4b17023SJohn Marino 	  /* Note potentially trapping expressions.  */
1825e4b17023SJohn Marino 	  if (may_trap_p (expr->expr))
1826e4b17023SJohn Marino 	    {
1827e4b17023SJohn Marino 	      SET_BIT (prune_exprs, expr->bitmap_index);
1828e4b17023SJohn Marino 	      continue;
1829e4b17023SJohn Marino 	    }
1830e4b17023SJohn Marino 
1831e4b17023SJohn Marino 	  if (!pre_p && MEM_P (expr->expr))
1832e4b17023SJohn Marino 	    /* Note memory references that can be clobbered by a call.
1833e4b17023SJohn Marino 	       We do not split abnormal edges in hoisting, so would
1834e4b17023SJohn Marino 	       a memory reference get hoisted along an abnormal edge,
1835e4b17023SJohn Marino 	       it would be placed /before/ the call.  Therefore, only
1836e4b17023SJohn Marino 	       constant memory references can be hoisted along abnormal
1837e4b17023SJohn Marino 	       edges.  */
1838e4b17023SJohn Marino 	    {
1839e4b17023SJohn Marino 	      if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF
1840e4b17023SJohn Marino 		  && CONSTANT_POOL_ADDRESS_P (XEXP (expr->expr, 0)))
1841e4b17023SJohn Marino 		continue;
1842e4b17023SJohn Marino 
1843e4b17023SJohn Marino 	      if (MEM_READONLY_P (expr->expr)
1844e4b17023SJohn Marino 		  && !MEM_VOLATILE_P (expr->expr)
1845e4b17023SJohn Marino 		  && MEM_NOTRAP_P (expr->expr))
1846e4b17023SJohn Marino 		/* Constant memory reference, e.g., a PIC address.  */
1847e4b17023SJohn Marino 		continue;
1848e4b17023SJohn Marino 
1849e4b17023SJohn Marino 	      /* ??? Optimally, we would use interprocedural alias
1850e4b17023SJohn Marino 		 analysis to determine if this mem is actually killed
1851e4b17023SJohn Marino 		 by this call.  */
1852e4b17023SJohn Marino 
1853e4b17023SJohn Marino 	      SET_BIT (prune_exprs, expr->bitmap_index);
1854e4b17023SJohn Marino 	    }
1855e4b17023SJohn Marino 	}
1856e4b17023SJohn Marino     }
1857e4b17023SJohn Marino 
1858e4b17023SJohn Marino   FOR_EACH_BB (bb)
1859e4b17023SJohn Marino     {
1860e4b17023SJohn Marino       edge e;
1861e4b17023SJohn Marino       edge_iterator ei;
1862e4b17023SJohn Marino 
1863e4b17023SJohn Marino       /* If the current block is the destination of an abnormal edge, we
1864e4b17023SJohn Marino 	 kill all trapping (for PRE) and memory (for hoist) expressions
1865e4b17023SJohn Marino 	 because we won't be able to properly place the instruction on
1866e4b17023SJohn Marino 	 the edge.  So make them neither anticipatable nor transparent.
1867e4b17023SJohn Marino 	 This is fairly conservative.
1868e4b17023SJohn Marino 
1869e4b17023SJohn Marino 	 ??? For hoisting it may be necessary to check for set-and-jump
1870e4b17023SJohn Marino 	 instructions here, not just for abnormal edges.  The general problem
1871e4b17023SJohn Marino 	 is that when an expression cannot not be placed right at the end of
1872e4b17023SJohn Marino 	 a basic block we should account for any side-effects of a subsequent
1873e4b17023SJohn Marino 	 jump instructions that could clobber the expression.  It would
1874e4b17023SJohn Marino 	 be best to implement this check along the lines of
1875e4b17023SJohn Marino 	 hoist_expr_reaches_here_p where the target block is already known
1876e4b17023SJohn Marino 	 and, hence, there's no need to conservatively prune expressions on
1877e4b17023SJohn Marino 	 "intermediate" set-and-jump instructions.  */
1878e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bb->preds)
1879e4b17023SJohn Marino 	if ((e->flags & EDGE_ABNORMAL)
1880e4b17023SJohn Marino 	    && (pre_p || CALL_P (BB_END (e->src))))
1881e4b17023SJohn Marino 	  {
1882e4b17023SJohn Marino 	    sbitmap_difference (antloc[bb->index],
1883e4b17023SJohn Marino 				antloc[bb->index], prune_exprs);
1884e4b17023SJohn Marino 	    sbitmap_difference (transp[bb->index],
1885e4b17023SJohn Marino 				transp[bb->index], prune_exprs);
1886e4b17023SJohn Marino 	    break;
1887e4b17023SJohn Marino 	  }
1888e4b17023SJohn Marino     }
1889e4b17023SJohn Marino 
1890e4b17023SJohn Marino   sbitmap_free (prune_exprs);
1891e4b17023SJohn Marino }
1892e4b17023SJohn Marino 
1893e4b17023SJohn Marino /* It may be necessary to insert a large number of insns on edges to
1894e4b17023SJohn Marino    make the existing occurrences of expressions fully redundant.  This
1895e4b17023SJohn Marino    routine examines the set of insertions and deletions and if the ratio
1896e4b17023SJohn Marino    of insertions to deletions is too high for a particular expression, then
1897e4b17023SJohn Marino    the expression is removed from the insertion/deletion sets.
1898e4b17023SJohn Marino 
1899e4b17023SJohn Marino    N_ELEMS is the number of elements in the hash table.  */
1900e4b17023SJohn Marino 
1901e4b17023SJohn Marino static void
prune_insertions_deletions(int n_elems)1902e4b17023SJohn Marino prune_insertions_deletions (int n_elems)
1903e4b17023SJohn Marino {
1904e4b17023SJohn Marino   sbitmap_iterator sbi;
1905e4b17023SJohn Marino   sbitmap prune_exprs;
1906e4b17023SJohn Marino 
1907e4b17023SJohn Marino   /* We always use I to iterate over blocks/edges and J to iterate over
1908e4b17023SJohn Marino      expressions.  */
1909e4b17023SJohn Marino   unsigned int i, j;
1910e4b17023SJohn Marino 
1911e4b17023SJohn Marino   /* Counts for the number of times an expression needs to be inserted and
1912e4b17023SJohn Marino      number of times an expression can be removed as a result.  */
1913e4b17023SJohn Marino   int *insertions = GCNEWVEC (int, n_elems);
1914e4b17023SJohn Marino   int *deletions = GCNEWVEC (int, n_elems);
1915e4b17023SJohn Marino 
1916e4b17023SJohn Marino   /* Set of expressions which require too many insertions relative to
1917e4b17023SJohn Marino      the number of deletions achieved.  We will prune these out of the
1918e4b17023SJohn Marino      insertion/deletion sets.  */
1919e4b17023SJohn Marino   prune_exprs = sbitmap_alloc (n_elems);
1920e4b17023SJohn Marino   sbitmap_zero (prune_exprs);
1921e4b17023SJohn Marino 
1922e4b17023SJohn Marino   /* Iterate over the edges counting the number of times each expression
1923e4b17023SJohn Marino      needs to be inserted.  */
1924e4b17023SJohn Marino   for (i = 0; i < (unsigned) n_edges; i++)
1925e4b17023SJohn Marino     {
1926e4b17023SJohn Marino       EXECUTE_IF_SET_IN_SBITMAP (pre_insert_map[i], 0, j, sbi)
1927e4b17023SJohn Marino 	insertions[j]++;
1928e4b17023SJohn Marino     }
1929e4b17023SJohn Marino 
1930e4b17023SJohn Marino   /* Similarly for deletions, but those occur in blocks rather than on
1931e4b17023SJohn Marino      edges.  */
1932e4b17023SJohn Marino   for (i = 0; i < (unsigned) last_basic_block; i++)
1933e4b17023SJohn Marino     {
1934e4b17023SJohn Marino       EXECUTE_IF_SET_IN_SBITMAP (pre_delete_map[i], 0, j, sbi)
1935e4b17023SJohn Marino 	deletions[j]++;
1936e4b17023SJohn Marino     }
1937e4b17023SJohn Marino 
1938e4b17023SJohn Marino   /* Now that we have accurate counts, iterate over the elements in the
1939e4b17023SJohn Marino      hash table and see if any need too many insertions relative to the
1940e4b17023SJohn Marino      number of evaluations that can be removed.  If so, mark them in
1941e4b17023SJohn Marino      PRUNE_EXPRS.  */
1942e4b17023SJohn Marino   for (j = 0; j < (unsigned) n_elems; j++)
1943e4b17023SJohn Marino     if (deletions[j]
1944e4b17023SJohn Marino 	&& ((unsigned) insertions[j] / deletions[j]) > MAX_GCSE_INSERTION_RATIO)
1945e4b17023SJohn Marino       SET_BIT (prune_exprs, j);
1946e4b17023SJohn Marino 
1947e4b17023SJohn Marino   /* Now prune PRE_INSERT_MAP and PRE_DELETE_MAP based on PRUNE_EXPRS.  */
1948e4b17023SJohn Marino   EXECUTE_IF_SET_IN_SBITMAP (prune_exprs, 0, j, sbi)
1949e4b17023SJohn Marino     {
1950e4b17023SJohn Marino       for (i = 0; i < (unsigned) n_edges; i++)
1951e4b17023SJohn Marino 	RESET_BIT (pre_insert_map[i], j);
1952e4b17023SJohn Marino 
1953e4b17023SJohn Marino       for (i = 0; i < (unsigned) last_basic_block; i++)
1954e4b17023SJohn Marino 	RESET_BIT (pre_delete_map[i], j);
1955e4b17023SJohn Marino     }
1956e4b17023SJohn Marino 
1957e4b17023SJohn Marino   sbitmap_free (prune_exprs);
1958e4b17023SJohn Marino   free (insertions);
1959e4b17023SJohn Marino   free (deletions);
1960e4b17023SJohn Marino }
1961e4b17023SJohn Marino 
1962e4b17023SJohn Marino /* Top level routine to do the dataflow analysis needed by PRE.  */
1963e4b17023SJohn Marino 
1964e4b17023SJohn Marino static struct edge_list *
compute_pre_data(void)1965e4b17023SJohn Marino compute_pre_data (void)
1966e4b17023SJohn Marino {
1967e4b17023SJohn Marino   struct edge_list *edge_list;
1968e4b17023SJohn Marino   basic_block bb;
1969e4b17023SJohn Marino 
1970e4b17023SJohn Marino   compute_local_properties (transp, comp, antloc, &expr_hash_table);
1971e4b17023SJohn Marino   prune_expressions (true);
1972e4b17023SJohn Marino   sbitmap_vector_zero (ae_kill, last_basic_block);
1973e4b17023SJohn Marino 
1974e4b17023SJohn Marino   /* Compute ae_kill for each basic block using:
1975e4b17023SJohn Marino 
1976e4b17023SJohn Marino      ~(TRANSP | COMP)
1977e4b17023SJohn Marino   */
1978e4b17023SJohn Marino 
1979e4b17023SJohn Marino   FOR_EACH_BB (bb)
1980e4b17023SJohn Marino     {
1981e4b17023SJohn Marino       sbitmap_a_or_b (ae_kill[bb->index], transp[bb->index], comp[bb->index]);
1982e4b17023SJohn Marino       sbitmap_not (ae_kill[bb->index], ae_kill[bb->index]);
1983e4b17023SJohn Marino     }
1984e4b17023SJohn Marino 
1985e4b17023SJohn Marino   edge_list = pre_edge_lcm (expr_hash_table.n_elems, transp, comp, antloc,
1986e4b17023SJohn Marino 			    ae_kill, &pre_insert_map, &pre_delete_map);
1987e4b17023SJohn Marino   sbitmap_vector_free (antloc);
1988e4b17023SJohn Marino   antloc = NULL;
1989e4b17023SJohn Marino   sbitmap_vector_free (ae_kill);
1990e4b17023SJohn Marino   ae_kill = NULL;
1991e4b17023SJohn Marino 
1992e4b17023SJohn Marino   prune_insertions_deletions (expr_hash_table.n_elems);
1993e4b17023SJohn Marino 
1994e4b17023SJohn Marino   return edge_list;
1995e4b17023SJohn Marino }
1996e4b17023SJohn Marino 
1997e4b17023SJohn Marino /* PRE utilities */
1998e4b17023SJohn Marino 
1999e4b17023SJohn Marino /* Return nonzero if an occurrence of expression EXPR in OCCR_BB would reach
2000e4b17023SJohn Marino    block BB.
2001e4b17023SJohn Marino 
2002e4b17023SJohn Marino    VISITED is a pointer to a working buffer for tracking which BB's have
2003e4b17023SJohn Marino    been visited.  It is NULL for the top-level call.
2004e4b17023SJohn Marino 
2005e4b17023SJohn Marino    We treat reaching expressions that go through blocks containing the same
2006e4b17023SJohn Marino    reaching expression as "not reaching".  E.g. if EXPR is generated in blocks
2007e4b17023SJohn Marino    2 and 3, INSN is in block 4, and 2->3->4, we treat the expression in block
2008e4b17023SJohn Marino    2 as not reaching.  The intent is to improve the probability of finding
2009e4b17023SJohn Marino    only one reaching expression and to reduce register lifetimes by picking
2010e4b17023SJohn Marino    the closest such expression.  */
2011e4b17023SJohn Marino 
2012e4b17023SJohn Marino static int
pre_expr_reaches_here_p_work(basic_block occr_bb,struct expr * expr,basic_block bb,char * visited)2013e4b17023SJohn Marino pre_expr_reaches_here_p_work (basic_block occr_bb, struct expr *expr,
2014e4b17023SJohn Marino 			      basic_block bb, char *visited)
2015e4b17023SJohn Marino {
2016e4b17023SJohn Marino   edge pred;
2017e4b17023SJohn Marino   edge_iterator ei;
2018e4b17023SJohn Marino 
2019e4b17023SJohn Marino   FOR_EACH_EDGE (pred, ei, bb->preds)
2020e4b17023SJohn Marino     {
2021e4b17023SJohn Marino       basic_block pred_bb = pred->src;
2022e4b17023SJohn Marino 
2023e4b17023SJohn Marino       if (pred->src == ENTRY_BLOCK_PTR
2024e4b17023SJohn Marino 	  /* Has predecessor has already been visited?  */
2025e4b17023SJohn Marino 	  || visited[pred_bb->index])
2026e4b17023SJohn Marino 	;/* Nothing to do.  */
2027e4b17023SJohn Marino 
2028e4b17023SJohn Marino       /* Does this predecessor generate this expression?  */
2029e4b17023SJohn Marino       else if (TEST_BIT (comp[pred_bb->index], expr->bitmap_index))
2030e4b17023SJohn Marino 	{
2031e4b17023SJohn Marino 	  /* Is this the occurrence we're looking for?
2032e4b17023SJohn Marino 	     Note that there's only one generating occurrence per block
2033e4b17023SJohn Marino 	     so we just need to check the block number.  */
2034e4b17023SJohn Marino 	  if (occr_bb == pred_bb)
2035e4b17023SJohn Marino 	    return 1;
2036e4b17023SJohn Marino 
2037e4b17023SJohn Marino 	  visited[pred_bb->index] = 1;
2038e4b17023SJohn Marino 	}
2039e4b17023SJohn Marino       /* Ignore this predecessor if it kills the expression.  */
2040e4b17023SJohn Marino       else if (! TEST_BIT (transp[pred_bb->index], expr->bitmap_index))
2041e4b17023SJohn Marino 	visited[pred_bb->index] = 1;
2042e4b17023SJohn Marino 
2043e4b17023SJohn Marino       /* Neither gen nor kill.  */
2044e4b17023SJohn Marino       else
2045e4b17023SJohn Marino 	{
2046e4b17023SJohn Marino 	  visited[pred_bb->index] = 1;
2047e4b17023SJohn Marino 	  if (pre_expr_reaches_here_p_work (occr_bb, expr, pred_bb, visited))
2048e4b17023SJohn Marino 	    return 1;
2049e4b17023SJohn Marino 	}
2050e4b17023SJohn Marino     }
2051e4b17023SJohn Marino 
2052e4b17023SJohn Marino   /* All paths have been checked.  */
2053e4b17023SJohn Marino   return 0;
2054e4b17023SJohn Marino }
2055e4b17023SJohn Marino 
2056e4b17023SJohn Marino /* The wrapper for pre_expr_reaches_here_work that ensures that any
2057e4b17023SJohn Marino    memory allocated for that function is returned.  */
2058e4b17023SJohn Marino 
2059e4b17023SJohn Marino static int
pre_expr_reaches_here_p(basic_block occr_bb,struct expr * expr,basic_block bb)2060e4b17023SJohn Marino pre_expr_reaches_here_p (basic_block occr_bb, struct expr *expr, basic_block bb)
2061e4b17023SJohn Marino {
2062e4b17023SJohn Marino   int rval;
2063e4b17023SJohn Marino   char *visited = XCNEWVEC (char, last_basic_block);
2064e4b17023SJohn Marino 
2065e4b17023SJohn Marino   rval = pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited);
2066e4b17023SJohn Marino 
2067e4b17023SJohn Marino   free (visited);
2068e4b17023SJohn Marino   return rval;
2069e4b17023SJohn Marino }
2070e4b17023SJohn Marino 
2071e4b17023SJohn Marino /* Generate RTL to copy an EXPR to its `reaching_reg' and return it.  */
2072e4b17023SJohn Marino 
2073e4b17023SJohn Marino static rtx
process_insert_insn(struct expr * expr)2074e4b17023SJohn Marino process_insert_insn (struct expr *expr)
2075e4b17023SJohn Marino {
2076e4b17023SJohn Marino   rtx reg = expr->reaching_reg;
2077e4b17023SJohn Marino   /* Copy the expression to make sure we don't have any sharing issues.  */
2078e4b17023SJohn Marino   rtx exp = copy_rtx (expr->expr);
2079e4b17023SJohn Marino   rtx pat;
2080e4b17023SJohn Marino 
2081e4b17023SJohn Marino   start_sequence ();
2082e4b17023SJohn Marino 
2083e4b17023SJohn Marino   /* If the expression is something that's an operand, like a constant,
2084e4b17023SJohn Marino      just copy it to a register.  */
2085e4b17023SJohn Marino   if (general_operand (exp, GET_MODE (reg)))
2086e4b17023SJohn Marino     emit_move_insn (reg, exp);
2087e4b17023SJohn Marino 
2088e4b17023SJohn Marino   /* Otherwise, make a new insn to compute this expression and make sure the
2089e4b17023SJohn Marino      insn will be recognized (this also adds any needed CLOBBERs).  */
2090e4b17023SJohn Marino   else
2091e4b17023SJohn Marino     {
2092e4b17023SJohn Marino       rtx insn = emit_insn (gen_rtx_SET (VOIDmode, reg, exp));
2093e4b17023SJohn Marino 
2094e4b17023SJohn Marino       if (insn_invalid_p (insn))
2095e4b17023SJohn Marino 	gcc_unreachable ();
2096e4b17023SJohn Marino     }
2097e4b17023SJohn Marino 
2098e4b17023SJohn Marino   pat = get_insns ();
2099e4b17023SJohn Marino   end_sequence ();
2100e4b17023SJohn Marino 
2101e4b17023SJohn Marino   return pat;
2102e4b17023SJohn Marino }
2103e4b17023SJohn Marino 
2104e4b17023SJohn Marino /* Add EXPR to the end of basic block BB.
2105e4b17023SJohn Marino 
2106e4b17023SJohn Marino    This is used by both the PRE and code hoisting.  */
2107e4b17023SJohn Marino 
2108e4b17023SJohn Marino static void
insert_insn_end_basic_block(struct expr * expr,basic_block bb)2109e4b17023SJohn Marino insert_insn_end_basic_block (struct expr *expr, basic_block bb)
2110e4b17023SJohn Marino {
2111e4b17023SJohn Marino   rtx insn = BB_END (bb);
2112e4b17023SJohn Marino   rtx new_insn;
2113e4b17023SJohn Marino   rtx reg = expr->reaching_reg;
2114e4b17023SJohn Marino   int regno = REGNO (reg);
2115e4b17023SJohn Marino   rtx pat, pat_end;
2116e4b17023SJohn Marino 
2117e4b17023SJohn Marino   pat = process_insert_insn (expr);
2118e4b17023SJohn Marino   gcc_assert (pat && INSN_P (pat));
2119e4b17023SJohn Marino 
2120e4b17023SJohn Marino   pat_end = pat;
2121e4b17023SJohn Marino   while (NEXT_INSN (pat_end) != NULL_RTX)
2122e4b17023SJohn Marino     pat_end = NEXT_INSN (pat_end);
2123e4b17023SJohn Marino 
2124e4b17023SJohn Marino   /* If the last insn is a jump, insert EXPR in front [taking care to
2125e4b17023SJohn Marino      handle cc0, etc. properly].  Similarly we need to care trapping
2126e4b17023SJohn Marino      instructions in presence of non-call exceptions.  */
2127e4b17023SJohn Marino 
2128e4b17023SJohn Marino   if (JUMP_P (insn)
2129e4b17023SJohn Marino       || (NONJUMP_INSN_P (insn)
2130e4b17023SJohn Marino 	  && (!single_succ_p (bb)
2131e4b17023SJohn Marino 	      || single_succ_edge (bb)->flags & EDGE_ABNORMAL)))
2132e4b17023SJohn Marino     {
2133e4b17023SJohn Marino #ifdef HAVE_cc0
2134e4b17023SJohn Marino       rtx note;
2135e4b17023SJohn Marino #endif
2136e4b17023SJohn Marino 
2137e4b17023SJohn Marino       /* If this is a jump table, then we can't insert stuff here.  Since
2138e4b17023SJohn Marino 	 we know the previous real insn must be the tablejump, we insert
2139e4b17023SJohn Marino 	 the new instruction just before the tablejump.  */
2140e4b17023SJohn Marino       if (GET_CODE (PATTERN (insn)) == ADDR_VEC
2141e4b17023SJohn Marino 	  || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
2142e4b17023SJohn Marino 	insn = prev_active_insn (insn);
2143e4b17023SJohn Marino 
2144e4b17023SJohn Marino #ifdef HAVE_cc0
2145e4b17023SJohn Marino       /* FIXME: 'twould be nice to call prev_cc0_setter here but it aborts
2146e4b17023SJohn Marino 	 if cc0 isn't set.  */
2147e4b17023SJohn Marino       note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
2148e4b17023SJohn Marino       if (note)
2149e4b17023SJohn Marino 	insn = XEXP (note, 0);
2150e4b17023SJohn Marino       else
2151e4b17023SJohn Marino 	{
2152e4b17023SJohn Marino 	  rtx maybe_cc0_setter = prev_nonnote_insn (insn);
2153e4b17023SJohn Marino 	  if (maybe_cc0_setter
2154e4b17023SJohn Marino 	      && INSN_P (maybe_cc0_setter)
2155e4b17023SJohn Marino 	      && sets_cc0_p (PATTERN (maybe_cc0_setter)))
2156e4b17023SJohn Marino 	    insn = maybe_cc0_setter;
2157e4b17023SJohn Marino 	}
2158e4b17023SJohn Marino #endif
2159e4b17023SJohn Marino       /* FIXME: What if something in cc0/jump uses value set in new insn?  */
2160e4b17023SJohn Marino       new_insn = emit_insn_before_noloc (pat, insn, bb);
2161e4b17023SJohn Marino     }
2162e4b17023SJohn Marino 
2163e4b17023SJohn Marino   /* Likewise if the last insn is a call, as will happen in the presence
2164e4b17023SJohn Marino      of exception handling.  */
2165e4b17023SJohn Marino   else if (CALL_P (insn)
2166e4b17023SJohn Marino 	   && (!single_succ_p (bb)
2167e4b17023SJohn Marino 	       || single_succ_edge (bb)->flags & EDGE_ABNORMAL))
2168e4b17023SJohn Marino     {
2169e4b17023SJohn Marino       /* Keeping in mind targets with small register classes and parameters
2170e4b17023SJohn Marino          in registers, we search backward and place the instructions before
2171e4b17023SJohn Marino 	 the first parameter is loaded.  Do this for everyone for consistency
2172e4b17023SJohn Marino 	 and a presumption that we'll get better code elsewhere as well.  */
2173e4b17023SJohn Marino 
2174e4b17023SJohn Marino       /* Since different machines initialize their parameter registers
2175e4b17023SJohn Marino 	 in different orders, assume nothing.  Collect the set of all
2176e4b17023SJohn Marino 	 parameter registers.  */
2177e4b17023SJohn Marino       insn = find_first_parameter_load (insn, BB_HEAD (bb));
2178e4b17023SJohn Marino 
2179e4b17023SJohn Marino       /* If we found all the parameter loads, then we want to insert
2180e4b17023SJohn Marino 	 before the first parameter load.
2181e4b17023SJohn Marino 
2182e4b17023SJohn Marino 	 If we did not find all the parameter loads, then we might have
2183e4b17023SJohn Marino 	 stopped on the head of the block, which could be a CODE_LABEL.
2184e4b17023SJohn Marino 	 If we inserted before the CODE_LABEL, then we would be putting
2185e4b17023SJohn Marino 	 the insn in the wrong basic block.  In that case, put the insn
2186e4b17023SJohn Marino 	 after the CODE_LABEL.  Also, respect NOTE_INSN_BASIC_BLOCK.  */
2187e4b17023SJohn Marino       while (LABEL_P (insn)
2188e4b17023SJohn Marino 	     || NOTE_INSN_BASIC_BLOCK_P (insn))
2189e4b17023SJohn Marino 	insn = NEXT_INSN (insn);
2190e4b17023SJohn Marino 
2191e4b17023SJohn Marino       new_insn = emit_insn_before_noloc (pat, insn, bb);
2192e4b17023SJohn Marino     }
2193e4b17023SJohn Marino   else
2194e4b17023SJohn Marino     new_insn = emit_insn_after_noloc (pat, insn, bb);
2195e4b17023SJohn Marino 
2196e4b17023SJohn Marino   while (1)
2197e4b17023SJohn Marino     {
2198e4b17023SJohn Marino       if (INSN_P (pat))
2199e4b17023SJohn Marino 	add_label_notes (PATTERN (pat), new_insn);
2200e4b17023SJohn Marino       if (pat == pat_end)
2201e4b17023SJohn Marino 	break;
2202e4b17023SJohn Marino       pat = NEXT_INSN (pat);
2203e4b17023SJohn Marino     }
2204e4b17023SJohn Marino 
2205e4b17023SJohn Marino   gcse_create_count++;
2206e4b17023SJohn Marino 
2207e4b17023SJohn Marino   if (dump_file)
2208e4b17023SJohn Marino     {
2209e4b17023SJohn Marino       fprintf (dump_file, "PRE/HOIST: end of bb %d, insn %d, ",
2210e4b17023SJohn Marino 	       bb->index, INSN_UID (new_insn));
2211e4b17023SJohn Marino       fprintf (dump_file, "copying expression %d to reg %d\n",
2212e4b17023SJohn Marino 	       expr->bitmap_index, regno);
2213e4b17023SJohn Marino     }
2214e4b17023SJohn Marino }
2215e4b17023SJohn Marino 
2216e4b17023SJohn Marino /* Insert partially redundant expressions on edges in the CFG to make
2217e4b17023SJohn Marino    the expressions fully redundant.  */
2218e4b17023SJohn Marino 
2219e4b17023SJohn Marino static int
pre_edge_insert(struct edge_list * edge_list,struct expr ** index_map)2220e4b17023SJohn Marino pre_edge_insert (struct edge_list *edge_list, struct expr **index_map)
2221e4b17023SJohn Marino {
2222e4b17023SJohn Marino   int e, i, j, num_edges, set_size, did_insert = 0;
2223e4b17023SJohn Marino   sbitmap *inserted;
2224e4b17023SJohn Marino 
2225e4b17023SJohn Marino   /* Where PRE_INSERT_MAP is nonzero, we add the expression on that edge
2226e4b17023SJohn Marino      if it reaches any of the deleted expressions.  */
2227e4b17023SJohn Marino 
2228e4b17023SJohn Marino   set_size = pre_insert_map[0]->size;
2229e4b17023SJohn Marino   num_edges = NUM_EDGES (edge_list);
2230e4b17023SJohn Marino   inserted = sbitmap_vector_alloc (num_edges, expr_hash_table.n_elems);
2231e4b17023SJohn Marino   sbitmap_vector_zero (inserted, num_edges);
2232e4b17023SJohn Marino 
2233e4b17023SJohn Marino   for (e = 0; e < num_edges; e++)
2234e4b17023SJohn Marino     {
2235e4b17023SJohn Marino       int indx;
2236e4b17023SJohn Marino       basic_block bb = INDEX_EDGE_PRED_BB (edge_list, e);
2237e4b17023SJohn Marino 
2238e4b17023SJohn Marino       for (i = indx = 0; i < set_size; i++, indx += SBITMAP_ELT_BITS)
2239e4b17023SJohn Marino 	{
2240e4b17023SJohn Marino 	  SBITMAP_ELT_TYPE insert = pre_insert_map[e]->elms[i];
2241e4b17023SJohn Marino 
2242e4b17023SJohn Marino 	  for (j = indx;
2243e4b17023SJohn Marino 	       insert && j < (int) expr_hash_table.n_elems;
2244e4b17023SJohn Marino 	       j++, insert >>= 1)
2245e4b17023SJohn Marino 	    if ((insert & 1) != 0 && index_map[j]->reaching_reg != NULL_RTX)
2246e4b17023SJohn Marino 	      {
2247e4b17023SJohn Marino 		struct expr *expr = index_map[j];
2248e4b17023SJohn Marino 		struct occr *occr;
2249e4b17023SJohn Marino 
2250e4b17023SJohn Marino 		/* Now look at each deleted occurrence of this expression.  */
2251e4b17023SJohn Marino 		for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
2252e4b17023SJohn Marino 		  {
2253e4b17023SJohn Marino 		    if (! occr->deleted_p)
2254e4b17023SJohn Marino 		      continue;
2255e4b17023SJohn Marino 
2256e4b17023SJohn Marino 		    /* Insert this expression on this edge if it would
2257e4b17023SJohn Marino 		       reach the deleted occurrence in BB.  */
2258e4b17023SJohn Marino 		    if (!TEST_BIT (inserted[e], j))
2259e4b17023SJohn Marino 		      {
2260e4b17023SJohn Marino 			rtx insn;
2261e4b17023SJohn Marino 			edge eg = INDEX_EDGE (edge_list, e);
2262e4b17023SJohn Marino 
2263e4b17023SJohn Marino 			/* We can't insert anything on an abnormal and
2264e4b17023SJohn Marino 			   critical edge, so we insert the insn at the end of
2265e4b17023SJohn Marino 			   the previous block. There are several alternatives
2266e4b17023SJohn Marino 			   detailed in Morgans book P277 (sec 10.5) for
2267e4b17023SJohn Marino 			   handling this situation.  This one is easiest for
2268e4b17023SJohn Marino 			   now.  */
2269e4b17023SJohn Marino 
2270e4b17023SJohn Marino 			if (eg->flags & EDGE_ABNORMAL)
2271e4b17023SJohn Marino 			  insert_insn_end_basic_block (index_map[j], bb);
2272e4b17023SJohn Marino 			else
2273e4b17023SJohn Marino 			  {
2274e4b17023SJohn Marino 			    insn = process_insert_insn (index_map[j]);
2275e4b17023SJohn Marino 			    insert_insn_on_edge (insn, eg);
2276e4b17023SJohn Marino 			  }
2277e4b17023SJohn Marino 
2278e4b17023SJohn Marino 			if (dump_file)
2279e4b17023SJohn Marino 			  {
2280e4b17023SJohn Marino 			    fprintf (dump_file, "PRE: edge (%d,%d), ",
2281e4b17023SJohn Marino 				     bb->index,
2282e4b17023SJohn Marino 				     INDEX_EDGE_SUCC_BB (edge_list, e)->index);
2283e4b17023SJohn Marino 			    fprintf (dump_file, "copy expression %d\n",
2284e4b17023SJohn Marino 				     expr->bitmap_index);
2285e4b17023SJohn Marino 			  }
2286e4b17023SJohn Marino 
2287e4b17023SJohn Marino 			update_ld_motion_stores (expr);
2288e4b17023SJohn Marino 			SET_BIT (inserted[e], j);
2289e4b17023SJohn Marino 			did_insert = 1;
2290e4b17023SJohn Marino 			gcse_create_count++;
2291e4b17023SJohn Marino 		      }
2292e4b17023SJohn Marino 		  }
2293e4b17023SJohn Marino 	      }
2294e4b17023SJohn Marino 	}
2295e4b17023SJohn Marino     }
2296e4b17023SJohn Marino 
2297e4b17023SJohn Marino   sbitmap_vector_free (inserted);
2298e4b17023SJohn Marino   return did_insert;
2299e4b17023SJohn Marino }
2300e4b17023SJohn Marino 
2301e4b17023SJohn Marino /* Copy the result of EXPR->EXPR generated by INSN to EXPR->REACHING_REG.
2302e4b17023SJohn Marino    Given "old_reg <- expr" (INSN), instead of adding after it
2303e4b17023SJohn Marino      reaching_reg <- old_reg
2304e4b17023SJohn Marino    it's better to do the following:
2305e4b17023SJohn Marino      reaching_reg <- expr
2306e4b17023SJohn Marino      old_reg      <- reaching_reg
2307e4b17023SJohn Marino    because this way copy propagation can discover additional PRE
2308e4b17023SJohn Marino    opportunities.  But if this fails, we try the old way.
2309e4b17023SJohn Marino    When "expr" is a store, i.e.
2310e4b17023SJohn Marino    given "MEM <- old_reg", instead of adding after it
2311e4b17023SJohn Marino      reaching_reg <- old_reg
2312e4b17023SJohn Marino    it's better to add it before as follows:
2313e4b17023SJohn Marino      reaching_reg <- old_reg
2314e4b17023SJohn Marino      MEM          <- reaching_reg.  */
2315e4b17023SJohn Marino 
2316e4b17023SJohn Marino static void
pre_insert_copy_insn(struct expr * expr,rtx insn)2317e4b17023SJohn Marino pre_insert_copy_insn (struct expr *expr, rtx insn)
2318e4b17023SJohn Marino {
2319e4b17023SJohn Marino   rtx reg = expr->reaching_reg;
2320e4b17023SJohn Marino   int regno = REGNO (reg);
2321e4b17023SJohn Marino   int indx = expr->bitmap_index;
2322e4b17023SJohn Marino   rtx pat = PATTERN (insn);
2323e4b17023SJohn Marino   rtx set, first_set, new_insn;
2324e4b17023SJohn Marino   rtx old_reg;
2325e4b17023SJohn Marino   int i;
2326e4b17023SJohn Marino 
2327e4b17023SJohn Marino   /* This block matches the logic in hash_scan_insn.  */
2328e4b17023SJohn Marino   switch (GET_CODE (pat))
2329e4b17023SJohn Marino     {
2330e4b17023SJohn Marino     case SET:
2331e4b17023SJohn Marino       set = pat;
2332e4b17023SJohn Marino       break;
2333e4b17023SJohn Marino 
2334e4b17023SJohn Marino     case PARALLEL:
2335e4b17023SJohn Marino       /* Search through the parallel looking for the set whose
2336e4b17023SJohn Marino 	 source was the expression that we're interested in.  */
2337e4b17023SJohn Marino       first_set = NULL_RTX;
2338e4b17023SJohn Marino       set = NULL_RTX;
2339e4b17023SJohn Marino       for (i = 0; i < XVECLEN (pat, 0); i++)
2340e4b17023SJohn Marino 	{
2341e4b17023SJohn Marino 	  rtx x = XVECEXP (pat, 0, i);
2342e4b17023SJohn Marino 	  if (GET_CODE (x) == SET)
2343e4b17023SJohn Marino 	    {
2344e4b17023SJohn Marino 	      /* If the source was a REG_EQUAL or REG_EQUIV note, we
2345e4b17023SJohn Marino 		 may not find an equivalent expression, but in this
2346e4b17023SJohn Marino 		 case the PARALLEL will have a single set.  */
2347e4b17023SJohn Marino 	      if (first_set == NULL_RTX)
2348e4b17023SJohn Marino 		first_set = x;
2349e4b17023SJohn Marino 	      if (expr_equiv_p (SET_SRC (x), expr->expr))
2350e4b17023SJohn Marino 	        {
2351e4b17023SJohn Marino 	          set = x;
2352e4b17023SJohn Marino 	          break;
2353e4b17023SJohn Marino 	        }
2354e4b17023SJohn Marino 	    }
2355e4b17023SJohn Marino 	}
2356e4b17023SJohn Marino 
2357e4b17023SJohn Marino       gcc_assert (first_set);
2358e4b17023SJohn Marino       if (set == NULL_RTX)
2359e4b17023SJohn Marino         set = first_set;
2360e4b17023SJohn Marino       break;
2361e4b17023SJohn Marino 
2362e4b17023SJohn Marino     default:
2363e4b17023SJohn Marino       gcc_unreachable ();
2364e4b17023SJohn Marino     }
2365e4b17023SJohn Marino 
2366e4b17023SJohn Marino   if (REG_P (SET_DEST (set)))
2367e4b17023SJohn Marino     {
2368e4b17023SJohn Marino       old_reg = SET_DEST (set);
2369e4b17023SJohn Marino       /* Check if we can modify the set destination in the original insn.  */
2370e4b17023SJohn Marino       if (validate_change (insn, &SET_DEST (set), reg, 0))
2371e4b17023SJohn Marino         {
2372e4b17023SJohn Marino           new_insn = gen_move_insn (old_reg, reg);
2373e4b17023SJohn Marino           new_insn = emit_insn_after (new_insn, insn);
2374e4b17023SJohn Marino         }
2375e4b17023SJohn Marino       else
2376e4b17023SJohn Marino         {
2377e4b17023SJohn Marino           new_insn = gen_move_insn (reg, old_reg);
2378e4b17023SJohn Marino           new_insn = emit_insn_after (new_insn, insn);
2379e4b17023SJohn Marino         }
2380e4b17023SJohn Marino     }
2381e4b17023SJohn Marino   else /* This is possible only in case of a store to memory.  */
2382e4b17023SJohn Marino     {
2383e4b17023SJohn Marino       old_reg = SET_SRC (set);
2384e4b17023SJohn Marino       new_insn = gen_move_insn (reg, old_reg);
2385e4b17023SJohn Marino 
2386e4b17023SJohn Marino       /* Check if we can modify the set source in the original insn.  */
2387e4b17023SJohn Marino       if (validate_change (insn, &SET_SRC (set), reg, 0))
2388e4b17023SJohn Marino         new_insn = emit_insn_before (new_insn, insn);
2389e4b17023SJohn Marino       else
2390e4b17023SJohn Marino         new_insn = emit_insn_after (new_insn, insn);
2391e4b17023SJohn Marino     }
2392e4b17023SJohn Marino 
2393e4b17023SJohn Marino   gcse_create_count++;
2394e4b17023SJohn Marino 
2395e4b17023SJohn Marino   if (dump_file)
2396e4b17023SJohn Marino     fprintf (dump_file,
2397e4b17023SJohn Marino 	     "PRE: bb %d, insn %d, copy expression %d in insn %d to reg %d\n",
2398e4b17023SJohn Marino 	      BLOCK_FOR_INSN (insn)->index, INSN_UID (new_insn), indx,
2399e4b17023SJohn Marino 	      INSN_UID (insn), regno);
2400e4b17023SJohn Marino }
2401e4b17023SJohn Marino 
2402e4b17023SJohn Marino /* Copy available expressions that reach the redundant expression
2403e4b17023SJohn Marino    to `reaching_reg'.  */
2404e4b17023SJohn Marino 
2405e4b17023SJohn Marino static void
pre_insert_copies(void)2406e4b17023SJohn Marino pre_insert_copies (void)
2407e4b17023SJohn Marino {
2408e4b17023SJohn Marino   unsigned int i, added_copy;
2409e4b17023SJohn Marino   struct expr *expr;
2410e4b17023SJohn Marino   struct occr *occr;
2411e4b17023SJohn Marino   struct occr *avail;
2412e4b17023SJohn Marino 
2413e4b17023SJohn Marino   /* For each available expression in the table, copy the result to
2414e4b17023SJohn Marino      `reaching_reg' if the expression reaches a deleted one.
2415e4b17023SJohn Marino 
2416e4b17023SJohn Marino      ??? The current algorithm is rather brute force.
2417e4b17023SJohn Marino      Need to do some profiling.  */
2418e4b17023SJohn Marino 
2419e4b17023SJohn Marino   for (i = 0; i < expr_hash_table.size; i++)
2420e4b17023SJohn Marino     for (expr = expr_hash_table.table[i]; expr; expr = expr->next_same_hash)
2421e4b17023SJohn Marino       {
2422e4b17023SJohn Marino 	/* If the basic block isn't reachable, PPOUT will be TRUE.  However,
2423e4b17023SJohn Marino 	   we don't want to insert a copy here because the expression may not
2424e4b17023SJohn Marino 	   really be redundant.  So only insert an insn if the expression was
2425e4b17023SJohn Marino 	   deleted.  This test also avoids further processing if the
2426e4b17023SJohn Marino 	   expression wasn't deleted anywhere.  */
2427e4b17023SJohn Marino 	if (expr->reaching_reg == NULL)
2428e4b17023SJohn Marino 	  continue;
2429e4b17023SJohn Marino 
2430e4b17023SJohn Marino 	/* Set when we add a copy for that expression.  */
2431e4b17023SJohn Marino 	added_copy = 0;
2432e4b17023SJohn Marino 
2433e4b17023SJohn Marino 	for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
2434e4b17023SJohn Marino 	  {
2435e4b17023SJohn Marino 	    if (! occr->deleted_p)
2436e4b17023SJohn Marino 	      continue;
2437e4b17023SJohn Marino 
2438e4b17023SJohn Marino 	    for (avail = expr->avail_occr; avail != NULL; avail = avail->next)
2439e4b17023SJohn Marino 	      {
2440e4b17023SJohn Marino 		rtx insn = avail->insn;
2441e4b17023SJohn Marino 
2442e4b17023SJohn Marino 		/* No need to handle this one if handled already.  */
2443e4b17023SJohn Marino 		if (avail->copied_p)
2444e4b17023SJohn Marino 		  continue;
2445e4b17023SJohn Marino 
2446e4b17023SJohn Marino 		/* Don't handle this one if it's a redundant one.  */
2447e4b17023SJohn Marino 		if (INSN_DELETED_P (insn))
2448e4b17023SJohn Marino 		  continue;
2449e4b17023SJohn Marino 
2450e4b17023SJohn Marino 		/* Or if the expression doesn't reach the deleted one.  */
2451e4b17023SJohn Marino 		if (! pre_expr_reaches_here_p (BLOCK_FOR_INSN (avail->insn),
2452e4b17023SJohn Marino 					       expr,
2453e4b17023SJohn Marino 					       BLOCK_FOR_INSN (occr->insn)))
2454e4b17023SJohn Marino 		  continue;
2455e4b17023SJohn Marino 
2456e4b17023SJohn Marino                 added_copy = 1;
2457e4b17023SJohn Marino 
2458e4b17023SJohn Marino 		/* Copy the result of avail to reaching_reg.  */
2459e4b17023SJohn Marino 		pre_insert_copy_insn (expr, insn);
2460e4b17023SJohn Marino 		avail->copied_p = 1;
2461e4b17023SJohn Marino 	      }
2462e4b17023SJohn Marino 	  }
2463e4b17023SJohn Marino 
2464e4b17023SJohn Marino 	  if (added_copy)
2465e4b17023SJohn Marino             update_ld_motion_stores (expr);
2466e4b17023SJohn Marino       }
2467e4b17023SJohn Marino }
2468e4b17023SJohn Marino 
2469e4b17023SJohn Marino /* Emit move from SRC to DEST noting the equivalence with expression computed
2470e4b17023SJohn Marino    in INSN.  */
2471e4b17023SJohn Marino 
2472e4b17023SJohn Marino static rtx
gcse_emit_move_after(rtx dest,rtx src,rtx insn)2473e4b17023SJohn Marino gcse_emit_move_after (rtx dest, rtx src, rtx insn)
2474e4b17023SJohn Marino {
2475e4b17023SJohn Marino   rtx new_rtx;
2476e4b17023SJohn Marino   rtx set = single_set (insn), set2;
2477e4b17023SJohn Marino   rtx note;
2478e4b17023SJohn Marino   rtx eqv;
2479e4b17023SJohn Marino 
2480e4b17023SJohn Marino   /* This should never fail since we're creating a reg->reg copy
2481e4b17023SJohn Marino      we've verified to be valid.  */
2482e4b17023SJohn Marino 
2483e4b17023SJohn Marino   new_rtx = emit_insn_after (gen_move_insn (dest, src), insn);
2484e4b17023SJohn Marino 
2485e4b17023SJohn Marino   /* Note the equivalence for local CSE pass.  */
2486e4b17023SJohn Marino   set2 = single_set (new_rtx);
2487e4b17023SJohn Marino   if (!set2 || !rtx_equal_p (SET_DEST (set2), dest))
2488e4b17023SJohn Marino     return new_rtx;
2489e4b17023SJohn Marino   if ((note = find_reg_equal_equiv_note (insn)))
2490e4b17023SJohn Marino     eqv = XEXP (note, 0);
2491e4b17023SJohn Marino   else
2492e4b17023SJohn Marino     eqv = SET_SRC (set);
2493e4b17023SJohn Marino 
2494e4b17023SJohn Marino   set_unique_reg_note (new_rtx, REG_EQUAL, copy_insn_1 (eqv));
2495e4b17023SJohn Marino 
2496e4b17023SJohn Marino   return new_rtx;
2497e4b17023SJohn Marino }
2498e4b17023SJohn Marino 
2499e4b17023SJohn Marino /* Delete redundant computations.
2500e4b17023SJohn Marino    Deletion is done by changing the insn to copy the `reaching_reg' of
2501e4b17023SJohn Marino    the expression into the result of the SET.  It is left to later passes
2502e4b17023SJohn Marino    (cprop, cse2, flow, combine, regmove) to propagate the copy or eliminate it.
2503e4b17023SJohn Marino 
2504e4b17023SJohn Marino    Return nonzero if a change is made.  */
2505e4b17023SJohn Marino 
2506e4b17023SJohn Marino static int
pre_delete(void)2507e4b17023SJohn Marino pre_delete (void)
2508e4b17023SJohn Marino {
2509e4b17023SJohn Marino   unsigned int i;
2510e4b17023SJohn Marino   int changed;
2511e4b17023SJohn Marino   struct expr *expr;
2512e4b17023SJohn Marino   struct occr *occr;
2513e4b17023SJohn Marino 
2514e4b17023SJohn Marino   changed = 0;
2515e4b17023SJohn Marino   for (i = 0; i < expr_hash_table.size; i++)
2516e4b17023SJohn Marino     for (expr = expr_hash_table.table[i]; expr; expr = expr->next_same_hash)
2517e4b17023SJohn Marino       {
2518e4b17023SJohn Marino 	int indx = expr->bitmap_index;
2519e4b17023SJohn Marino 
2520e4b17023SJohn Marino 	/* We only need to search antic_occr since we require ANTLOC != 0.  */
2521e4b17023SJohn Marino 	for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
2522e4b17023SJohn Marino 	  {
2523e4b17023SJohn Marino 	    rtx insn = occr->insn;
2524e4b17023SJohn Marino 	    rtx set;
2525e4b17023SJohn Marino 	    basic_block bb = BLOCK_FOR_INSN (insn);
2526e4b17023SJohn Marino 
2527e4b17023SJohn Marino 	    /* We only delete insns that have a single_set.  */
2528e4b17023SJohn Marino 	    if (TEST_BIT (pre_delete_map[bb->index], indx)
2529e4b17023SJohn Marino 		&& (set = single_set (insn)) != 0
2530e4b17023SJohn Marino                 && dbg_cnt (pre_insn))
2531e4b17023SJohn Marino 	      {
2532e4b17023SJohn Marino 		/* Create a pseudo-reg to store the result of reaching
2533e4b17023SJohn Marino 		   expressions into.  Get the mode for the new pseudo from
2534e4b17023SJohn Marino 		   the mode of the original destination pseudo.  */
2535e4b17023SJohn Marino 		if (expr->reaching_reg == NULL)
2536e4b17023SJohn Marino 		  expr->reaching_reg = gen_reg_rtx_and_attrs (SET_DEST (set));
2537e4b17023SJohn Marino 
2538e4b17023SJohn Marino 		gcse_emit_move_after (SET_DEST (set), expr->reaching_reg, insn);
2539e4b17023SJohn Marino 		delete_insn (insn);
2540e4b17023SJohn Marino 		occr->deleted_p = 1;
2541e4b17023SJohn Marino 		changed = 1;
2542e4b17023SJohn Marino 		gcse_subst_count++;
2543e4b17023SJohn Marino 
2544e4b17023SJohn Marino 		if (dump_file)
2545e4b17023SJohn Marino 		  {
2546e4b17023SJohn Marino 		    fprintf (dump_file,
2547e4b17023SJohn Marino 			     "PRE: redundant insn %d (expression %d) in ",
2548e4b17023SJohn Marino 			       INSN_UID (insn), indx);
2549e4b17023SJohn Marino 		    fprintf (dump_file, "bb %d, reaching reg is %d\n",
2550e4b17023SJohn Marino 			     bb->index, REGNO (expr->reaching_reg));
2551e4b17023SJohn Marino 		  }
2552e4b17023SJohn Marino 	      }
2553e4b17023SJohn Marino 	  }
2554e4b17023SJohn Marino       }
2555e4b17023SJohn Marino 
2556e4b17023SJohn Marino   return changed;
2557e4b17023SJohn Marino }
2558e4b17023SJohn Marino 
2559e4b17023SJohn Marino /* Perform GCSE optimizations using PRE.
2560e4b17023SJohn Marino    This is called by one_pre_gcse_pass after all the dataflow analysis
2561e4b17023SJohn Marino    has been done.
2562e4b17023SJohn Marino 
2563e4b17023SJohn Marino    This is based on the original Morel-Renvoise paper Fred Chow's thesis, and
2564e4b17023SJohn Marino    lazy code motion from Knoop, Ruthing and Steffen as described in Advanced
2565e4b17023SJohn Marino    Compiler Design and Implementation.
2566e4b17023SJohn Marino 
2567e4b17023SJohn Marino    ??? A new pseudo reg is created to hold the reaching expression.  The nice
2568e4b17023SJohn Marino    thing about the classical approach is that it would try to use an existing
2569e4b17023SJohn Marino    reg.  If the register can't be adequately optimized [i.e. we introduce
2570e4b17023SJohn Marino    reload problems], one could add a pass here to propagate the new register
2571e4b17023SJohn Marino    through the block.
2572e4b17023SJohn Marino 
2573e4b17023SJohn Marino    ??? We don't handle single sets in PARALLELs because we're [currently] not
2574e4b17023SJohn Marino    able to copy the rest of the parallel when we insert copies to create full
2575e4b17023SJohn Marino    redundancies from partial redundancies.  However, there's no reason why we
2576e4b17023SJohn Marino    can't handle PARALLELs in the cases where there are no partial
2577e4b17023SJohn Marino    redundancies.  */
2578e4b17023SJohn Marino 
2579e4b17023SJohn Marino static int
pre_gcse(struct edge_list * edge_list)2580e4b17023SJohn Marino pre_gcse (struct edge_list *edge_list)
2581e4b17023SJohn Marino {
2582e4b17023SJohn Marino   unsigned int i;
2583e4b17023SJohn Marino   int did_insert, changed;
2584e4b17023SJohn Marino   struct expr **index_map;
2585e4b17023SJohn Marino   struct expr *expr;
2586e4b17023SJohn Marino 
2587e4b17023SJohn Marino   /* Compute a mapping from expression number (`bitmap_index') to
2588e4b17023SJohn Marino      hash table entry.  */
2589e4b17023SJohn Marino 
2590e4b17023SJohn Marino   index_map = XCNEWVEC (struct expr *, expr_hash_table.n_elems);
2591e4b17023SJohn Marino   for (i = 0; i < expr_hash_table.size; i++)
2592e4b17023SJohn Marino     for (expr = expr_hash_table.table[i]; expr; expr = expr->next_same_hash)
2593e4b17023SJohn Marino       index_map[expr->bitmap_index] = expr;
2594e4b17023SJohn Marino 
2595e4b17023SJohn Marino   /* Delete the redundant insns first so that
2596e4b17023SJohn Marino      - we know what register to use for the new insns and for the other
2597e4b17023SJohn Marino        ones with reaching expressions
2598e4b17023SJohn Marino      - we know which insns are redundant when we go to create copies  */
2599e4b17023SJohn Marino 
2600e4b17023SJohn Marino   changed = pre_delete ();
2601e4b17023SJohn Marino   did_insert = pre_edge_insert (edge_list, index_map);
2602e4b17023SJohn Marino 
2603e4b17023SJohn Marino   /* In other places with reaching expressions, copy the expression to the
2604e4b17023SJohn Marino      specially allocated pseudo-reg that reaches the redundant expr.  */
2605e4b17023SJohn Marino   pre_insert_copies ();
2606e4b17023SJohn Marino   if (did_insert)
2607e4b17023SJohn Marino     {
2608e4b17023SJohn Marino       commit_edge_insertions ();
2609e4b17023SJohn Marino       changed = 1;
2610e4b17023SJohn Marino     }
2611e4b17023SJohn Marino 
2612e4b17023SJohn Marino   free (index_map);
2613e4b17023SJohn Marino   return changed;
2614e4b17023SJohn Marino }
2615e4b17023SJohn Marino 
2616e4b17023SJohn Marino /* Top level routine to perform one PRE GCSE pass.
2617e4b17023SJohn Marino 
2618e4b17023SJohn Marino    Return nonzero if a change was made.  */
2619e4b17023SJohn Marino 
2620e4b17023SJohn Marino static int
one_pre_gcse_pass(void)2621e4b17023SJohn Marino one_pre_gcse_pass (void)
2622e4b17023SJohn Marino {
2623e4b17023SJohn Marino   int changed = 0;
2624e4b17023SJohn Marino 
2625e4b17023SJohn Marino   gcse_subst_count = 0;
2626e4b17023SJohn Marino   gcse_create_count = 0;
2627e4b17023SJohn Marino 
2628e4b17023SJohn Marino   /* Return if there's nothing to do, or it is too expensive.  */
2629e4b17023SJohn Marino   if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1
2630e4b17023SJohn Marino       || is_too_expensive (_("PRE disabled")))
2631e4b17023SJohn Marino     return 0;
2632e4b17023SJohn Marino 
2633e4b17023SJohn Marino   /* We need alias.  */
2634e4b17023SJohn Marino   init_alias_analysis ();
2635e4b17023SJohn Marino 
2636e4b17023SJohn Marino   bytes_used = 0;
2637e4b17023SJohn Marino   gcc_obstack_init (&gcse_obstack);
2638e4b17023SJohn Marino   alloc_gcse_mem ();
2639e4b17023SJohn Marino 
2640e4b17023SJohn Marino   alloc_hash_table (&expr_hash_table);
2641e4b17023SJohn Marino   add_noreturn_fake_exit_edges ();
2642e4b17023SJohn Marino   if (flag_gcse_lm)
2643e4b17023SJohn Marino     compute_ld_motion_mems ();
2644e4b17023SJohn Marino 
2645e4b17023SJohn Marino   compute_hash_table (&expr_hash_table);
2646e4b17023SJohn Marino   if (flag_gcse_lm)
2647e4b17023SJohn Marino     trim_ld_motion_mems ();
2648e4b17023SJohn Marino   if (dump_file)
2649e4b17023SJohn Marino     dump_hash_table (dump_file, "Expression", &expr_hash_table);
2650e4b17023SJohn Marino 
2651e4b17023SJohn Marino   if (expr_hash_table.n_elems > 0)
2652e4b17023SJohn Marino     {
2653e4b17023SJohn Marino       struct edge_list *edge_list;
2654e4b17023SJohn Marino       alloc_pre_mem (last_basic_block, expr_hash_table.n_elems);
2655e4b17023SJohn Marino       edge_list = compute_pre_data ();
2656e4b17023SJohn Marino       changed |= pre_gcse (edge_list);
2657e4b17023SJohn Marino       free_edge_list (edge_list);
2658e4b17023SJohn Marino       free_pre_mem ();
2659e4b17023SJohn Marino     }
2660e4b17023SJohn Marino 
2661e4b17023SJohn Marino   if (flag_gcse_lm)
2662e4b17023SJohn Marino     free_ld_motion_mems ();
2663e4b17023SJohn Marino   remove_fake_exit_edges ();
2664e4b17023SJohn Marino   free_hash_table (&expr_hash_table);
2665e4b17023SJohn Marino 
2666e4b17023SJohn Marino   free_gcse_mem ();
2667e4b17023SJohn Marino   obstack_free (&gcse_obstack, NULL);
2668e4b17023SJohn Marino 
2669e4b17023SJohn Marino   /* We are finished with alias.  */
2670e4b17023SJohn Marino   end_alias_analysis ();
2671e4b17023SJohn Marino 
2672e4b17023SJohn Marino   if (dump_file)
2673e4b17023SJohn Marino     {
2674e4b17023SJohn Marino       fprintf (dump_file, "PRE GCSE of %s, %d basic blocks, %d bytes needed, ",
2675e4b17023SJohn Marino 	       current_function_name (), n_basic_blocks, bytes_used);
2676e4b17023SJohn Marino       fprintf (dump_file, "%d substs, %d insns created\n",
2677e4b17023SJohn Marino 	       gcse_subst_count, gcse_create_count);
2678e4b17023SJohn Marino     }
2679e4b17023SJohn Marino 
2680e4b17023SJohn Marino   return changed;
2681e4b17023SJohn Marino }
2682e4b17023SJohn Marino 
2683e4b17023SJohn Marino /* If X contains any LABEL_REF's, add REG_LABEL_OPERAND notes for them
2684e4b17023SJohn Marino    to INSN.  If such notes are added to an insn which references a
2685e4b17023SJohn Marino    CODE_LABEL, the LABEL_NUSES count is incremented.  We have to add
2686e4b17023SJohn Marino    that note, because the following loop optimization pass requires
2687e4b17023SJohn Marino    them.  */
2688e4b17023SJohn Marino 
2689e4b17023SJohn Marino /* ??? If there was a jump optimization pass after gcse and before loop,
2690e4b17023SJohn Marino    then we would not need to do this here, because jump would add the
2691e4b17023SJohn Marino    necessary REG_LABEL_OPERAND and REG_LABEL_TARGET notes.  */
2692e4b17023SJohn Marino 
2693e4b17023SJohn Marino static void
add_label_notes(rtx x,rtx insn)2694e4b17023SJohn Marino add_label_notes (rtx x, rtx insn)
2695e4b17023SJohn Marino {
2696e4b17023SJohn Marino   enum rtx_code code = GET_CODE (x);
2697e4b17023SJohn Marino   int i, j;
2698e4b17023SJohn Marino   const char *fmt;
2699e4b17023SJohn Marino 
2700e4b17023SJohn Marino   if (code == LABEL_REF && !LABEL_REF_NONLOCAL_P (x))
2701e4b17023SJohn Marino     {
2702e4b17023SJohn Marino       /* This code used to ignore labels that referred to dispatch tables to
2703e4b17023SJohn Marino 	 avoid flow generating (slightly) worse code.
2704e4b17023SJohn Marino 
2705e4b17023SJohn Marino 	 We no longer ignore such label references (see LABEL_REF handling in
2706e4b17023SJohn Marino 	 mark_jump_label for additional information).  */
2707e4b17023SJohn Marino 
2708e4b17023SJohn Marino       /* There's no reason for current users to emit jump-insns with
2709e4b17023SJohn Marino 	 such a LABEL_REF, so we don't have to handle REG_LABEL_TARGET
2710e4b17023SJohn Marino 	 notes.  */
2711e4b17023SJohn Marino       gcc_assert (!JUMP_P (insn));
2712e4b17023SJohn Marino       add_reg_note (insn, REG_LABEL_OPERAND, XEXP (x, 0));
2713e4b17023SJohn Marino 
2714e4b17023SJohn Marino       if (LABEL_P (XEXP (x, 0)))
2715e4b17023SJohn Marino 	LABEL_NUSES (XEXP (x, 0))++;
2716e4b17023SJohn Marino 
2717e4b17023SJohn Marino       return;
2718e4b17023SJohn Marino     }
2719e4b17023SJohn Marino 
2720e4b17023SJohn Marino   for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
2721e4b17023SJohn Marino     {
2722e4b17023SJohn Marino       if (fmt[i] == 'e')
2723e4b17023SJohn Marino 	add_label_notes (XEXP (x, i), insn);
2724e4b17023SJohn Marino       else if (fmt[i] == 'E')
2725e4b17023SJohn Marino 	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
2726e4b17023SJohn Marino 	  add_label_notes (XVECEXP (x, i, j), insn);
2727e4b17023SJohn Marino     }
2728e4b17023SJohn Marino }
2729e4b17023SJohn Marino 
2730e4b17023SJohn Marino /* Code Hoisting variables and subroutines.  */
2731e4b17023SJohn Marino 
2732e4b17023SJohn Marino /* Very busy expressions.  */
2733e4b17023SJohn Marino static sbitmap *hoist_vbein;
2734e4b17023SJohn Marino static sbitmap *hoist_vbeout;
2735e4b17023SJohn Marino 
2736e4b17023SJohn Marino /* ??? We could compute post dominators and run this algorithm in
2737e4b17023SJohn Marino    reverse to perform tail merging, doing so would probably be
2738e4b17023SJohn Marino    more effective than the tail merging code in jump.c.
2739e4b17023SJohn Marino 
2740e4b17023SJohn Marino    It's unclear if tail merging could be run in parallel with
2741e4b17023SJohn Marino    code hoisting.  It would be nice.  */
2742e4b17023SJohn Marino 
2743e4b17023SJohn Marino /* Allocate vars used for code hoisting analysis.  */
2744e4b17023SJohn Marino 
2745e4b17023SJohn Marino static void
alloc_code_hoist_mem(int n_blocks,int n_exprs)2746e4b17023SJohn Marino alloc_code_hoist_mem (int n_blocks, int n_exprs)
2747e4b17023SJohn Marino {
2748e4b17023SJohn Marino   antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
2749e4b17023SJohn Marino   transp = sbitmap_vector_alloc (n_blocks, n_exprs);
2750e4b17023SJohn Marino   comp = sbitmap_vector_alloc (n_blocks, n_exprs);
2751e4b17023SJohn Marino 
2752e4b17023SJohn Marino   hoist_vbein = sbitmap_vector_alloc (n_blocks, n_exprs);
2753e4b17023SJohn Marino   hoist_vbeout = sbitmap_vector_alloc (n_blocks, n_exprs);
2754e4b17023SJohn Marino }
2755e4b17023SJohn Marino 
2756e4b17023SJohn Marino /* Free vars used for code hoisting analysis.  */
2757e4b17023SJohn Marino 
2758e4b17023SJohn Marino static void
free_code_hoist_mem(void)2759e4b17023SJohn Marino free_code_hoist_mem (void)
2760e4b17023SJohn Marino {
2761e4b17023SJohn Marino   sbitmap_vector_free (antloc);
2762e4b17023SJohn Marino   sbitmap_vector_free (transp);
2763e4b17023SJohn Marino   sbitmap_vector_free (comp);
2764e4b17023SJohn Marino 
2765e4b17023SJohn Marino   sbitmap_vector_free (hoist_vbein);
2766e4b17023SJohn Marino   sbitmap_vector_free (hoist_vbeout);
2767e4b17023SJohn Marino 
2768e4b17023SJohn Marino   free_dominance_info (CDI_DOMINATORS);
2769e4b17023SJohn Marino }
2770e4b17023SJohn Marino 
2771e4b17023SJohn Marino /* Compute the very busy expressions at entry/exit from each block.
2772e4b17023SJohn Marino 
2773e4b17023SJohn Marino    An expression is very busy if all paths from a given point
2774e4b17023SJohn Marino    compute the expression.  */
2775e4b17023SJohn Marino 
2776e4b17023SJohn Marino static void
compute_code_hoist_vbeinout(void)2777e4b17023SJohn Marino compute_code_hoist_vbeinout (void)
2778e4b17023SJohn Marino {
2779e4b17023SJohn Marino   int changed, passes;
2780e4b17023SJohn Marino   basic_block bb;
2781e4b17023SJohn Marino 
2782e4b17023SJohn Marino   sbitmap_vector_zero (hoist_vbeout, last_basic_block);
2783e4b17023SJohn Marino   sbitmap_vector_zero (hoist_vbein, last_basic_block);
2784e4b17023SJohn Marino 
2785e4b17023SJohn Marino   passes = 0;
2786e4b17023SJohn Marino   changed = 1;
2787e4b17023SJohn Marino 
2788e4b17023SJohn Marino   while (changed)
2789e4b17023SJohn Marino     {
2790e4b17023SJohn Marino       changed = 0;
2791e4b17023SJohn Marino 
2792e4b17023SJohn Marino       /* We scan the blocks in the reverse order to speed up
2793e4b17023SJohn Marino 	 the convergence.  */
2794e4b17023SJohn Marino       FOR_EACH_BB_REVERSE (bb)
2795e4b17023SJohn Marino 	{
2796e4b17023SJohn Marino 	  if (bb->next_bb != EXIT_BLOCK_PTR)
2797e4b17023SJohn Marino 	    {
2798e4b17023SJohn Marino 	      sbitmap_intersection_of_succs (hoist_vbeout[bb->index],
2799e4b17023SJohn Marino 					     hoist_vbein, bb->index);
2800e4b17023SJohn Marino 
2801e4b17023SJohn Marino 	      /* Include expressions in VBEout that are calculated
2802e4b17023SJohn Marino 		 in BB and available at its end.  */
2803e4b17023SJohn Marino 	      sbitmap_a_or_b (hoist_vbeout[bb->index],
2804e4b17023SJohn Marino 			      hoist_vbeout[bb->index], comp[bb->index]);
2805e4b17023SJohn Marino 	    }
2806e4b17023SJohn Marino 
2807e4b17023SJohn Marino 	  changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index],
2808e4b17023SJohn Marino 					      antloc[bb->index],
2809e4b17023SJohn Marino 					      hoist_vbeout[bb->index],
2810e4b17023SJohn Marino 					      transp[bb->index]);
2811e4b17023SJohn Marino 	}
2812e4b17023SJohn Marino 
2813e4b17023SJohn Marino       passes++;
2814e4b17023SJohn Marino     }
2815e4b17023SJohn Marino 
2816e4b17023SJohn Marino   if (dump_file)
2817e4b17023SJohn Marino     {
2818e4b17023SJohn Marino       fprintf (dump_file, "hoisting vbeinout computation: %d passes\n", passes);
2819e4b17023SJohn Marino 
2820e4b17023SJohn Marino       FOR_EACH_BB (bb)
2821e4b17023SJohn Marino         {
2822e4b17023SJohn Marino 	  fprintf (dump_file, "vbein (%d): ", bb->index);
2823e4b17023SJohn Marino 	  dump_sbitmap_file (dump_file, hoist_vbein[bb->index]);
2824e4b17023SJohn Marino 	  fprintf (dump_file, "vbeout(%d): ", bb->index);
2825e4b17023SJohn Marino 	  dump_sbitmap_file (dump_file, hoist_vbeout[bb->index]);
2826e4b17023SJohn Marino 	}
2827e4b17023SJohn Marino     }
2828e4b17023SJohn Marino }
2829e4b17023SJohn Marino 
2830e4b17023SJohn Marino /* Top level routine to do the dataflow analysis needed by code hoisting.  */
2831e4b17023SJohn Marino 
2832e4b17023SJohn Marino static void
compute_code_hoist_data(void)2833e4b17023SJohn Marino compute_code_hoist_data (void)
2834e4b17023SJohn Marino {
2835e4b17023SJohn Marino   compute_local_properties (transp, comp, antloc, &expr_hash_table);
2836e4b17023SJohn Marino   prune_expressions (false);
2837e4b17023SJohn Marino   compute_code_hoist_vbeinout ();
2838e4b17023SJohn Marino   calculate_dominance_info (CDI_DOMINATORS);
2839e4b17023SJohn Marino   if (dump_file)
2840e4b17023SJohn Marino     fprintf (dump_file, "\n");
2841e4b17023SJohn Marino }
2842e4b17023SJohn Marino 
2843e4b17023SJohn Marino /* Determine if the expression identified by EXPR_INDEX would
2844e4b17023SJohn Marino    reach BB unimpared if it was placed at the end of EXPR_BB.
2845e4b17023SJohn Marino    Stop the search if the expression would need to be moved more
2846e4b17023SJohn Marino    than DISTANCE instructions.
2847e4b17023SJohn Marino 
2848e4b17023SJohn Marino    It's unclear exactly what Muchnick meant by "unimpared".  It seems
2849e4b17023SJohn Marino    to me that the expression must either be computed or transparent in
2850e4b17023SJohn Marino    *every* block in the path(s) from EXPR_BB to BB.  Any other definition
2851e4b17023SJohn Marino    would allow the expression to be hoisted out of loops, even if
2852e4b17023SJohn Marino    the expression wasn't a loop invariant.
2853e4b17023SJohn Marino 
2854e4b17023SJohn Marino    Contrast this to reachability for PRE where an expression is
2855e4b17023SJohn Marino    considered reachable if *any* path reaches instead of *all*
2856e4b17023SJohn Marino    paths.  */
2857e4b17023SJohn Marino 
2858e4b17023SJohn Marino static int
hoist_expr_reaches_here_p(basic_block expr_bb,int expr_index,basic_block bb,char * visited,int distance,int * bb_size)2859e4b17023SJohn Marino hoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb,
2860e4b17023SJohn Marino 			   char *visited, int distance, int *bb_size)
2861e4b17023SJohn Marino {
2862e4b17023SJohn Marino   edge pred;
2863e4b17023SJohn Marino   edge_iterator ei;
2864e4b17023SJohn Marino   int visited_allocated_locally = 0;
2865e4b17023SJohn Marino 
2866e4b17023SJohn Marino   /* Terminate the search if distance, for which EXPR is allowed to move,
2867e4b17023SJohn Marino      is exhausted.  */
2868e4b17023SJohn Marino   if (distance > 0)
2869e4b17023SJohn Marino     {
2870e4b17023SJohn Marino       distance -= bb_size[bb->index];
2871e4b17023SJohn Marino 
2872e4b17023SJohn Marino       if (distance <= 0)
2873e4b17023SJohn Marino 	return 0;
2874e4b17023SJohn Marino     }
2875e4b17023SJohn Marino   else
2876e4b17023SJohn Marino     gcc_assert (distance == 0);
2877e4b17023SJohn Marino 
2878e4b17023SJohn Marino   if (visited == NULL)
2879e4b17023SJohn Marino     {
2880e4b17023SJohn Marino       visited_allocated_locally = 1;
2881e4b17023SJohn Marino       visited = XCNEWVEC (char, last_basic_block);
2882e4b17023SJohn Marino     }
2883e4b17023SJohn Marino 
2884e4b17023SJohn Marino   FOR_EACH_EDGE (pred, ei, bb->preds)
2885e4b17023SJohn Marino     {
2886e4b17023SJohn Marino       basic_block pred_bb = pred->src;
2887e4b17023SJohn Marino 
2888e4b17023SJohn Marino       if (pred->src == ENTRY_BLOCK_PTR)
2889e4b17023SJohn Marino 	break;
2890e4b17023SJohn Marino       else if (pred_bb == expr_bb)
2891e4b17023SJohn Marino 	continue;
2892e4b17023SJohn Marino       else if (visited[pred_bb->index])
2893e4b17023SJohn Marino 	continue;
2894e4b17023SJohn Marino 
2895e4b17023SJohn Marino       else if (! TEST_BIT (transp[pred_bb->index], expr_index))
2896e4b17023SJohn Marino 	break;
2897e4b17023SJohn Marino 
2898e4b17023SJohn Marino       /* Not killed.  */
2899e4b17023SJohn Marino       else
2900e4b17023SJohn Marino 	{
2901e4b17023SJohn Marino 	  visited[pred_bb->index] = 1;
2902e4b17023SJohn Marino 	  if (! hoist_expr_reaches_here_p (expr_bb, expr_index, pred_bb,
2903e4b17023SJohn Marino 					   visited, distance, bb_size))
2904e4b17023SJohn Marino 	    break;
2905e4b17023SJohn Marino 	}
2906e4b17023SJohn Marino     }
2907e4b17023SJohn Marino   if (visited_allocated_locally)
2908e4b17023SJohn Marino     free (visited);
2909e4b17023SJohn Marino 
2910e4b17023SJohn Marino   return (pred == NULL);
2911e4b17023SJohn Marino }
2912e4b17023SJohn Marino 
2913e4b17023SJohn Marino /* Find occurence in BB.  */
2914e4b17023SJohn Marino 
2915e4b17023SJohn Marino static struct occr *
find_occr_in_bb(struct occr * occr,basic_block bb)2916e4b17023SJohn Marino find_occr_in_bb (struct occr *occr, basic_block bb)
2917e4b17023SJohn Marino {
2918e4b17023SJohn Marino   /* Find the right occurrence of this expression.  */
2919e4b17023SJohn Marino   while (occr && BLOCK_FOR_INSN (occr->insn) != bb)
2920e4b17023SJohn Marino     occr = occr->next;
2921e4b17023SJohn Marino 
2922e4b17023SJohn Marino   return occr;
2923e4b17023SJohn Marino }
2924e4b17023SJohn Marino 
2925e4b17023SJohn Marino /* Actually perform code hoisting.  */
2926e4b17023SJohn Marino 
2927e4b17023SJohn Marino static int
hoist_code(void)2928e4b17023SJohn Marino hoist_code (void)
2929e4b17023SJohn Marino {
2930e4b17023SJohn Marino   basic_block bb, dominated;
2931e4b17023SJohn Marino   VEC (basic_block, heap) *dom_tree_walk;
2932e4b17023SJohn Marino   unsigned int dom_tree_walk_index;
2933e4b17023SJohn Marino   VEC (basic_block, heap) *domby;
2934e4b17023SJohn Marino   unsigned int i,j;
2935e4b17023SJohn Marino   struct expr **index_map;
2936e4b17023SJohn Marino   struct expr *expr;
2937e4b17023SJohn Marino   int *to_bb_head;
2938e4b17023SJohn Marino   int *bb_size;
2939e4b17023SJohn Marino   int changed = 0;
2940e4b17023SJohn Marino 
2941e4b17023SJohn Marino   /* Compute a mapping from expression number (`bitmap_index') to
2942e4b17023SJohn Marino      hash table entry.  */
2943e4b17023SJohn Marino 
2944e4b17023SJohn Marino   index_map = XCNEWVEC (struct expr *, expr_hash_table.n_elems);
2945e4b17023SJohn Marino   for (i = 0; i < expr_hash_table.size; i++)
2946e4b17023SJohn Marino     for (expr = expr_hash_table.table[i]; expr; expr = expr->next_same_hash)
2947e4b17023SJohn Marino       index_map[expr->bitmap_index] = expr;
2948e4b17023SJohn Marino 
2949e4b17023SJohn Marino   /* Calculate sizes of basic blocks and note how far
2950e4b17023SJohn Marino      each instruction is from the start of its block.  We then use this
2951e4b17023SJohn Marino      data to restrict distance an expression can travel.  */
2952e4b17023SJohn Marino 
2953e4b17023SJohn Marino   to_bb_head = XCNEWVEC (int, get_max_uid ());
2954e4b17023SJohn Marino   bb_size = XCNEWVEC (int, last_basic_block);
2955e4b17023SJohn Marino 
2956e4b17023SJohn Marino   FOR_EACH_BB (bb)
2957e4b17023SJohn Marino     {
2958e4b17023SJohn Marino       rtx insn;
2959e4b17023SJohn Marino       int to_head;
2960e4b17023SJohn Marino 
2961e4b17023SJohn Marino       to_head = 0;
2962e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
2963e4b17023SJohn Marino 	{
2964e4b17023SJohn Marino 	  /* Don't count debug instructions to avoid them affecting
2965e4b17023SJohn Marino 	     decision choices.  */
2966e4b17023SJohn Marino 	  if (NONDEBUG_INSN_P (insn))
2967e4b17023SJohn Marino 	    to_bb_head[INSN_UID (insn)] = to_head++;
2968e4b17023SJohn Marino 	}
2969e4b17023SJohn Marino 
2970e4b17023SJohn Marino       bb_size[bb->index] = to_head;
2971e4b17023SJohn Marino     }
2972e4b17023SJohn Marino 
2973e4b17023SJohn Marino   gcc_assert (EDGE_COUNT (ENTRY_BLOCK_PTR->succs) == 1
2974e4b17023SJohn Marino 	      && (EDGE_SUCC (ENTRY_BLOCK_PTR, 0)->dest
2975e4b17023SJohn Marino 		  == ENTRY_BLOCK_PTR->next_bb));
2976e4b17023SJohn Marino 
2977e4b17023SJohn Marino   dom_tree_walk = get_all_dominated_blocks (CDI_DOMINATORS,
2978e4b17023SJohn Marino 					    ENTRY_BLOCK_PTR->next_bb);
2979e4b17023SJohn Marino 
2980e4b17023SJohn Marino   /* Walk over each basic block looking for potentially hoistable
2981e4b17023SJohn Marino      expressions, nothing gets hoisted from the entry block.  */
2982e4b17023SJohn Marino   FOR_EACH_VEC_ELT (basic_block, dom_tree_walk, dom_tree_walk_index, bb)
2983e4b17023SJohn Marino     {
2984e4b17023SJohn Marino       domby = get_dominated_to_depth (CDI_DOMINATORS, bb, MAX_HOIST_DEPTH);
2985e4b17023SJohn Marino 
2986e4b17023SJohn Marino       if (VEC_length (basic_block, domby) == 0)
2987e4b17023SJohn Marino 	continue;
2988e4b17023SJohn Marino 
2989e4b17023SJohn Marino       /* Examine each expression that is very busy at the exit of this
2990e4b17023SJohn Marino 	 block.  These are the potentially hoistable expressions.  */
2991e4b17023SJohn Marino       for (i = 0; i < hoist_vbeout[bb->index]->n_bits; i++)
2992e4b17023SJohn Marino 	{
2993e4b17023SJohn Marino 	  if (TEST_BIT (hoist_vbeout[bb->index], i))
2994e4b17023SJohn Marino 	    {
2995e4b17023SJohn Marino 	      /* Current expression.  */
2996e4b17023SJohn Marino 	      struct expr *expr = index_map[i];
2997e4b17023SJohn Marino 	      /* Number of occurences of EXPR that can be hoisted to BB.  */
2998e4b17023SJohn Marino 	      int hoistable = 0;
2999e4b17023SJohn Marino 	      /* Basic blocks that have occurences reachable from BB.  */
3000e4b17023SJohn Marino 	      bitmap_head _from_bbs, *from_bbs = &_from_bbs;
3001e4b17023SJohn Marino 	      /* Occurences reachable from BB.  */
3002e4b17023SJohn Marino 	      VEC (occr_t, heap) *occrs_to_hoist = NULL;
3003e4b17023SJohn Marino 	      /* We want to insert the expression into BB only once, so
3004e4b17023SJohn Marino 		 note when we've inserted it.  */
3005e4b17023SJohn Marino 	      int insn_inserted_p;
3006e4b17023SJohn Marino 	      occr_t occr;
3007e4b17023SJohn Marino 
3008e4b17023SJohn Marino 	      bitmap_initialize (from_bbs, 0);
3009e4b17023SJohn Marino 
3010e4b17023SJohn Marino 	      /* If an expression is computed in BB and is available at end of
3011e4b17023SJohn Marino 		 BB, hoist all occurences dominated by BB to BB.  */
3012e4b17023SJohn Marino 	      if (TEST_BIT (comp[bb->index], i))
3013e4b17023SJohn Marino 		{
3014e4b17023SJohn Marino 		  occr = find_occr_in_bb (expr->antic_occr, bb);
3015e4b17023SJohn Marino 
3016e4b17023SJohn Marino 		  if (occr)
3017e4b17023SJohn Marino 		    {
3018e4b17023SJohn Marino 		      /* An occurence might've been already deleted
3019e4b17023SJohn Marino 			 while processing a dominator of BB.  */
3020e4b17023SJohn Marino 		      if (!occr->deleted_p)
3021e4b17023SJohn Marino 			{
3022e4b17023SJohn Marino 			  gcc_assert (NONDEBUG_INSN_P (occr->insn));
3023e4b17023SJohn Marino 			  hoistable++;
3024e4b17023SJohn Marino 			}
3025e4b17023SJohn Marino 		    }
3026e4b17023SJohn Marino 		  else
3027e4b17023SJohn Marino 		    hoistable++;
3028e4b17023SJohn Marino 		}
3029e4b17023SJohn Marino 
3030e4b17023SJohn Marino 	      /* We've found a potentially hoistable expression, now
3031e4b17023SJohn Marino 		 we look at every block BB dominates to see if it
3032e4b17023SJohn Marino 		 computes the expression.  */
3033e4b17023SJohn Marino 	      FOR_EACH_VEC_ELT (basic_block, domby, j, dominated)
3034e4b17023SJohn Marino 		{
3035e4b17023SJohn Marino 		  int max_distance;
3036e4b17023SJohn Marino 
3037e4b17023SJohn Marino 		  /* Ignore self dominance.  */
3038e4b17023SJohn Marino 		  if (bb == dominated)
3039e4b17023SJohn Marino 		    continue;
3040e4b17023SJohn Marino 		  /* We've found a dominated block, now see if it computes
3041e4b17023SJohn Marino 		     the busy expression and whether or not moving that
3042e4b17023SJohn Marino 		     expression to the "beginning" of that block is safe.  */
3043e4b17023SJohn Marino 		  if (!TEST_BIT (antloc[dominated->index], i))
3044e4b17023SJohn Marino 		    continue;
3045e4b17023SJohn Marino 
3046e4b17023SJohn Marino 		  occr = find_occr_in_bb (expr->antic_occr, dominated);
3047e4b17023SJohn Marino 		  gcc_assert (occr);
3048e4b17023SJohn Marino 
3049e4b17023SJohn Marino 		  /* An occurence might've been already deleted
3050e4b17023SJohn Marino 		     while processing a dominator of BB.  */
3051e4b17023SJohn Marino 		  if (occr->deleted_p)
3052e4b17023SJohn Marino 		    continue;
3053e4b17023SJohn Marino 		  gcc_assert (NONDEBUG_INSN_P (occr->insn));
3054e4b17023SJohn Marino 
3055e4b17023SJohn Marino 		  max_distance = expr->max_distance;
3056e4b17023SJohn Marino 		  if (max_distance > 0)
3057e4b17023SJohn Marino 		    /* Adjust MAX_DISTANCE to account for the fact that
3058e4b17023SJohn Marino 		       OCCR won't have to travel all of DOMINATED, but
3059e4b17023SJohn Marino 		       only part of it.  */
3060e4b17023SJohn Marino 		    max_distance += (bb_size[dominated->index]
3061e4b17023SJohn Marino 				     - to_bb_head[INSN_UID (occr->insn)]);
3062e4b17023SJohn Marino 
3063e4b17023SJohn Marino 		  /* Note if the expression would reach the dominated block
3064e4b17023SJohn Marino 		     unimpared if it was placed at the end of BB.
3065e4b17023SJohn Marino 
3066e4b17023SJohn Marino 		     Keep track of how many times this expression is hoistable
3067e4b17023SJohn Marino 		     from a dominated block into BB.  */
3068e4b17023SJohn Marino 		  if (hoist_expr_reaches_here_p (bb, i, dominated, NULL,
3069e4b17023SJohn Marino 						 max_distance, bb_size))
3070e4b17023SJohn Marino 		    {
3071e4b17023SJohn Marino 		      hoistable++;
3072e4b17023SJohn Marino 		      VEC_safe_push (occr_t, heap,
3073e4b17023SJohn Marino 				     occrs_to_hoist, occr);
3074e4b17023SJohn Marino 		      bitmap_set_bit (from_bbs, dominated->index);
3075e4b17023SJohn Marino 		    }
3076e4b17023SJohn Marino 		}
3077e4b17023SJohn Marino 
3078e4b17023SJohn Marino 	      /* If we found more than one hoistable occurrence of this
3079e4b17023SJohn Marino 		 expression, then note it in the vector of expressions to
3080e4b17023SJohn Marino 		 hoist.  It makes no sense to hoist things which are computed
3081e4b17023SJohn Marino 		 in only one BB, and doing so tends to pessimize register
3082e4b17023SJohn Marino 		 allocation.  One could increase this value to try harder
3083e4b17023SJohn Marino 		 to avoid any possible code expansion due to register
3084e4b17023SJohn Marino 		 allocation issues; however experiments have shown that
3085e4b17023SJohn Marino 		 the vast majority of hoistable expressions are only movable
3086e4b17023SJohn Marino 		 from two successors, so raising this threshold is likely
3087e4b17023SJohn Marino 		 to nullify any benefit we get from code hoisting.  */
3088e4b17023SJohn Marino 	      if (hoistable > 1 && dbg_cnt (hoist_insn))
3089e4b17023SJohn Marino 		{
3090e4b17023SJohn Marino 		  /* If (hoistable != VEC_length), then there is
3091e4b17023SJohn Marino 		     an occurence of EXPR in BB itself.  Don't waste
3092e4b17023SJohn Marino 		     time looking for LCA in this case.  */
3093e4b17023SJohn Marino 		  if ((unsigned) hoistable
3094e4b17023SJohn Marino 		      == VEC_length (occr_t, occrs_to_hoist))
3095e4b17023SJohn Marino 		    {
3096e4b17023SJohn Marino 		      basic_block lca;
3097e4b17023SJohn Marino 
3098e4b17023SJohn Marino 		      lca = nearest_common_dominator_for_set (CDI_DOMINATORS,
3099e4b17023SJohn Marino 							      from_bbs);
3100e4b17023SJohn Marino 		      if (lca != bb)
3101e4b17023SJohn Marino 			/* Punt, it's better to hoist these occurences to
3102e4b17023SJohn Marino 			   LCA.  */
3103e4b17023SJohn Marino 			VEC_free (occr_t, heap, occrs_to_hoist);
3104e4b17023SJohn Marino 		    }
3105e4b17023SJohn Marino 		}
3106e4b17023SJohn Marino 	      else
3107e4b17023SJohn Marino 		/* Punt, no point hoisting a single occurence.  */
3108e4b17023SJohn Marino 		VEC_free (occr_t, heap, occrs_to_hoist);
3109e4b17023SJohn Marino 
3110e4b17023SJohn Marino 	      insn_inserted_p = 0;
3111e4b17023SJohn Marino 
3112e4b17023SJohn Marino 	      /* Walk through occurences of I'th expressions we want
3113e4b17023SJohn Marino 		 to hoist to BB and make the transformations.  */
3114e4b17023SJohn Marino 	      FOR_EACH_VEC_ELT (occr_t, occrs_to_hoist, j, occr)
3115e4b17023SJohn Marino 		{
3116e4b17023SJohn Marino 		  rtx insn;
3117e4b17023SJohn Marino 		  rtx set;
3118e4b17023SJohn Marino 
3119e4b17023SJohn Marino 		  gcc_assert (!occr->deleted_p);
3120e4b17023SJohn Marino 
3121e4b17023SJohn Marino 		  insn = occr->insn;
3122e4b17023SJohn Marino 		  set = single_set (insn);
3123e4b17023SJohn Marino 		  gcc_assert (set);
3124e4b17023SJohn Marino 
3125e4b17023SJohn Marino 		  /* Create a pseudo-reg to store the result of reaching
3126e4b17023SJohn Marino 		     expressions into.  Get the mode for the new pseudo
3127e4b17023SJohn Marino 		     from the mode of the original destination pseudo.
3128e4b17023SJohn Marino 
3129e4b17023SJohn Marino 		     It is important to use new pseudos whenever we
3130e4b17023SJohn Marino 		     emit a set.  This will allow reload to use
3131e4b17023SJohn Marino 		     rematerialization for such registers.  */
3132e4b17023SJohn Marino 		  if (!insn_inserted_p)
3133e4b17023SJohn Marino 		    expr->reaching_reg
3134e4b17023SJohn Marino 		      = gen_reg_rtx_and_attrs (SET_DEST (set));
3135e4b17023SJohn Marino 
3136e4b17023SJohn Marino 		  gcse_emit_move_after (SET_DEST (set), expr->reaching_reg,
3137e4b17023SJohn Marino 					insn);
3138e4b17023SJohn Marino 		  delete_insn (insn);
3139e4b17023SJohn Marino 		  occr->deleted_p = 1;
3140e4b17023SJohn Marino 		  changed = 1;
3141e4b17023SJohn Marino 		  gcse_subst_count++;
3142e4b17023SJohn Marino 
3143e4b17023SJohn Marino 		  if (!insn_inserted_p)
3144e4b17023SJohn Marino 		    {
3145e4b17023SJohn Marino 		      insert_insn_end_basic_block (expr, bb);
3146e4b17023SJohn Marino 		      insn_inserted_p = 1;
3147e4b17023SJohn Marino 		    }
3148e4b17023SJohn Marino 		}
3149e4b17023SJohn Marino 
3150e4b17023SJohn Marino 	      VEC_free (occr_t, heap, occrs_to_hoist);
3151e4b17023SJohn Marino 	      bitmap_clear (from_bbs);
3152e4b17023SJohn Marino 	    }
3153e4b17023SJohn Marino 	}
3154e4b17023SJohn Marino       VEC_free (basic_block, heap, domby);
3155e4b17023SJohn Marino     }
3156e4b17023SJohn Marino 
3157e4b17023SJohn Marino   VEC_free (basic_block, heap, dom_tree_walk);
3158e4b17023SJohn Marino   free (bb_size);
3159e4b17023SJohn Marino   free (to_bb_head);
3160e4b17023SJohn Marino   free (index_map);
3161e4b17023SJohn Marino 
3162e4b17023SJohn Marino   return changed;
3163e4b17023SJohn Marino }
3164e4b17023SJohn Marino 
3165e4b17023SJohn Marino /* Top level routine to perform one code hoisting (aka unification) pass
3166e4b17023SJohn Marino 
3167e4b17023SJohn Marino    Return nonzero if a change was made.  */
3168e4b17023SJohn Marino 
3169e4b17023SJohn Marino static int
one_code_hoisting_pass(void)3170e4b17023SJohn Marino one_code_hoisting_pass (void)
3171e4b17023SJohn Marino {
3172e4b17023SJohn Marino   int changed = 0;
3173e4b17023SJohn Marino 
3174e4b17023SJohn Marino   gcse_subst_count = 0;
3175e4b17023SJohn Marino   gcse_create_count = 0;
3176e4b17023SJohn Marino 
3177e4b17023SJohn Marino   /* Return if there's nothing to do, or it is too expensive.  */
3178e4b17023SJohn Marino   if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1
3179e4b17023SJohn Marino       || is_too_expensive (_("GCSE disabled")))
3180e4b17023SJohn Marino     return 0;
3181e4b17023SJohn Marino 
3182e4b17023SJohn Marino   doing_code_hoisting_p = true;
3183e4b17023SJohn Marino 
3184e4b17023SJohn Marino   /* We need alias.  */
3185e4b17023SJohn Marino   init_alias_analysis ();
3186e4b17023SJohn Marino 
3187e4b17023SJohn Marino   bytes_used = 0;
3188e4b17023SJohn Marino   gcc_obstack_init (&gcse_obstack);
3189e4b17023SJohn Marino   alloc_gcse_mem ();
3190e4b17023SJohn Marino 
3191e4b17023SJohn Marino   alloc_hash_table (&expr_hash_table);
3192e4b17023SJohn Marino   compute_hash_table (&expr_hash_table);
3193e4b17023SJohn Marino   if (dump_file)
3194e4b17023SJohn Marino     dump_hash_table (dump_file, "Code Hosting Expressions", &expr_hash_table);
3195e4b17023SJohn Marino 
3196e4b17023SJohn Marino   if (expr_hash_table.n_elems > 0)
3197e4b17023SJohn Marino     {
3198e4b17023SJohn Marino       alloc_code_hoist_mem (last_basic_block, expr_hash_table.n_elems);
3199e4b17023SJohn Marino       compute_code_hoist_data ();
3200e4b17023SJohn Marino       changed = hoist_code ();
3201e4b17023SJohn Marino       free_code_hoist_mem ();
3202e4b17023SJohn Marino     }
3203e4b17023SJohn Marino 
3204e4b17023SJohn Marino   free_hash_table (&expr_hash_table);
3205e4b17023SJohn Marino   free_gcse_mem ();
3206e4b17023SJohn Marino   obstack_free (&gcse_obstack, NULL);
3207e4b17023SJohn Marino 
3208e4b17023SJohn Marino   /* We are finished with alias.  */
3209e4b17023SJohn Marino   end_alias_analysis ();
3210e4b17023SJohn Marino 
3211e4b17023SJohn Marino   if (dump_file)
3212e4b17023SJohn Marino     {
3213e4b17023SJohn Marino       fprintf (dump_file, "HOIST of %s, %d basic blocks, %d bytes needed, ",
3214e4b17023SJohn Marino 	       current_function_name (), n_basic_blocks, bytes_used);
3215e4b17023SJohn Marino       fprintf (dump_file, "%d substs, %d insns created\n",
3216e4b17023SJohn Marino 	       gcse_subst_count, gcse_create_count);
3217e4b17023SJohn Marino     }
3218e4b17023SJohn Marino 
3219e4b17023SJohn Marino   doing_code_hoisting_p = false;
3220e4b17023SJohn Marino 
3221e4b17023SJohn Marino   return changed;
3222e4b17023SJohn Marino }
3223e4b17023SJohn Marino 
3224e4b17023SJohn Marino /*  Here we provide the things required to do store motion towards the exit.
3225e4b17023SJohn Marino     In order for this to be effective, gcse also needed to be taught how to
3226e4b17023SJohn Marino     move a load when it is killed only by a store to itself.
3227e4b17023SJohn Marino 
3228e4b17023SJohn Marino 	    int i;
3229e4b17023SJohn Marino 	    float a[10];
3230e4b17023SJohn Marino 
3231e4b17023SJohn Marino 	    void foo(float scale)
3232e4b17023SJohn Marino 	    {
3233e4b17023SJohn Marino 	      for (i=0; i<10; i++)
3234e4b17023SJohn Marino 		a[i] *= scale;
3235e4b17023SJohn Marino 	    }
3236e4b17023SJohn Marino 
3237e4b17023SJohn Marino     'i' is both loaded and stored to in the loop. Normally, gcse cannot move
3238e4b17023SJohn Marino     the load out since its live around the loop, and stored at the bottom
3239e4b17023SJohn Marino     of the loop.
3240e4b17023SJohn Marino 
3241e4b17023SJohn Marino       The 'Load Motion' referred to and implemented in this file is
3242e4b17023SJohn Marino     an enhancement to gcse which when using edge based LCM, recognizes
3243e4b17023SJohn Marino     this situation and allows gcse to move the load out of the loop.
3244e4b17023SJohn Marino 
3245e4b17023SJohn Marino       Once gcse has hoisted the load, store motion can then push this
3246e4b17023SJohn Marino     load towards the exit, and we end up with no loads or stores of 'i'
3247e4b17023SJohn Marino     in the loop.  */
3248e4b17023SJohn Marino 
3249e4b17023SJohn Marino static hashval_t
pre_ldst_expr_hash(const void * p)3250e4b17023SJohn Marino pre_ldst_expr_hash (const void *p)
3251e4b17023SJohn Marino {
3252e4b17023SJohn Marino   int do_not_record_p = 0;
3253e4b17023SJohn Marino   const struct ls_expr *const x = (const struct ls_expr *) p;
3254e4b17023SJohn Marino   return
3255e4b17023SJohn Marino     hash_rtx (x->pattern, GET_MODE (x->pattern), &do_not_record_p, NULL, false);
3256e4b17023SJohn Marino }
3257e4b17023SJohn Marino 
3258e4b17023SJohn Marino static int
pre_ldst_expr_eq(const void * p1,const void * p2)3259e4b17023SJohn Marino pre_ldst_expr_eq (const void *p1, const void *p2)
3260e4b17023SJohn Marino {
3261e4b17023SJohn Marino   const struct ls_expr *const ptr1 = (const struct ls_expr *) p1,
3262e4b17023SJohn Marino     *const ptr2 = (const struct ls_expr *) p2;
3263e4b17023SJohn Marino   return expr_equiv_p (ptr1->pattern, ptr2->pattern);
3264e4b17023SJohn Marino }
3265e4b17023SJohn Marino 
3266e4b17023SJohn Marino /* This will search the ldst list for a matching expression. If it
3267e4b17023SJohn Marino    doesn't find one, we create one and initialize it.  */
3268e4b17023SJohn Marino 
3269e4b17023SJohn Marino static struct ls_expr *
ldst_entry(rtx x)3270e4b17023SJohn Marino ldst_entry (rtx x)
3271e4b17023SJohn Marino {
3272e4b17023SJohn Marino   int do_not_record_p = 0;
3273e4b17023SJohn Marino   struct ls_expr * ptr;
3274e4b17023SJohn Marino   unsigned int hash;
3275e4b17023SJohn Marino   void **slot;
3276e4b17023SJohn Marino   struct ls_expr e;
3277e4b17023SJohn Marino 
3278e4b17023SJohn Marino   hash = hash_rtx (x, GET_MODE (x), &do_not_record_p,
3279e4b17023SJohn Marino 		   NULL,  /*have_reg_qty=*/false);
3280e4b17023SJohn Marino 
3281e4b17023SJohn Marino   e.pattern = x;
3282e4b17023SJohn Marino   slot = htab_find_slot_with_hash (pre_ldst_table, &e, hash, INSERT);
3283e4b17023SJohn Marino   if (*slot)
3284e4b17023SJohn Marino     return (struct ls_expr *)*slot;
3285e4b17023SJohn Marino 
3286e4b17023SJohn Marino   ptr = XNEW (struct ls_expr);
3287e4b17023SJohn Marino 
3288e4b17023SJohn Marino   ptr->next         = pre_ldst_mems;
3289e4b17023SJohn Marino   ptr->expr         = NULL;
3290e4b17023SJohn Marino   ptr->pattern      = x;
3291e4b17023SJohn Marino   ptr->pattern_regs = NULL_RTX;
3292e4b17023SJohn Marino   ptr->loads        = NULL_RTX;
3293e4b17023SJohn Marino   ptr->stores       = NULL_RTX;
3294e4b17023SJohn Marino   ptr->reaching_reg = NULL_RTX;
3295e4b17023SJohn Marino   ptr->invalid      = 0;
3296e4b17023SJohn Marino   ptr->index        = 0;
3297e4b17023SJohn Marino   ptr->hash_index   = hash;
3298e4b17023SJohn Marino   pre_ldst_mems     = ptr;
3299e4b17023SJohn Marino   *slot = ptr;
3300e4b17023SJohn Marino 
3301e4b17023SJohn Marino   return ptr;
3302e4b17023SJohn Marino }
3303e4b17023SJohn Marino 
3304e4b17023SJohn Marino /* Free up an individual ldst entry.  */
3305e4b17023SJohn Marino 
3306e4b17023SJohn Marino static void
free_ldst_entry(struct ls_expr * ptr)3307e4b17023SJohn Marino free_ldst_entry (struct ls_expr * ptr)
3308e4b17023SJohn Marino {
3309e4b17023SJohn Marino   free_INSN_LIST_list (& ptr->loads);
3310e4b17023SJohn Marino   free_INSN_LIST_list (& ptr->stores);
3311e4b17023SJohn Marino 
3312e4b17023SJohn Marino   free (ptr);
3313e4b17023SJohn Marino }
3314e4b17023SJohn Marino 
3315e4b17023SJohn Marino /* Free up all memory associated with the ldst list.  */
3316e4b17023SJohn Marino 
3317e4b17023SJohn Marino static void
free_ld_motion_mems(void)3318e4b17023SJohn Marino free_ld_motion_mems (void)
3319e4b17023SJohn Marino {
3320e4b17023SJohn Marino   if (pre_ldst_table)
3321e4b17023SJohn Marino     htab_delete (pre_ldst_table);
3322e4b17023SJohn Marino   pre_ldst_table = NULL;
3323e4b17023SJohn Marino 
3324e4b17023SJohn Marino   while (pre_ldst_mems)
3325e4b17023SJohn Marino     {
3326e4b17023SJohn Marino       struct ls_expr * tmp = pre_ldst_mems;
3327e4b17023SJohn Marino 
3328e4b17023SJohn Marino       pre_ldst_mems = pre_ldst_mems->next;
3329e4b17023SJohn Marino 
3330e4b17023SJohn Marino       free_ldst_entry (tmp);
3331e4b17023SJohn Marino     }
3332e4b17023SJohn Marino 
3333e4b17023SJohn Marino   pre_ldst_mems = NULL;
3334e4b17023SJohn Marino }
3335e4b17023SJohn Marino 
3336e4b17023SJohn Marino /* Dump debugging info about the ldst list.  */
3337e4b17023SJohn Marino 
3338e4b17023SJohn Marino static void
print_ldst_list(FILE * file)3339e4b17023SJohn Marino print_ldst_list (FILE * file)
3340e4b17023SJohn Marino {
3341e4b17023SJohn Marino   struct ls_expr * ptr;
3342e4b17023SJohn Marino 
3343e4b17023SJohn Marino   fprintf (file, "LDST list: \n");
3344e4b17023SJohn Marino 
3345e4b17023SJohn Marino   for (ptr = pre_ldst_mems; ptr != NULL; ptr = ptr->next)
3346e4b17023SJohn Marino     {
3347e4b17023SJohn Marino       fprintf (file, "  Pattern (%3d): ", ptr->index);
3348e4b17023SJohn Marino 
3349e4b17023SJohn Marino       print_rtl (file, ptr->pattern);
3350e4b17023SJohn Marino 
3351e4b17023SJohn Marino       fprintf (file, "\n	 Loads : ");
3352e4b17023SJohn Marino 
3353e4b17023SJohn Marino       if (ptr->loads)
3354e4b17023SJohn Marino 	print_rtl (file, ptr->loads);
3355e4b17023SJohn Marino       else
3356e4b17023SJohn Marino 	fprintf (file, "(nil)");
3357e4b17023SJohn Marino 
3358e4b17023SJohn Marino       fprintf (file, "\n	Stores : ");
3359e4b17023SJohn Marino 
3360e4b17023SJohn Marino       if (ptr->stores)
3361e4b17023SJohn Marino 	print_rtl (file, ptr->stores);
3362e4b17023SJohn Marino       else
3363e4b17023SJohn Marino 	fprintf (file, "(nil)");
3364e4b17023SJohn Marino 
3365e4b17023SJohn Marino       fprintf (file, "\n\n");
3366e4b17023SJohn Marino     }
3367e4b17023SJohn Marino 
3368e4b17023SJohn Marino   fprintf (file, "\n");
3369e4b17023SJohn Marino }
3370e4b17023SJohn Marino 
3371e4b17023SJohn Marino /* Returns 1 if X is in the list of ldst only expressions.  */
3372e4b17023SJohn Marino 
3373e4b17023SJohn Marino static struct ls_expr *
find_rtx_in_ldst(rtx x)3374e4b17023SJohn Marino find_rtx_in_ldst (rtx x)
3375e4b17023SJohn Marino {
3376e4b17023SJohn Marino   struct ls_expr e;
3377e4b17023SJohn Marino   void **slot;
3378e4b17023SJohn Marino   if (!pre_ldst_table)
3379e4b17023SJohn Marino     return NULL;
3380e4b17023SJohn Marino   e.pattern = x;
3381e4b17023SJohn Marino   slot = htab_find_slot (pre_ldst_table, &e, NO_INSERT);
3382e4b17023SJohn Marino   if (!slot || ((struct ls_expr *)*slot)->invalid)
3383e4b17023SJohn Marino     return NULL;
3384e4b17023SJohn Marino   return (struct ls_expr *) *slot;
3385e4b17023SJohn Marino }
3386e4b17023SJohn Marino 
3387e4b17023SJohn Marino /* Load Motion for loads which only kill themselves.  */
3388e4b17023SJohn Marino 
3389e4b17023SJohn Marino /* Return true if x, a MEM, is a simple access with no side effects.
3390e4b17023SJohn Marino    These are the types of loads we consider for the ld_motion list,
3391e4b17023SJohn Marino    otherwise we let the usual aliasing take care of it.  */
3392e4b17023SJohn Marino 
3393e4b17023SJohn Marino static int
simple_mem(const_rtx x)3394e4b17023SJohn Marino simple_mem (const_rtx x)
3395e4b17023SJohn Marino {
3396e4b17023SJohn Marino   if (MEM_VOLATILE_P (x))
3397e4b17023SJohn Marino     return 0;
3398e4b17023SJohn Marino 
3399e4b17023SJohn Marino   if (GET_MODE (x) == BLKmode)
3400e4b17023SJohn Marino     return 0;
3401e4b17023SJohn Marino 
3402e4b17023SJohn Marino   /* If we are handling exceptions, we must be careful with memory references
3403e4b17023SJohn Marino      that may trap.  If we are not, the behavior is undefined, so we may just
3404e4b17023SJohn Marino      continue.  */
3405e4b17023SJohn Marino   if (cfun->can_throw_non_call_exceptions && may_trap_p (x))
3406e4b17023SJohn Marino     return 0;
3407e4b17023SJohn Marino 
3408e4b17023SJohn Marino   if (side_effects_p (x))
3409e4b17023SJohn Marino     return 0;
3410e4b17023SJohn Marino 
3411e4b17023SJohn Marino   /* Do not consider function arguments passed on stack.  */
3412e4b17023SJohn Marino   if (reg_mentioned_p (stack_pointer_rtx, x))
3413e4b17023SJohn Marino     return 0;
3414e4b17023SJohn Marino 
3415e4b17023SJohn Marino   if (flag_float_store && FLOAT_MODE_P (GET_MODE (x)))
3416e4b17023SJohn Marino     return 0;
3417e4b17023SJohn Marino 
3418e4b17023SJohn Marino   return 1;
3419e4b17023SJohn Marino }
3420e4b17023SJohn Marino 
3421e4b17023SJohn Marino /* Make sure there isn't a buried reference in this pattern anywhere.
3422e4b17023SJohn Marino    If there is, invalidate the entry for it since we're not capable
3423e4b17023SJohn Marino    of fixing it up just yet.. We have to be sure we know about ALL
3424e4b17023SJohn Marino    loads since the aliasing code will allow all entries in the
3425e4b17023SJohn Marino    ld_motion list to not-alias itself.  If we miss a load, we will get
3426e4b17023SJohn Marino    the wrong value since gcse might common it and we won't know to
3427e4b17023SJohn Marino    fix it up.  */
3428e4b17023SJohn Marino 
3429e4b17023SJohn Marino static void
invalidate_any_buried_refs(rtx x)3430e4b17023SJohn Marino invalidate_any_buried_refs (rtx x)
3431e4b17023SJohn Marino {
3432e4b17023SJohn Marino   const char * fmt;
3433e4b17023SJohn Marino   int i, j;
3434e4b17023SJohn Marino   struct ls_expr * ptr;
3435e4b17023SJohn Marino 
3436e4b17023SJohn Marino   /* Invalidate it in the list.  */
3437e4b17023SJohn Marino   if (MEM_P (x) && simple_mem (x))
3438e4b17023SJohn Marino     {
3439e4b17023SJohn Marino       ptr = ldst_entry (x);
3440e4b17023SJohn Marino       ptr->invalid = 1;
3441e4b17023SJohn Marino     }
3442e4b17023SJohn Marino 
3443e4b17023SJohn Marino   /* Recursively process the insn.  */
3444e4b17023SJohn Marino   fmt = GET_RTX_FORMAT (GET_CODE (x));
3445e4b17023SJohn Marino 
3446e4b17023SJohn Marino   for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
3447e4b17023SJohn Marino     {
3448e4b17023SJohn Marino       if (fmt[i] == 'e')
3449e4b17023SJohn Marino 	invalidate_any_buried_refs (XEXP (x, i));
3450e4b17023SJohn Marino       else if (fmt[i] == 'E')
3451e4b17023SJohn Marino 	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
3452e4b17023SJohn Marino 	  invalidate_any_buried_refs (XVECEXP (x, i, j));
3453e4b17023SJohn Marino     }
3454e4b17023SJohn Marino }
3455e4b17023SJohn Marino 
3456e4b17023SJohn Marino /* Find all the 'simple' MEMs which are used in LOADs and STORES.  Simple
3457e4b17023SJohn Marino    being defined as MEM loads and stores to symbols, with no side effects
3458e4b17023SJohn Marino    and no registers in the expression.  For a MEM destination, we also
3459e4b17023SJohn Marino    check that the insn is still valid if we replace the destination with a
3460e4b17023SJohn Marino    REG, as is done in update_ld_motion_stores.  If there are any uses/defs
3461e4b17023SJohn Marino    which don't match this criteria, they are invalidated and trimmed out
3462e4b17023SJohn Marino    later.  */
3463e4b17023SJohn Marino 
3464e4b17023SJohn Marino static void
compute_ld_motion_mems(void)3465e4b17023SJohn Marino compute_ld_motion_mems (void)
3466e4b17023SJohn Marino {
3467e4b17023SJohn Marino   struct ls_expr * ptr;
3468e4b17023SJohn Marino   basic_block bb;
3469e4b17023SJohn Marino   rtx insn;
3470e4b17023SJohn Marino 
3471e4b17023SJohn Marino   pre_ldst_mems = NULL;
3472e4b17023SJohn Marino   pre_ldst_table
3473e4b17023SJohn Marino     = htab_create (13, pre_ldst_expr_hash, pre_ldst_expr_eq, NULL);
3474e4b17023SJohn Marino 
3475e4b17023SJohn Marino   FOR_EACH_BB (bb)
3476e4b17023SJohn Marino     {
3477e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
3478e4b17023SJohn Marino 	{
3479e4b17023SJohn Marino 	  if (NONDEBUG_INSN_P (insn))
3480e4b17023SJohn Marino 	    {
3481e4b17023SJohn Marino 	      if (GET_CODE (PATTERN (insn)) == SET)
3482e4b17023SJohn Marino 		{
3483e4b17023SJohn Marino 		  rtx src = SET_SRC (PATTERN (insn));
3484e4b17023SJohn Marino 		  rtx dest = SET_DEST (PATTERN (insn));
3485e4b17023SJohn Marino 
3486e4b17023SJohn Marino 		  /* Check for a simple LOAD...  */
3487e4b17023SJohn Marino 		  if (MEM_P (src) && simple_mem (src))
3488e4b17023SJohn Marino 		    {
3489e4b17023SJohn Marino 		      ptr = ldst_entry (src);
3490e4b17023SJohn Marino 		      if (REG_P (dest))
3491e4b17023SJohn Marino 			ptr->loads = alloc_INSN_LIST (insn, ptr->loads);
3492e4b17023SJohn Marino 		      else
3493e4b17023SJohn Marino 			ptr->invalid = 1;
3494e4b17023SJohn Marino 		    }
3495e4b17023SJohn Marino 		  else
3496e4b17023SJohn Marino 		    {
3497e4b17023SJohn Marino 		      /* Make sure there isn't a buried load somewhere.  */
3498e4b17023SJohn Marino 		      invalidate_any_buried_refs (src);
3499e4b17023SJohn Marino 		    }
3500e4b17023SJohn Marino 
3501e4b17023SJohn Marino 		  /* Check for stores. Don't worry about aliased ones, they
3502e4b17023SJohn Marino 		     will block any movement we might do later. We only care
3503e4b17023SJohn Marino 		     about this exact pattern since those are the only
3504e4b17023SJohn Marino 		     circumstance that we will ignore the aliasing info.  */
3505e4b17023SJohn Marino 		  if (MEM_P (dest) && simple_mem (dest))
3506e4b17023SJohn Marino 		    {
3507e4b17023SJohn Marino 		      ptr = ldst_entry (dest);
3508e4b17023SJohn Marino 
3509e4b17023SJohn Marino 		      if (! MEM_P (src)
3510e4b17023SJohn Marino 			  && GET_CODE (src) != ASM_OPERANDS
3511e4b17023SJohn Marino 			  /* Check for REG manually since want_to_gcse_p
3512e4b17023SJohn Marino 			     returns 0 for all REGs.  */
3513e4b17023SJohn Marino 			  && can_assign_to_reg_without_clobbers_p (src))
3514e4b17023SJohn Marino 			ptr->stores = alloc_INSN_LIST (insn, ptr->stores);
3515e4b17023SJohn Marino 		      else
3516e4b17023SJohn Marino 			ptr->invalid = 1;
3517e4b17023SJohn Marino 		    }
3518e4b17023SJohn Marino 		}
3519e4b17023SJohn Marino 	      else
3520e4b17023SJohn Marino 		invalidate_any_buried_refs (PATTERN (insn));
3521e4b17023SJohn Marino 	    }
3522e4b17023SJohn Marino 	}
3523e4b17023SJohn Marino     }
3524e4b17023SJohn Marino }
3525e4b17023SJohn Marino 
3526e4b17023SJohn Marino /* Remove any references that have been either invalidated or are not in the
3527e4b17023SJohn Marino    expression list for pre gcse.  */
3528e4b17023SJohn Marino 
3529e4b17023SJohn Marino static void
trim_ld_motion_mems(void)3530e4b17023SJohn Marino trim_ld_motion_mems (void)
3531e4b17023SJohn Marino {
3532e4b17023SJohn Marino   struct ls_expr * * last = & pre_ldst_mems;
3533e4b17023SJohn Marino   struct ls_expr * ptr = pre_ldst_mems;
3534e4b17023SJohn Marino 
3535e4b17023SJohn Marino   while (ptr != NULL)
3536e4b17023SJohn Marino     {
3537e4b17023SJohn Marino       struct expr * expr;
3538e4b17023SJohn Marino 
3539e4b17023SJohn Marino       /* Delete if entry has been made invalid.  */
3540e4b17023SJohn Marino       if (! ptr->invalid)
3541e4b17023SJohn Marino 	{
3542e4b17023SJohn Marino 	  /* Delete if we cannot find this mem in the expression list.  */
3543e4b17023SJohn Marino 	  unsigned int hash = ptr->hash_index % expr_hash_table.size;
3544e4b17023SJohn Marino 
3545e4b17023SJohn Marino 	  for (expr = expr_hash_table.table[hash];
3546e4b17023SJohn Marino 	       expr != NULL;
3547e4b17023SJohn Marino 	       expr = expr->next_same_hash)
3548e4b17023SJohn Marino 	    if (expr_equiv_p (expr->expr, ptr->pattern))
3549e4b17023SJohn Marino 	      break;
3550e4b17023SJohn Marino 	}
3551e4b17023SJohn Marino       else
3552e4b17023SJohn Marino 	expr = (struct expr *) 0;
3553e4b17023SJohn Marino 
3554e4b17023SJohn Marino       if (expr)
3555e4b17023SJohn Marino 	{
3556e4b17023SJohn Marino 	  /* Set the expression field if we are keeping it.  */
3557e4b17023SJohn Marino 	  ptr->expr = expr;
3558e4b17023SJohn Marino 	  last = & ptr->next;
3559e4b17023SJohn Marino 	  ptr = ptr->next;
3560e4b17023SJohn Marino 	}
3561e4b17023SJohn Marino       else
3562e4b17023SJohn Marino 	{
3563e4b17023SJohn Marino 	  *last = ptr->next;
3564e4b17023SJohn Marino 	  htab_remove_elt_with_hash (pre_ldst_table, ptr, ptr->hash_index);
3565e4b17023SJohn Marino 	  free_ldst_entry (ptr);
3566e4b17023SJohn Marino 	  ptr = * last;
3567e4b17023SJohn Marino 	}
3568e4b17023SJohn Marino     }
3569e4b17023SJohn Marino 
3570e4b17023SJohn Marino   /* Show the world what we've found.  */
3571e4b17023SJohn Marino   if (dump_file && pre_ldst_mems != NULL)
3572e4b17023SJohn Marino     print_ldst_list (dump_file);
3573e4b17023SJohn Marino }
3574e4b17023SJohn Marino 
3575e4b17023SJohn Marino /* This routine will take an expression which we are replacing with
3576e4b17023SJohn Marino    a reaching register, and update any stores that are needed if
3577e4b17023SJohn Marino    that expression is in the ld_motion list.  Stores are updated by
3578e4b17023SJohn Marino    copying their SRC to the reaching register, and then storing
3579e4b17023SJohn Marino    the reaching register into the store location. These keeps the
3580e4b17023SJohn Marino    correct value in the reaching register for the loads.  */
3581e4b17023SJohn Marino 
3582e4b17023SJohn Marino static void
update_ld_motion_stores(struct expr * expr)3583e4b17023SJohn Marino update_ld_motion_stores (struct expr * expr)
3584e4b17023SJohn Marino {
3585e4b17023SJohn Marino   struct ls_expr * mem_ptr;
3586e4b17023SJohn Marino 
3587e4b17023SJohn Marino   if ((mem_ptr = find_rtx_in_ldst (expr->expr)))
3588e4b17023SJohn Marino     {
3589e4b17023SJohn Marino       /* We can try to find just the REACHED stores, but is shouldn't
3590e4b17023SJohn Marino 	 matter to set the reaching reg everywhere...  some might be
3591e4b17023SJohn Marino 	 dead and should be eliminated later.  */
3592e4b17023SJohn Marino 
3593e4b17023SJohn Marino       /* We replace (set mem expr) with (set reg expr) (set mem reg)
3594e4b17023SJohn Marino 	 where reg is the reaching reg used in the load.  We checked in
3595e4b17023SJohn Marino 	 compute_ld_motion_mems that we can replace (set mem expr) with
3596e4b17023SJohn Marino 	 (set reg expr) in that insn.  */
3597e4b17023SJohn Marino       rtx list = mem_ptr->stores;
3598e4b17023SJohn Marino 
3599e4b17023SJohn Marino       for ( ; list != NULL_RTX; list = XEXP (list, 1))
3600e4b17023SJohn Marino 	{
3601e4b17023SJohn Marino 	  rtx insn = XEXP (list, 0);
3602e4b17023SJohn Marino 	  rtx pat = PATTERN (insn);
3603e4b17023SJohn Marino 	  rtx src = SET_SRC (pat);
3604e4b17023SJohn Marino 	  rtx reg = expr->reaching_reg;
3605e4b17023SJohn Marino 	  rtx copy;
3606e4b17023SJohn Marino 
3607e4b17023SJohn Marino 	  /* If we've already copied it, continue.  */
3608e4b17023SJohn Marino 	  if (expr->reaching_reg == src)
3609e4b17023SJohn Marino 	    continue;
3610e4b17023SJohn Marino 
3611e4b17023SJohn Marino 	  if (dump_file)
3612e4b17023SJohn Marino 	    {
3613e4b17023SJohn Marino 	      fprintf (dump_file, "PRE:  store updated with reaching reg ");
3614e4b17023SJohn Marino 	      print_rtl (dump_file, reg);
3615e4b17023SJohn Marino 	      fprintf (dump_file, ":\n	");
3616e4b17023SJohn Marino 	      print_inline_rtx (dump_file, insn, 8);
3617e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
3618e4b17023SJohn Marino 	    }
3619e4b17023SJohn Marino 
3620e4b17023SJohn Marino 	  copy = gen_move_insn (reg, copy_rtx (SET_SRC (pat)));
3621e4b17023SJohn Marino 	  emit_insn_before (copy, insn);
3622e4b17023SJohn Marino 	  SET_SRC (pat) = reg;
3623e4b17023SJohn Marino 	  df_insn_rescan (insn);
3624e4b17023SJohn Marino 
3625e4b17023SJohn Marino 	  /* un-recognize this pattern since it's probably different now.  */
3626e4b17023SJohn Marino 	  INSN_CODE (insn) = -1;
3627e4b17023SJohn Marino 	  gcse_create_count++;
3628e4b17023SJohn Marino 	}
3629e4b17023SJohn Marino     }
3630e4b17023SJohn Marino }
3631e4b17023SJohn Marino 
3632e4b17023SJohn Marino /* Return true if the graph is too expensive to optimize. PASS is the
3633e4b17023SJohn Marino    optimization about to be performed.  */
3634e4b17023SJohn Marino 
3635e4b17023SJohn Marino static bool
is_too_expensive(const char * pass)3636e4b17023SJohn Marino is_too_expensive (const char *pass)
3637e4b17023SJohn Marino {
3638e4b17023SJohn Marino   /* Trying to perform global optimizations on flow graphs which have
3639e4b17023SJohn Marino      a high connectivity will take a long time and is unlikely to be
3640e4b17023SJohn Marino      particularly useful.
3641e4b17023SJohn Marino 
3642e4b17023SJohn Marino      In normal circumstances a cfg should have about twice as many
3643e4b17023SJohn Marino      edges as blocks.  But we do not want to punish small functions
3644e4b17023SJohn Marino      which have a couple switch statements.  Rather than simply
3645e4b17023SJohn Marino      threshold the number of blocks, uses something with a more
3646e4b17023SJohn Marino      graceful degradation.  */
3647e4b17023SJohn Marino   if (n_edges > 20000 + n_basic_blocks * 4)
3648e4b17023SJohn Marino     {
3649e4b17023SJohn Marino       warning (OPT_Wdisabled_optimization,
3650e4b17023SJohn Marino 	       "%s: %d basic blocks and %d edges/basic block",
3651e4b17023SJohn Marino 	       pass, n_basic_blocks, n_edges / n_basic_blocks);
3652e4b17023SJohn Marino 
3653e4b17023SJohn Marino       return true;
3654e4b17023SJohn Marino     }
3655e4b17023SJohn Marino 
3656e4b17023SJohn Marino   /* If allocating memory for the dataflow bitmaps would take up too much
3657e4b17023SJohn Marino      storage it's better just to disable the optimization.  */
3658e4b17023SJohn Marino   if ((n_basic_blocks
3659e4b17023SJohn Marino        * SBITMAP_SET_SIZE (max_reg_num ())
3660e4b17023SJohn Marino        * sizeof (SBITMAP_ELT_TYPE)) > MAX_GCSE_MEMORY)
3661e4b17023SJohn Marino     {
3662e4b17023SJohn Marino       warning (OPT_Wdisabled_optimization,
3663e4b17023SJohn Marino 	       "%s: %d basic blocks and %d registers",
3664e4b17023SJohn Marino 	       pass, n_basic_blocks, max_reg_num ());
3665e4b17023SJohn Marino 
3666e4b17023SJohn Marino       return true;
3667e4b17023SJohn Marino     }
3668e4b17023SJohn Marino 
3669e4b17023SJohn Marino   return false;
3670e4b17023SJohn Marino }
3671e4b17023SJohn Marino 
3672e4b17023SJohn Marino /* All the passes implemented in this file.  Each pass has its
3673e4b17023SJohn Marino    own gate and execute function, and at the end of the file a
3674e4b17023SJohn Marino    pass definition for passes.c.
3675e4b17023SJohn Marino 
3676e4b17023SJohn Marino    We do not construct an accurate cfg in functions which call
3677e4b17023SJohn Marino    setjmp, so none of these passes runs if the function calls
3678e4b17023SJohn Marino    setjmp.
3679e4b17023SJohn Marino    FIXME: Should just handle setjmp via REG_SETJMP notes.  */
3680e4b17023SJohn Marino 
3681e4b17023SJohn Marino static bool
gate_rtl_pre(void)3682e4b17023SJohn Marino gate_rtl_pre (void)
3683e4b17023SJohn Marino {
3684e4b17023SJohn Marino   return optimize > 0 && flag_gcse
3685e4b17023SJohn Marino     && !cfun->calls_setjmp
3686e4b17023SJohn Marino     && optimize_function_for_speed_p (cfun)
3687e4b17023SJohn Marino     && dbg_cnt (pre);
3688e4b17023SJohn Marino }
3689e4b17023SJohn Marino 
3690e4b17023SJohn Marino static unsigned int
execute_rtl_pre(void)3691e4b17023SJohn Marino execute_rtl_pre (void)
3692e4b17023SJohn Marino {
3693e4b17023SJohn Marino   int changed;
3694e4b17023SJohn Marino   delete_unreachable_blocks ();
3695e4b17023SJohn Marino   df_analyze ();
3696e4b17023SJohn Marino   changed = one_pre_gcse_pass ();
3697e4b17023SJohn Marino   flag_rerun_cse_after_global_opts |= changed;
3698e4b17023SJohn Marino   if (changed)
3699e4b17023SJohn Marino     cleanup_cfg (0);
3700e4b17023SJohn Marino   return 0;
3701e4b17023SJohn Marino }
3702e4b17023SJohn Marino 
3703e4b17023SJohn Marino static bool
gate_rtl_hoist(void)3704e4b17023SJohn Marino gate_rtl_hoist (void)
3705e4b17023SJohn Marino {
3706e4b17023SJohn Marino   return optimize > 0 && flag_gcse
3707e4b17023SJohn Marino     && !cfun->calls_setjmp
3708e4b17023SJohn Marino     /* It does not make sense to run code hoisting unless we are optimizing
3709e4b17023SJohn Marino        for code size -- it rarely makes programs faster, and can make then
3710e4b17023SJohn Marino        bigger if we did PRE (when optimizing for space, we don't run PRE).  */
3711e4b17023SJohn Marino     && optimize_function_for_size_p (cfun)
3712e4b17023SJohn Marino     && dbg_cnt (hoist);
3713e4b17023SJohn Marino }
3714e4b17023SJohn Marino 
3715e4b17023SJohn Marino static unsigned int
execute_rtl_hoist(void)3716e4b17023SJohn Marino execute_rtl_hoist (void)
3717e4b17023SJohn Marino {
3718e4b17023SJohn Marino   int changed;
3719e4b17023SJohn Marino   delete_unreachable_blocks ();
3720e4b17023SJohn Marino   df_analyze ();
3721e4b17023SJohn Marino   changed = one_code_hoisting_pass ();
3722e4b17023SJohn Marino   flag_rerun_cse_after_global_opts |= changed;
3723e4b17023SJohn Marino   if (changed)
3724e4b17023SJohn Marino     cleanup_cfg (0);
3725e4b17023SJohn Marino   return 0;
3726e4b17023SJohn Marino }
3727e4b17023SJohn Marino 
3728e4b17023SJohn Marino struct rtl_opt_pass pass_rtl_pre =
3729e4b17023SJohn Marino {
3730e4b17023SJohn Marino  {
3731e4b17023SJohn Marino   RTL_PASS,
3732e4b17023SJohn Marino   "rtl pre",                            /* name */
3733e4b17023SJohn Marino   gate_rtl_pre,                         /* gate */
3734e4b17023SJohn Marino   execute_rtl_pre,    			/* execute */
3735e4b17023SJohn Marino   NULL,                                 /* sub */
3736e4b17023SJohn Marino   NULL,                                 /* next */
3737e4b17023SJohn Marino   0,                                    /* static_pass_number */
3738e4b17023SJohn Marino   TV_PRE,                               /* tv_id */
3739e4b17023SJohn Marino   PROP_cfglayout,                       /* properties_required */
3740e4b17023SJohn Marino   0,                                    /* properties_provided */
3741e4b17023SJohn Marino   0,                                    /* properties_destroyed */
3742e4b17023SJohn Marino   0,                                    /* todo_flags_start */
3743e4b17023SJohn Marino   TODO_df_finish | TODO_verify_rtl_sharing |
3744e4b17023SJohn Marino   TODO_verify_flow | TODO_ggc_collect   /* todo_flags_finish */
3745e4b17023SJohn Marino  }
3746e4b17023SJohn Marino };
3747e4b17023SJohn Marino 
3748e4b17023SJohn Marino struct rtl_opt_pass pass_rtl_hoist =
3749e4b17023SJohn Marino {
3750e4b17023SJohn Marino  {
3751e4b17023SJohn Marino   RTL_PASS,
3752e4b17023SJohn Marino   "hoist",                              /* name */
3753e4b17023SJohn Marino   gate_rtl_hoist,                       /* gate */
3754e4b17023SJohn Marino   execute_rtl_hoist,  			/* execute */
3755e4b17023SJohn Marino   NULL,                                 /* sub */
3756e4b17023SJohn Marino   NULL,                                 /* next */
3757e4b17023SJohn Marino   0,                                    /* static_pass_number */
3758e4b17023SJohn Marino   TV_HOIST,                             /* tv_id */
3759e4b17023SJohn Marino   PROP_cfglayout,                       /* properties_required */
3760e4b17023SJohn Marino   0,                                    /* properties_provided */
3761e4b17023SJohn Marino   0,                                    /* properties_destroyed */
3762e4b17023SJohn Marino   0,                                    /* todo_flags_start */
3763e4b17023SJohn Marino   TODO_df_finish | TODO_verify_rtl_sharing |
3764e4b17023SJohn Marino   TODO_verify_flow | TODO_ggc_collect   /* todo_flags_finish */
3765e4b17023SJohn Marino  }
3766e4b17023SJohn Marino };
3767e4b17023SJohn Marino 
3768e4b17023SJohn Marino #include "gt-gcse.h"
3769