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 = ®_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 = ®_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